Index: trunk/tools/FlairGCS/CMakeLists.txt
===================================================================
--- trunk/tools/FlairGCS/CMakeLists.txt	(revision 9)
+++ trunk/tools/FlairGCS/CMakeLists.txt	(revision 9)
@@ -0,0 +1,106 @@
+PROJECT(FlairGCS)
+cmake_minimum_required(VERSION 2.8)
+include($ENV{FLAIR_ROOT}/flair-dev/cmake-modules/GlobalCmakeFlair.cmake)
+
+SET(PROJECT_SOURCE_FILES
+	src/Manager.cpp
+	src/ConnectionLayout.cpp
+	src/main.cpp
+	src/UdtSocket.cpp
+	src/Scope.cpp
+	src/ScopeFixedStep.cpp
+	src/ScopeVariableStep.cpp
+	src/DataPlot1D.cpp
+	src/DataPlot2D.cpp
+	src/RangeFinderPlot.cpp
+	src/Picture.cpp
+	src/DataRemote.cpp
+	src/Scrollbar.cpp
+	src/file_ui.cpp
+	src/FormLayout.cpp
+	src/Vector3DSpinBox.cpp
+	src/DoubleSpinBox.cpp
+	src/SpinBox.cpp
+	src/CheckBox.cpp
+	src/ComboBox.cpp
+	src/Tab.cpp
+	src/TabWidget.cpp
+	src/GroupBox.cpp
+	src/GridLayout.cpp
+	src/Layout.cpp
+	src/PushButton.cpp
+	src/TextEdit.cpp
+	src/Label.cpp
+	src/Map.cpp
+	src/mapwidget.cpp
+	src/Landmark.cpp
+	src/XmlWidget.cpp
+)
+
+SET(FILES_TO_MOC
+	src/UdtSocket.h
+	src/RangeFinderPlot.h
+	src/Scope.h
+	src/DataPlot2D.h
+	src/Picture.h
+	src/Scrollbar.h
+	src/Manager.h
+	src/file_ui.h
+	src/Vector3DSpinBox.h
+	src/DoubleSpinBox.h
+	src/SpinBox.h
+	src/CheckBox.h
+	src/ComboBox.h
+	src/PushButton.h
+	src/mapwidget.h
+	src/Map.h
+	src/XmlWidget.h
+	src/ConnectionLayout.h
+)
+
+FIND_PACKAGE(Qt4 REQUIRED)
+SET(QT_USE_QTGUI TRUE)
+SET(QT_USE_QTMAIN TRUE)
+SET(QT_USE_QTXML TRUE)
+SET(QT_USE_QTNETWORK TRUE)
+INCLUDE(${QT_USE_FILE})
+
+QT4_WRAP_CPP(MOC_SOURCES ${FILES_TO_MOC})
+
+# generate rules for building source files from the resources
+QT4_ADD_RESOURCES(RCC_SOURCES "src/ressources.qrc")
+
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+ADD_DEFINITIONS(-DQT_THREAD_SUPPORT -DQT_NO_DEBUG)
+
+include_directories(
+	${CMAKE_SOURCE_DIR}/src
+	${CMAKE_SOURCE_DIR}/../../lib/FlairCore/src/unexported
+	${QT_INCLUDE_DIR}
+	${CMAKE_SYSROOT}/usr/include/udt
+	${CMAKE_SYSROOT}/usr/include/qwt
+	${CMAKE_SYSROOT}/usr/include/qt4/QtMobility
+	${CMAKE_SYSROOT}/usr/include/qt4/QtLocation
+)
+
+LINK_DIRECTORIES (
+	${QT_LIBRARY_DIR}
+)
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${PROJECT_SOURCE_FILES} ${MOC_SOURCES} ${RCC_SOURCES})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${QT_LIBRARIES} qwt udt QtLocation FileLib z)
+
+INSTALL(
+	TARGETS ${PROJECT_NAME}
+	RUNTIME DESTINATION $ENV{FLAIR_ROOT}/flair-bin/tools/${ARCH_DIR}
+)
+
+add_custom_target(
+	svn_rev
+	COMMAND $ENV{FLAIR_ROOT}/flair-dev/scripts/svn_revision.sh $ENV{FLAIR_ROOT}/flair-src ${CMAKE_CURRENT_SOURCE_DIR}/src/svnversion.h
+)
+
+add_dependencies(${PROJECT_NAME} svn_rev)
+
+
+SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
Index: trunk/tools/FlairGCS/cmake_codeblocks.sh
===================================================================
--- trunk/tools/FlairGCS/cmake_codeblocks.sh	(revision 9)
+++ trunk/tools/FlairGCS/cmake_codeblocks.sh	(revision 9)
@@ -0,0 +1,26 @@
+DIR=build_$(uname -m)
+
+#verifie l'existence du lien symbolique build
+if [ -d build ];then
+	if ! readlink build > /dev/null ; then
+		#it is a directory, exit to do not erase anything
+		err "Error: build already exsits and is a directory; it should be a symlink."
+		exit 1
+	fi
+	if ! readlink build | grep -w $DIR >/dev/null; then
+		echo "Warnink, build was pointing to another directory."
+	fi
+	rm build
+fi
+
+#creation du repertoire
+mkdir -p $DIR
+#creation du lien symbolique
+ln -s $DIR build
+
+#creation project x86
+cd build
+
+rm -f CMakeCache.txt
+rm -rf CMakeFiles
+cmake ../ -G "CodeBlocks - Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=${OECORE_CMAKE_HOST_TOOLCHAIN}
Index: trunk/tools/FlairGCS/cmake_mingw.bat
===================================================================
--- trunk/tools/FlairGCS/cmake_mingw.bat	(revision 9)
+++ trunk/tools/FlairGCS/cmake_mingw.bat	(revision 9)
@@ -0,0 +1,3 @@
+mkdir build_win32
+cd build_win32
+cmake ../ -G "CodeBlocks - MinGW Makefiles"
Index: trunk/tools/FlairGCS/src/CheckBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/CheckBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/CheckBox.cpp	(revision 9)
@@ -0,0 +1,86 @@
+#include "CheckBox.h"
+#include "Layout.h"
+#include <QCheckBox>
+#include <QFormLayout>
+
+CheckBox::CheckBox(Layout* parent,int row, int col,QString name,bool value): FormLayout(parent,row,col,name,"CheckBox")
+{
+    checkbox = new QCheckBox();
+    checkbox->setChecked(value);
+
+    checkbox_value=value;
+
+    object_layout->addRow(name,checkbox);
+
+    connect(checkbox,SIGNAL(toggled(bool)),this, SLOT(valuechanged(bool)));
+
+    if(checkbox_value==true)
+    {
+        SetValue("1");
+    }
+    else
+    {
+        SetValue("0");
+    }
+}
+
+CheckBox::~CheckBox()
+{
+    delete checkbox;
+}
+
+void CheckBox::SetUptodate(void)
+{
+    ui_to_var();
+    ui_to_xml();
+    visible_widget->setPalette(black_pal);
+}
+
+void CheckBox::ui_to_var(void)
+{
+    checkbox_value=checkbox->isChecked();
+}
+
+void CheckBox::ui_to_xml(void)
+{
+    if(checkbox->isChecked()==true)
+    {
+        SetValue("1");
+    }
+    else
+    {
+        SetValue("0");
+    }
+}
+
+void CheckBox::Reset(void)
+{
+    checkbox->setChecked(checkbox_value);
+}
+
+void CheckBox::LoadEvent(QDomElement dom)
+{
+    if(checkbox->isEnabled()==true)
+    {
+        if(dom.attribute("value")==QString("1"))
+        {
+            checkbox->setChecked(true);
+        }
+        else
+        {
+            checkbox->setChecked(false);
+        }
+    }
+}
+
+void CheckBox::valuechanged(bool value)
+{
+    if(value!=checkbox_value)
+    {
+        visible_widget->setPalette(red_pal);
+    }
+    else
+    {
+        visible_widget->setPalette(black_pal);
+    }
+}
Index: trunk/tools/FlairGCS/src/CheckBox.h
===================================================================
--- trunk/tools/FlairGCS/src/CheckBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/CheckBox.h	(revision 9)
@@ -0,0 +1,32 @@
+#ifndef CHECKBOX_H
+#define CHECKBOX_H
+
+#include "FormLayout.h"
+
+class Layout;
+class QCheckBox;
+
+class CheckBox: public FormLayout
+{
+    Q_OBJECT
+
+    public:
+        CheckBox(Layout* parent,int row, int col,QString name,bool value);
+        ~CheckBox();
+
+
+    private:
+        QCheckBox* checkbox;
+        bool checkbox_value;
+        void SetUptodate(void);
+        void Reset(void);
+        void LoadEvent(QDomElement dom);
+
+        void ui_to_var(void);
+        void ui_to_xml(void);
+
+    private slots:
+        void valuechanged(bool value);
+};
+
+#endif // CHECKBOX_H
Index: trunk/tools/FlairGCS/src/ComboBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/ComboBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/ComboBox.cpp	(revision 9)
@@ -0,0 +1,78 @@
+#include "ComboBox.h"
+#include "Layout.h"
+#include <QComboBox>
+#include <QFormLayout>
+
+ComboBox::ComboBox(Layout* parent,int row, int col,QString name,int value): FormLayout(parent,row,col,name,"ComboBox")
+{
+    combobox = new QComboBox();
+    combobox->setCurrentIndex(value);
+
+    combobox_value=value;
+
+    object_layout->addRow(name,combobox);
+
+    connect(combobox,SIGNAL(currentIndexChanged(int)),this, SLOT(valuechanged(int)));
+
+    SetValue(QString::number(combobox_value));
+
+    //pour ne pas faire de doublons qd on ajoute des items
+    SetIsExpandable(true);
+}
+
+ComboBox::~ComboBox()
+{
+    delete combobox;
+}
+
+void ComboBox::XmlEvent(QDomElement dom)
+{
+     if(dom.attribute("item")!="") {
+        QString item=dom.attribute("item");
+        combobox->addItem(item);
+        combobox->setCurrentIndex(combobox_value);
+    }
+}
+
+void ComboBox::SetUptodate(void)
+{
+    ui_to_var();
+    ui_to_xml();
+    visible_widget->setPalette(black_pal);
+
+}
+
+void ComboBox::ui_to_var(void)
+{
+    combobox_value=combobox->currentIndex();
+}
+
+void ComboBox::ui_to_xml(void)
+{
+    SetValue(QString::number(combobox->currentIndex()));
+}
+
+void ComboBox::Reset(void)
+{
+    combobox->setCurrentIndex(combobox_value);
+}
+
+void ComboBox::LoadEvent(QDomElement dom)
+{
+    if(combobox->isEnabled()==true)
+    {
+        combobox->setCurrentIndex((dom.attribute("value")).toInt());
+    }
+}
+
+void ComboBox::valuechanged(int value)
+{
+    if(value!=combobox_value)
+    {
+        visible_widget->setPalette(red_pal);
+    }
+    else
+    {
+        visible_widget->setPalette(black_pal);
+    }
+}
Index: trunk/tools/FlairGCS/src/ComboBox.h
===================================================================
--- trunk/tools/FlairGCS/src/ComboBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/ComboBox.h	(revision 9)
@@ -0,0 +1,32 @@
+#ifndef COMBOBOX_H
+#define COMBOBOX_H
+
+#include "FormLayout.h"
+
+class QComboBox;
+class Layout;
+
+class ComboBox: public FormLayout
+{
+    Q_OBJECT
+
+    public:
+        ComboBox(Layout* parent,int row, int col,QString name,int value);
+        ~ComboBox();
+
+    private:
+        QComboBox* combobox;
+        int combobox_value;
+        void XmlEvent(QDomElement dom);
+        void SetUptodate(void);
+        void Reset(void);
+        void LoadEvent(QDomElement dom);
+
+        void ui_to_var(void);
+        void ui_to_xml(void);
+
+    private slots:
+        void valuechanged(int value);
+};
+
+#endif // COMBOBOX_H
Index: trunk/tools/FlairGCS/src/ConnectionLayout.cpp
===================================================================
--- trunk/tools/FlairGCS/src/ConnectionLayout.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/ConnectionLayout.cpp	(revision 9)
@@ -0,0 +1,171 @@
+#include "ConnectionLayout.h"
+#include "UdtSocket.h"
+#include "DataRemote.h"
+#include <qendian.h>
+#include "communication.h"
+#include <zlib.h>
+#include <assert.h>
+
+#define COMPRESS_CHUNK 1024
+
+
+ConnectionLayout::ConnectionLayout(UdtSocket* socket,QString name): Layout(NULL,name,"root") {
+    isRemoteNameDefined=false;
+    this->socket=socket;
+}
+
+ConnectionLayout::~ConnectionLayout() {
+}
+
+void ConnectionLayout::receive(char* buf,int size) {
+    //printf("trame %x\n",buf[0]);
+    //for(int i=0; i<size;i++) printf("%x ",buf[i]);
+    //printf("\n");
+    switch(buf[0]) {
+        case ZLIB_HEADER: {
+            ssize_t out_size;
+            char* uncompressbuf;
+            uncompressBuffer(buf,size,&uncompressbuf,&out_size);
+            handleUncompressedFrame(uncompressbuf,out_size);
+            free(uncompressbuf);
+            break;
+        }
+        default:
+            handleUncompressedFrame(buf,size);
+    }
+    free(buf);
+}
+
+void ConnectionLayout::XmlToSend(QDomDocument doc) {
+    //printf("xml to send\n%s\n",doc.toString().toLocal8Bit().constData());
+//xml to send a mettre dans le manager
+    QMetaObject::invokeMethod(socket,
+                              "write",
+                              Qt::BlockingQueuedConnection,
+                              Q_ARG(const char*,doc.toString().toLocal8Bit().constData()),
+                              Q_ARG(qint64,doc.toString().toLocal8Bit().length()));
+
+}
+
+void ConnectionLayout::LoadXml(QDomDocument to_parse) {
+    if(!isRemoteNameDefined) {
+        printf("load xml: name not defined!\n");
+        return;
+    }
+
+    QDomElement tmp=to_parse.firstChildElement("root");
+    while(tmp.attribute("name")!=remoteName && !tmp.isNull()) tmp=to_parse.nextSiblingElement("root");
+
+    if(!tmp.isNull()) {
+        XmlWidget::LoadXml(tmp);
+    } else {
+        printf("%s not found in xml file \n",remoteName.toLocal8Bit().constData());
+    }
+}
+
+void ConnectionLayout::handleUncompressedFrame(char *buf,ssize_t size) {
+    switch((unsigned char)buf[0]) {
+        case XML_HEADER: {
+            QString xml;
+            QDomDocument doc;
+            xml=QString((char*)buf);
+            xml.resize(size);
+
+            //printf("recu %i\n%s\n",size,xml.toLocal8Bit().constData());
+            if(!doc.setContent(xml)) {
+                printf("prob setContent fichier\n");
+            }
+
+            if(!isRemoteNameDefined) {
+                isRemoteNameDefined=true;
+                remoteName=doc.firstChildElement("root").attribute("name");
+                setRemoteName(remoteName);
+                SetAttribute("name",remoteName);
+            }
+
+            ParseXml(doc.firstChildElement("root").firstChildElement());
+            break;
+        }
+        case DATAS_BIG_ENDIAN: {
+            //for(int i=0;i<size;i++) printf("%x ",buf[i]);
+            //printf("\n");
+            uint16_t period;
+            memcpy(&period,&buf[1],sizeof(uint16_t));
+            period=qFromBigEndian(period);
+            drawDatas(&buf[3],size-3,period,true);
+            break;
+        }
+        case DATAS_LITTLE_ENDIAN: {
+            //for(int i=0;i<size;i++) printf("%x ",buf[i]);
+            //printf("\n");
+            uint16_t period;
+            memcpy(&period,&buf[1],sizeof(uint16_t));
+            //printf("recu %i period %i\n",size,period);
+            drawDatas(&buf[3],size-3,period);
+            break;
+        }
+        default:
+            printf("trame non supportée %x\n",buf[0]);
+    }
+}
+
+void ConnectionLayout::removeDataRemote(DataRemote* data) {
+    dataremotes.removeOne(data);
+}
+
+void ConnectionLayout::addDataRemote(DataRemote* data) {
+    dataremotes.append(data);
+}
+
+QString ConnectionLayout::getRemoteName() {
+    return remoteName;
+}
+void ConnectionLayout::drawDatas(char* buf,int buf_size,uint16_t period,bool big_endian) {
+    for(int i=0;i<dataremotes.count();i++) {
+        dataremotes.at(i)->BufEvent(&buf,&buf_size,period,big_endian);
+    }
+}
+
+int ConnectionLayout::uncompressBuffer(char *in, ssize_t in_size,char **out,ssize_t *out_size) {
+    int ret;
+    unsigned have;
+    z_stream strm;
+
+    // allocate inflate state
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&strm);
+    if (ret != Z_OK)
+        return ret;
+
+    *out=(char*)malloc(COMPRESS_CHUNK);
+    if(!(*out))
+        return Z_BUF_ERROR;
+
+    strm.avail_in = in_size;
+    strm.next_in = (unsigned char*)in;
+    strm.avail_out = COMPRESS_CHUNK;
+    strm.next_out = (unsigned char*)*out;
+
+    ret = inflate(&strm, Z_NO_FLUSH);
+    assert(ret != Z_STREAM_ERROR);  // state not clobbered
+    switch (ret) {
+    case Z_NEED_DICT:
+        ret = Z_DATA_ERROR;     // and fall through
+    case Z_DATA_ERROR:
+    case Z_MEM_ERROR:
+        (void)inflateEnd(&strm);
+        return ret;
+    }
+    have = COMPRESS_CHUNK- strm.avail_out;
+    *out_size=have;
+
+    //printf("%i -> %i\n",in_size,have);
+    //printf("%s\n",*out);
+    // clean up and return
+    (void)inflateEnd(&strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
Index: trunk/tools/FlairGCS/src/ConnectionLayout.h
===================================================================
--- trunk/tools/FlairGCS/src/ConnectionLayout.h	(revision 9)
+++ trunk/tools/FlairGCS/src/ConnectionLayout.h	(revision 9)
@@ -0,0 +1,38 @@
+#ifndef CONNECTIONLAYOUT_H
+#define CONNECTIONLAYOUT_H
+
+#include "Layout.h"
+
+class UdtSocket;
+class DataRemote;
+
+class ConnectionLayout:  public Layout
+{
+    Q_OBJECT
+
+    public:
+        ConnectionLayout(UdtSocket* socket,QString name);
+        ~ConnectionLayout();
+        void XmlToSend(QDomDocument doc);
+        void addDataRemote(DataRemote* data);
+        void removeDataRemote(DataRemote* data);
+        void LoadXml(QDomDocument to_parse);
+        QString getRemoteName();
+
+    private:
+        static int uncompressBuffer(char *in, ssize_t in_size,char **out,ssize_t *out_size);
+        void handleUncompressedFrame(char *buf,ssize_t size);
+        void drawDatas(char* buf,int buf_size,uint16_t period,bool big_endian=false);
+        bool isRemoteNameDefined;
+        QString remoteName;
+        UdtSocket* socket;
+        QList<DataRemote*> dataremotes;
+
+    private slots:
+        void receive(char* buf,int  size);
+
+    signals:
+        void setRemoteName(QString name);
+};
+
+#endif // CONNECTIONLAYOUT_H
Index: trunk/tools/FlairGCS/src/DataPlot1D.cpp
===================================================================
--- trunk/tools/FlairGCS/src/DataPlot1D.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/DataPlot1D.cpp	(revision 9)
@@ -0,0 +1,116 @@
+#include "DataPlot1D.h"
+#include "Layout.h"
+#include <QMouseEvent>
+#include <QMenu>
+#include <QGridLayout>
+#include <qendian.h>
+
+DataPlot1D::DataPlot1D(Layout* parent,int row, int col,QString title,float ymin, float ymax,bool enabled,int period):
+    ScopeFixedStep(title,ymin,ymax,period/1000.),DataRemote(title,"DataPlot1D",parent,enabled,period) {
+
+    setEnabled(enabled);
+    parent->addWidget(this,row,col);
+    visible_widget=this;
+}
+
+DataPlot1D::~DataPlot1D() {
+    visible_widget=NULL;//because otherwise xmlwidget will delete it
+}
+
+void DataPlot1D::XmlEvent(QDomElement dom) {
+    if(dom.attribute("curve")!="") {
+        QString type=dom.attribute("type");
+        int r=dom.attribute("r").toInt();
+        int g=dom.attribute("g").toInt();
+        int b=dom.attribute("b").toInt();
+        QString name=dom.attribute("curve");
+        addCurve(QPen(QColor(r,g,b,255)),name);
+        datas_type.append(type);
+        if(type=="float") {
+            receivesize+=sizeof(float);
+        } else if(type=="int8_t") {
+            receivesize+=sizeof(int8_t);
+        } else if(type=="int16_t") {
+            receivesize+=sizeof(int16_t);
+        } else {
+            printf("MyDataPlot1D::addCurve unknown type %s\n",type.toLocal8Bit().constData());
+        }
+    } else {
+        XmlSetup(dom);
+    }
+}
+
+bool DataPlot1D::eventFilter(QObject *o, QEvent *e) {
+    if (  o == canvas() ) {
+        switch(e->type()) {
+            case QEvent::Resize: {
+                //resolution bug taille widgets:
+                setMaximumHeight(parentWidget()->height()/((QGridLayout*)(parentWidget()->layout()))->rowCount());
+                break;
+            }
+            case QEvent::MouseButtonPress: {
+                return mouseEvent((QMouseEvent*)e);
+            }
+
+            default:
+                break;
+        }
+    }
+    return Scope::eventFilter(o, e);
+}
+
+void DataPlot1D::BufEvent(char **buf,int *buf_size,uint16_t period,bool big_endian)
+{
+    setEnabled(IsEnabled());
+    if(IsEnabled()==false || RefreshRate_ms()!=period) return;
+    double* datas=(double*)malloc(datas_type.count()*sizeof(double));
+
+    for(int i=0;i<datas_type.count();i++) {
+        if(datas_type.at(i)=="float") {
+            uint32_t data_raw;
+            float* data=(float*)&data_raw;
+            memcpy((void*)&data_raw,*buf,sizeof(uint32_t));
+            *buf+=sizeof(uint32_t);
+            if(big_endian==true) data_raw=qFromBigEndian(data_raw);
+            datas[i]=*data;
+        } else if(datas_type.at(i)=="int8_t") {
+            int8_t data;
+            memcpy((void*)&data,*buf,sizeof(data));
+            *buf+=sizeof(data);
+            datas[i]=data;
+        } else if(datas_type.at(i)=="int16_t") {
+            int16_t data;
+            memcpy((void*)&data,*buf,sizeof(data));
+            *buf+=sizeof(data);
+            if(big_endian==true) data=qFromBigEndian(data);
+            datas[i]=data;
+        } else {
+            printf("DataPlot1D::BufEvent unknown type %s\n",datas_type.at(i).toLocal8Bit().constData());
+        }
+    }
+
+    step_s=period/1000.;
+    plot(datas);
+}
+
+//context menu
+bool DataPlot1D::mouseEvent(QMouseEvent *event) {
+    if (event->button() == Qt::RightButton) {
+        QMenu *menu = new QMenu("nom", (QwtPlot*)this);
+        QAction *a,*b,*z;
+
+        a=menu->addAction("reset time view");
+        b=menu->addAction("reset y view");
+        menu->addSeparator();
+
+        appendmenu(menu);
+        z=execmenu((QwtPlot*)this,menu,event->globalPos());
+        delete menu;
+
+        if(z==a) resetXView();
+        if(z==b) resetYView();
+
+        return true;
+    }
+    return false;
+}
Index: trunk/tools/FlairGCS/src/DataPlot1D.h
===================================================================
--- trunk/tools/FlairGCS/src/DataPlot1D.h	(revision 9)
+++ trunk/tools/FlairGCS/src/DataPlot1D.h	(revision 9)
@@ -0,0 +1,27 @@
+#ifndef DATAPLOT1D_H_INCLUDED
+#define DATAPLOT1D_H_INCLUDED
+
+#include "ScopeFixedStep.h"
+#include "DataRemote.h"
+
+
+class Layout;
+class QMouseEvent;
+
+class DataPlot1D :  public ScopeFixedStep,public DataRemote
+{
+    public:
+        DataPlot1D(Layout* parent,int row, int col,QString title,float ymin, float ymax,bool enabled,int period);
+        ~DataPlot1D();
+
+    private:
+        void XmlEvent(QDomElement dom);
+        bool eventFilter(QObject *, QEvent *);
+        void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian);
+        bool mouseEvent(QMouseEvent *event);
+        QList<QString> datas_type;
+
+};
+
+
+#endif // DATAPLOT1D_H_INCLUDED
Index: trunk/tools/FlairGCS/src/DataPlot2D.cpp
===================================================================
--- trunk/tools/FlairGCS/src/DataPlot2D.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/DataPlot2D.cpp	(revision 9)
@@ -0,0 +1,393 @@
+#include "DataPlot2D.h"
+#include "Layout.h"
+#include <qwt_plot.h>
+#include <qwt_plot_curve.h>
+#include <qwt_plot_grid.h>
+#include <qwt_plot_magnifier.h>
+#include <qwt_plot_canvas.h>
+#include <qwt_scale_widget.h>
+#include <qwt_legend_label.h>
+#include <qwt_legend.h>
+#include <qwt_plot_panner.h>
+#include <qwt_plot_rescaler.h>
+#include <QMouseEvent>
+#include <QMenu>
+#include <QInputDialog>
+#include <qendian.h>
+
+DataPlot2D::DataPlot2D(Layout* parent,int row, int col,QString plot_name,QString x_name,QString y_name,float xmin, float xmax,float ymin, float ymax,bool enabled,int period):
+    DataRemote(plot_name,"DataPlot2D",parent,enabled,period)
+{
+    plot=new QwtPlot(NULL);
+    plot->setEnabled(enabled);
+
+    parent->addWidget(plot,row,col);
+    visible_widget=plot;
+
+    view_size=20;//default 20s
+/*
+    // Disable polygon clipping
+    QwtPainter::setDeviceClipping(false);
+
+    // We don't need the cache here
+    plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
+    plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
+*/
+#if QT_VERSION >= 0x040000
+#ifdef Q_WS_X11
+    /*
+       Qt::WA_PaintOnScreen is only supported for X11, but leads
+       to substantial bugs with Qt 4.2.x/Windows
+     */
+    plot->canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
+#endif
+#endif
+
+    alignScales();
+
+    //d_x=new QList<double*>;
+    //d_y=new QList<double*>;
+    datas=new QList<QwtPlotCurve*>;
+    datas_type=new QList<QString>;
+
+    // Assign a title
+    plot->setTitle(plot_name);
+
+    // Axis
+    plot->setAxisTitle(QwtPlot::xBottom, x_name);
+    setXAxisScale(xmin,xmax);
+
+    plot->setAxisTitle(QwtPlot::yLeft, y_name);
+    setYAxisScale(ymin,ymax);
+
+    QwtPlotRescaler* rescaler = new QwtPlotRescaler( plot->canvas() );
+    rescaler->setRescalePolicy( QwtPlotRescaler::Fixed );/*
+    rescaler->setReferenceAxis(QwtPlot::xBottom);
+    rescaler->setAspectRatio(QwtPlot::yLeft, 1.0);*/
+
+    // grid
+    QwtPlotGrid *grid = new QwtPlotGrid;
+    //grid->enableXMin(false);
+    grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
+    //grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine));
+    grid->attach(plot);
+
+    //zoomer
+    QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(plot->canvas());
+    zoomer->setMouseButton(Qt::RightButton,Qt::ControlModifier);
+
+    //scroller
+    QwtPlotPanner *scroller =new QwtPlotPanner(plot->canvas());
+
+    //legend
+    QwtLegend* new_legend=new QwtLegend();
+    new_legend->setDefaultItemMode(QwtLegendData::Checkable);
+    plot->insertLegend(new_legend, QwtPlot::BottomLegend);
+
+    connect( new_legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( legendChecked( const QVariant &, bool ) ) );
+
+    plot->canvas()->installEventFilter(this);
+}
+
+DataPlot2D::~DataPlot2D()
+{
+    for(int i=0;i<d_x.count();i++)
+    {
+        free(d_x.at(i));
+        free(d_y.at(i));
+    }
+
+    delete datas;
+    delete datas_type;
+}
+
+void DataPlot2D::XmlEvent(QDomElement dom)
+{
+    if(dom.attribute("curve")!="") {
+        QString type=dom.attribute("type");
+        int r=dom.attribute("r").toInt();
+        int g=dom.attribute("g").toInt();
+        int b=dom.attribute("b").toInt();
+        QString name=dom.attribute("curve");
+        addCurve(QPen(QColor(r,g,b,255)),name,type);
+    } else {
+        XmlSetup(dom);
+    }
+}
+
+bool DataPlot2D::eventFilter(QObject *o, QEvent *e)
+{
+    if (  o == plot->canvas() )
+    {
+        switch(e->type())
+        {
+            case QEvent::MouseButtonPress:
+            {
+                mousePressEvent((QMouseEvent*)e);
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+    return plot->eventFilter(o, e);
+}
+
+void DataPlot2D::legendChecked( const QVariant &itemInfo, bool on )
+{
+    QwtPlotItem *plotItem = plot->infoToItem( itemInfo );
+    if ( plotItem )
+        showCurve( plotItem, on );
+}
+
+void DataPlot2D::showCurve(QwtPlotItem *item, bool on)
+{
+    item->setVisible(on);
+
+    QwtLegend *lgd = qobject_cast<QwtLegend *>( plot->legend() );
+
+    QList<QWidget *> legendWidgets =
+        lgd->legendWidgets( plot->itemToInfo( item ) );
+
+    if ( legendWidgets.size() == 1 )
+    {
+        QwtLegendLabel *legendLabel =
+            qobject_cast<QwtLegendLabel *>( legendWidgets[0] );
+
+        if ( legendLabel )
+            legendLabel->setChecked( on );
+    }
+
+    plot->replot();
+}
+
+void DataPlot2D::addCurve(QPen pen,QString legend,QString type)
+{
+    double* new_dx;
+    new_dx=(double*)malloc(view_size/refresh_rate*sizeof(double));
+    d_x.append(new_dx);
+    double* new_dy;
+    new_dy=(double*)malloc(view_size/refresh_rate*sizeof(double));
+    d_y.append(new_dy);
+
+    //  Initialize data
+    for (int i = 0; i< view_size/refresh_rate; i++) new_dx[i] = 0;
+    for (int i = 0; i< view_size/refresh_rate; i++) new_dy[i] = 0;
+
+    // Insert new curve
+    QwtPlotCurve* new_data;
+
+    new_data = new QwtPlotCurve(legend);
+    new_data->attach(plot);
+    new_data->setPen(pen);
+    datas->append(new_data);
+
+    showCurve(new_data, true);
+
+    datas_type->append(type);
+    bool tmp=true;
+    datas_first_update.append(tmp);
+
+    // Attach (don't copy) data. Both curves use the same x array.
+    new_data->setRawSamples(new_dx, new_dy, view_size/refresh_rate);
+
+    if(type=="float")
+    {
+        receivesize+=sizeof(float);
+    }
+    else if(type=="int8_t")
+    {
+        receivesize+=sizeof(int8_t);
+    }
+    else if(type=="int16_t")
+    {
+        receivesize+=sizeof(int16_t);
+    }
+    else
+    {
+        printf("DataPlot2D::addCurve unknown type %s\n",type.toLocal8Bit().constData());
+    }
+
+}
+
+void DataPlot2D::setXAxisScale(float xmin,float xmax)
+{
+    xmin_orig=xmin;
+    xmax_orig=xmax;
+    plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
+
+}
+
+void DataPlot2D::setYAxisScale(float ymin,float ymax)
+{
+    ymin_orig=ymin;
+    ymax_orig=ymax;
+    plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
+}
+
+//
+//  Set a plain canvas frame and align the scales to it
+//
+void DataPlot2D::alignScales(void)
+{
+    // The code below shows how to align the scales to
+    // the canvas frame, but is also a good example demonstrating
+    // why the spreaded API needs polishing.
+/*
+    plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
+    plot->canvas()->setLineWidth(1);
+*/
+    for ( int i = 0; i < QwtPlot::axisCnt; i++ )
+    {
+        QwtScaleWidget *scaleWidget = (QwtScaleWidget *)plot->axisWidget(i);
+        if ( scaleWidget )
+            scaleWidget->setMargin(0);
+
+        QwtScaleDraw *scaleDraw = (QwtScaleDraw *)plot->axisScaleDraw(i);
+        if ( scaleDraw )
+            scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
+    }
+}
+
+void DataPlot2D::BufEvent(char **buf,int *buf_size,uint16_t period,bool big_endian)
+{
+    plot->setEnabled(IsEnabled());
+    if(IsEnabled()==false || RefreshRate_ms()!=period) return;
+
+    for(int i=0;i<datas->count();i++)
+    {
+        if(datas_type->at(i)=="float")
+        {
+            uint32_t data1_raw;
+            float* data1=(float*)&data1_raw;
+            uint32_t data2_raw;
+            float* data2=(float*)&data2_raw;
+
+            memcpy((void*)&data1_raw,*buf,sizeof(uint32_t));
+            *buf+=sizeof(uint32_t);
+            memcpy((void*)&data2_raw,*buf,sizeof(uint32_t));
+            *buf+=sizeof(uint32_t);
+            if(big_endian==true) data1_raw=qFromBigEndian(data1_raw);
+            if(big_endian==true) data2_raw=qFromBigEndian(data2_raw);
+            plot_data(*data1,*data2,i);
+        }
+        else if(datas_type->at(i)=="int8_t")
+        {
+            int8_t data1,data2;
+            memcpy((void*)&data1,*buf,sizeof(data1));
+            *buf+=sizeof(data1);
+            memcpy((void*)&data2,*buf,sizeof(data2));
+            *buf+=sizeof(data2);
+            plot_data(data1,data2,i);
+        }
+        else if(datas_type->at(i)=="int16_t")
+        {
+            int16_t data1,data2;
+            memcpy((void*)&data1,*buf,sizeof(data1));
+            *buf+=sizeof(data1);
+            memcpy((void*)&data2,*buf,sizeof(data2));
+            *buf+=sizeof(data2);
+            plot_data(data1,data2,i);
+        }
+        else
+        {
+            printf("DataPlot1D::DrawDatas type non connu\n");
+        }
+    }
+
+    plot->replot();
+}
+
+void DataPlot2D::plot_data(double data_x,double data_y,int index)
+{
+    if(index<d_y.count())
+    {
+        if(datas_first_update.at(index)==false)
+        {
+            // Shift y array left and assign new value to y[view_size/refresh_rate - 1].
+            for ( int j = 0; j < view_size/refresh_rate - 1; j++ ) d_y.at(index)[j] = d_y.at(index)[j+1] ;
+            for ( int j = 0; j < view_size/refresh_rate - 1; j++ ) d_x.at(index)[j] = d_x.at(index)[j+1] ;
+            d_y.at(index)[(int)(view_size/refresh_rate) - 1] = data_y;
+            d_x.at(index)[(int)(view_size/refresh_rate) - 1] = data_x;
+        }
+        else
+        {
+            for ( int j = 0; j <= view_size/refresh_rate - 1; j++ ) d_y.at(index)[j] = data_y;
+            for ( int j = 0; j <= view_size/refresh_rate - 1; j++ ) d_x.at(index)[j] = data_x;
+            datas_first_update[index]=false;
+        }
+    }
+}
+
+
+//context menu
+void DataPlot2D::mousePressEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::RightButton)
+    {
+
+        QMenu * menu = new QMenu("nom", plot);
+        // ajout des actions
+        QAction *a,*z,*d;
+
+        a=menu->addAction("reset zoom");
+        menu->addSeparator();
+
+        d=menu->addAction(QString("set view size (%1s)").arg(view_size));
+
+        appendmenu(menu);
+        z=execmenu(plot,menu,event->globalPos());
+        delete menu;
+
+        if(z==a)
+        {
+            //zoom to original size
+            plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
+            plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
+        }
+
+        if(z==d)
+        {
+            bool ok;
+            float time = QInputDialog::getInt(plot, QString("Set view size (%1)").arg(plot->title().text()),tr("Value (s):"), view_size, 1, 65535, 10, &ok);
+            if(ok==true)
+            {
+                for(int i=0;i<datas->count();i++)
+                {
+                    if(time>view_size)
+                    {
+                        double* buf=(double*)malloc(time/refresh_rate*sizeof(double));
+                        d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double));
+                        memcpy(buf,d_x[i],(view_size/refresh_rate)*sizeof(double));
+                        memcpy(&d_x[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double));
+                        d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double));
+                        memcpy(buf,d_y[i],(view_size/refresh_rate)*sizeof(double));
+                        memcpy(&d_y[i][(int)(time/refresh_rate)-(int)(view_size/refresh_rate)],buf,(view_size/refresh_rate)*sizeof(double));
+                        free(buf);
+                        for(int j=0;j<(int)(time/refresh_rate)-(int)(view_size/refresh_rate);j++)
+                        {
+                            d_x.at(i)[j]=d_x.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1];
+                            d_y.at(i)[j]=d_y.at(i)[(int)(time/refresh_rate)-(int)(view_size/refresh_rate)+1];
+                        }
+                    }
+                    else
+                    {
+                        double* buf=(double*)malloc(time/refresh_rate*sizeof(double));
+                        memcpy(buf,&d_x[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double));
+                        d_x[i]=(double*)realloc(d_x.at(i),time/refresh_rate*sizeof(double));
+                        memcpy(d_x[i],buf,(time/refresh_rate)*sizeof(double));
+                        memcpy(buf,&d_y[i][(int)(view_size/refresh_rate)-(int)(time/refresh_rate)],(time/refresh_rate)*sizeof(double));
+                        d_y[i]=(double*)realloc(d_y.at(i),time/refresh_rate*sizeof(double));
+                        memcpy(d_y[i],buf,(time/refresh_rate)*sizeof(double));
+                        free(buf);
+                    }
+                    datas->at(i)->setRawSamples(d_x.at(i), d_y.at(i), time/refresh_rate);
+
+                }
+                view_size=time;
+
+            }
+        }
+    }
+}
Index: trunk/tools/FlairGCS/src/DataPlot2D.h
===================================================================
--- trunk/tools/FlairGCS/src/DataPlot2D.h	(revision 9)
+++ trunk/tools/FlairGCS/src/DataPlot2D.h	(revision 9)
@@ -0,0 +1,51 @@
+#ifndef DATAPLOT2D_H_INCLUDED
+#define DATAPLOT2D_H_INCLUDED
+
+#include "DataRemote.h"
+#include <stdint.h>
+#include <QPen>
+
+class Layout;
+class QwtPlot;
+class QwtPlotCurve;
+class QwtPlotItem;
+class QMouseEvent;
+
+class DataPlot2D :  public DataRemote
+{
+    Q_OBJECT
+
+    public:
+        DataPlot2D(Layout* parent,int row, int col,QString plot_name,QString x_name,QString y_name,float xmin, float xmax,float ymin, float ymax,bool enabled,int period);
+        ~DataPlot2D();
+        void addCurve(QPen pen,QString legend,QString type);
+
+    protected:
+         void mousePressEvent(QMouseEvent *event);
+
+    private:
+        QwtPlot* plot;
+        void XmlEvent(QDomElement dom);
+        void alignScales(void);
+        void plot_data(double data_x,double data_y,int index);
+        float xmin_orig,xmax_orig,ymin_orig,ymax_orig;
+
+        QList<QwtPlotCurve*> *datas;
+        QList<QString> *datas_type;
+        QList<bool> datas_first_update;
+        QList<double*> d_x;
+        QList<double*> d_y;
+        double view_size;//en s
+
+        bool eventFilter(QObject *, QEvent *);
+        void setYAxisScale(float ymin,float ymax);
+        void setXAxisScale(float xmin,float xmax);
+        void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian);
+        void showCurve(QwtPlotItem *item, bool on);
+
+    private slots:
+        void legendChecked( const QVariant &itemInfo, bool on );
+};
+
+
+#endif // DATAPLOT2D_H_INCLUDED
Index: trunk/tools/FlairGCS/src/DataRemote.cpp
===================================================================
--- trunk/tools/FlairGCS/src/DataRemote.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/DataRemote.cpp	(revision 9)
@@ -0,0 +1,92 @@
+#include "DataRemote.h"
+#include <QMenu>
+#include <QInputDialog>
+#include <QtXml>
+#include "Manager.h"
+#include "ConnectionLayout.h"
+
+DataRemote::DataRemote(QString name,QString type,XmlWidget* parent,bool enabled,int period):XmlWidget(name,type,parent) {
+    auto_refresh=enabled;
+    is_logging=true;
+    receivesize=0;
+    refresh_rate=(double)period/1000.;
+
+    connectionLayout()->addDataRemote(this);
+
+    //pour ne pas faire de doublons qd on change la periode
+    SetIsExpandable(true);
+}
+
+DataRemote::~DataRemote() {
+    connectionLayout()->removeDataRemote(this);
+}
+
+void DataRemote::appendmenu(QMenu * menu) {
+    menu->addSeparator();
+
+    b=menu->addAction("auto refresh");
+    b->setCheckable(true);
+    b->setChecked(auto_refresh);
+
+    c=menu->addAction(QString("set refresh rate (%1ms)").arg((uint16_t)(qRound(refresh_rate*1000))));
+    c->setEnabled(auto_refresh);
+    menu->addSeparator();
+
+    d=menu->addAction("log");
+    d->setCheckable(true);
+    d->setChecked(is_logging);
+}
+
+QAction* DataRemote::execmenu(QWidget* parent,QMenu * menu,QPoint point) {
+    QAction *z;
+
+    z=menu->exec(point);
+
+    //auto_refresh=b->isChecked();
+
+    if(z==b) {
+        SendPeriod(RefreshRate_ms(),b->isChecked());
+    }
+
+    if(z==c) {
+        bool ok;
+        //uint16_t time = QInputDialog::getInt(this, QString("Set refresh rate (%1)").arg(title().text()),tr("Value (ms):"), (uint16_t)(qRound(refresh_rate*1000)), 1, 65535, 10, &ok);
+        uint16_t time = QInputDialog::getInt(parent, "Set refresh rate ","Value (ms):", (uint16_t)(qRound(refresh_rate*1000)), 1, 65535, 10, &ok);
+        if(ok==true && time!=qRound(refresh_rate*1000)) {
+            //refresh_rate=time/1000.;
+            SendPeriod(time,b->isChecked());
+        }
+    }
+
+    return z;
+}
+
+uint16_t DataRemote::RefreshRate_ms(void) {
+    return (uint16_t)(qRound(refresh_rate*1000.));
+}
+
+bool DataRemote::IsEnabled(void) {
+    return auto_refresh;
+}
+
+void DataRemote::SendPeriod(int period,bool auto_refresh) {
+    SetAttribute("period", period);
+    SetAttribute("enabled", auto_refresh);
+
+    connectionLayout()->XmlToSend(XmlDoc());
+
+    RemoveAttribute("period");
+    RemoveAttribute("enabled");
+}
+
+int DataRemote::ReceiveSize(void) {
+    return receivesize;
+}
+
+void DataRemote::XmlSetup(QDomElement dom) {
+    refresh_rate=dom.attribute("period").toInt()/1000.;
+    if(dom.attribute("enabled")=="1")
+        auto_refresh=true;
+    else
+        auto_refresh=false;
+}
Index: trunk/tools/FlairGCS/src/DataRemote.h
===================================================================
--- trunk/tools/FlairGCS/src/DataRemote.h	(revision 9)
+++ trunk/tools/FlairGCS/src/DataRemote.h	(revision 9)
@@ -0,0 +1,36 @@
+#ifndef DATAREMOTE_H
+#define DATAREMOTE_H
+
+#include <stdint.h>
+#include "XmlWidget.h"
+#include <QPoint>
+
+class QMenu;
+class QAction;
+
+class DataRemote: public XmlWidget
+{
+    public:
+        DataRemote(QString name,QString type,XmlWidget* parent,bool enabled,int period);
+        ~DataRemote();
+        uint16_t RefreshRate_ms(void);
+        bool IsEnabled(void);
+        int ReceiveSize(void);
+        virtual void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian)=0;
+        void appendmenu(QMenu * menu);
+        QAction* execmenu(QWidget* parent,QMenu * menu,QPoint point);
+
+    protected:
+        bool auto_refresh;
+        bool is_logging;
+        double refresh_rate;//en s
+        int receivesize;
+
+        void XmlSetup(QDomElement dom);
+
+    private:
+        void SendPeriod(int period,bool auto_refresh);
+        QAction *b,*c,*d;
+};
+
+#endif // DATAREMOTE_H
Index: trunk/tools/FlairGCS/src/DoubleSpinBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/DoubleSpinBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/DoubleSpinBox.cpp	(revision 9)
@@ -0,0 +1,127 @@
+#include "DoubleSpinBox.h"
+#include "Layout.h"
+#include <QLineEdit>
+#include <QMenu>
+#include <QContextMenuEvent>
+#include <QDoubleSpinBox>
+#include <QFormLayout>
+
+DoubleSpinBox::DoubleSpinBox(Layout* parent,int row, int col,QString name,QString suffix,QString value,float min,float max,float step,int decimals): FormLayout(parent,row,col,name,"DoubleSpinBox")
+{
+    doublespinbox = new QDoubleSpinBox();
+
+    doublespinbox->setRange(min,max);
+    doublespinbox->setSingleStep(step);
+    doublespinbox->setDecimals(decimals);
+    if(suffix!="") doublespinbox->setSuffix(suffix);
+    adjust_decimals(value);
+    doublespinbox->setValue(value.toDouble());
+    doublespinbox_value=doublespinbox->cleanText();
+
+    //event filter for qdoublespinbox and its child (qlinedit and incremnt qbuttons)
+    doublespinbox->installEventFilter(this);
+    QObjectList o_list = doublespinbox->children();
+    for(int i = 0; i < o_list.length(); i++)
+    {
+        QLineEdit *cast = qobject_cast<QLineEdit*>(o_list[i]);
+        if(cast)
+            cast->installEventFilter(this);
+    }
+
+    object_layout->addRow(name,doublespinbox);
+
+    connect(doublespinbox,SIGNAL(valueChanged(const QString &)),this, SLOT(valuechanged(const QString &)));
+
+    SetValue(value);
+}
+
+DoubleSpinBox::~DoubleSpinBox()
+{
+    delete doublespinbox;
+}
+
+void DoubleSpinBox::adjust_decimals(QString value)
+{
+    //auto adjust decimals
+    QLocale locale;
+    value.remove(locale.groupSeparator());
+
+    QStringList parts = value.split(locale.decimalPoint());
+    if(parts.count() == 2)
+    {
+        doublespinbox->setDecimals(parts[1].size());
+    }
+}
+
+bool DoubleSpinBox::eventFilter(QObject *object, QEvent *event)
+{
+    if(object==doublespinbox && event->type()==QEvent::MouseButtonPress)
+    {
+        if (((QMouseEvent*)event)->button() == Qt::RightButton)
+        {
+            QMenu * menu = new QMenu("menu", doublespinbox);
+            QAction *a,*b,*c,*z;
+
+            a=menu->addAction("add decimal");
+            b=menu->addAction("remove decimal");
+
+            if(doublespinbox->decimals()==0) b->setEnabled(false);
+            z=menu->exec(((QMouseEvent*)event)->globalPos());
+
+            if(z==a) doublespinbox->setDecimals(doublespinbox->decimals()+1);
+            if(z==b) doublespinbox->setDecimals(doublespinbox->decimals()-1);
+            delete menu;
+            return true;
+        }
+    }
+
+    return object->eventFilter(object, event);
+}
+
+void DoubleSpinBox::SetUptodate(void)
+{
+    ui_to_var();
+    ui_to_xml();
+    visible_widget->setPalette(black_pal);
+}
+
+void DoubleSpinBox::ui_to_var(void)
+{
+    doublespinbox_value=doublespinbox->cleanText();
+}
+
+void DoubleSpinBox::ui_to_xml(void)
+{
+    SetValue(doublespinbox->cleanText());
+}
+
+void DoubleSpinBox::Reset(void)
+{
+    //le setvalue fait un arrondi pour l'affichage, la variable n'est donc plus egale
+    //on reprend la valeur de la boite et on force la couleur a noir
+    adjust_decimals(doublespinbox_value);
+    doublespinbox->setValue(doublespinbox_value.toDouble());
+    doublespinbox_value= doublespinbox->cleanText();
+    visible_widget->setPalette(black_pal);
+
+}
+
+void DoubleSpinBox::LoadEvent(QDomElement dom)
+{
+    if(doublespinbox->isEnabled()==true)
+    {
+        doublespinbox->setValue((dom.attribute("value")).toDouble());
+    }
+}
+
+void DoubleSpinBox::valuechanged(const QString &value)
+{
+    if(value!=doublespinbox_value)
+    {
+        visible_widget->setPalette(red_pal);
+    }
+    else
+    {
+        visible_widget->setPalette(black_pal);
+    }
+}
Index: trunk/tools/FlairGCS/src/DoubleSpinBox.h
===================================================================
--- trunk/tools/FlairGCS/src/DoubleSpinBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/DoubleSpinBox.h	(revision 9)
@@ -0,0 +1,33 @@
+#ifndef DOUBLESPINBOX_H
+#define DOUBLESPINBOX_H
+
+#include "FormLayout.h"
+
+class Layout;
+class QDoubleSpinBox;
+
+class DoubleSpinBox: public FormLayout
+{
+    Q_OBJECT
+
+    public:
+        //handle value as string, becouse double value are not exact
+        DoubleSpinBox(Layout* parent,int row, int col,QString name,QString suffix,QString value,float min,float max,float step,int decimals);
+        ~DoubleSpinBox();
+
+    private:
+        QDoubleSpinBox* doublespinbox;
+        QString doublespinbox_value;
+        void SetUptodate(void);
+        void Reset(void);
+        void LoadEvent(QDomElement dom);
+        void ui_to_var(void);
+        void ui_to_xml(void);
+        bool eventFilter(QObject *o, QEvent *e);
+        void adjust_decimals(QString value);
+
+    private slots:
+        void valuechanged(const QString &value);
+};
+
+#endif // DOUBLESPINBOX_H
Index: trunk/tools/FlairGCS/src/FormLayout.cpp
===================================================================
--- trunk/tools/FlairGCS/src/FormLayout.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/FormLayout.cpp	(revision 9)
@@ -0,0 +1,61 @@
+#include "FormLayout.h"
+#include "Layout.h"
+#include <QWidget>
+#include <QFormLayout>
+#include <QEvent>
+
+FormLayout::FormLayout(Layout* parent,int row, int col,QString name,QString type):XmlWidget(name,type,parent)
+{
+    visible_widget=new QWidget();
+
+    //create a grid to put label and object
+    visible_widget->setObjectName(name);
+
+    parent->addWidget(visible_widget,row,col);
+    object_layout = new QFormLayout(visible_widget);
+    object_layout->setHorizontalSpacing(2);
+    object_layout->setVerticalSpacing(2);
+    object_layout->setContentsMargins (2,2,2,2);
+
+    visible_widget->installEventFilter(this);
+}
+
+FormLayout::~FormLayout()
+{
+}
+
+bool FormLayout::IsUptodate(void)
+{
+    //si le widget n'est pas enabled, sa palette est differente de rouge (greyed) donc on renvoit true
+    //permet de ne pas envoyer les modifs d'un widget disabled
+    //if(label->palette()==red_pal) return false;
+    if(visible_widget->palette()==red_pal) return false;
+    return true;
+}
+
+bool FormLayout::eventFilter(QObject *o, QEvent *e)
+{
+    if (  o == visible_widget )
+    {
+        switch(e->type())
+        {
+            case QEvent::EnabledChange:
+            {
+                QPalette palette=visible_widget->palette();
+                QPalette result;
+
+                if(palette==red_pal) result=red_pal_greyed;
+                if(palette==red_pal_greyed) result=red_pal;
+                if(palette==black_pal) result=black_pal_greyed;
+                if(palette==black_pal_greyed) result=black_pal;
+
+                visible_widget->setPalette(result);
+            }
+
+            default:
+                break;
+        }
+
+    }
+    return QObject::eventFilter(o, e);
+}
Index: trunk/tools/FlairGCS/src/FormLayout.h
===================================================================
--- trunk/tools/FlairGCS/src/FormLayout.h	(revision 9)
+++ trunk/tools/FlairGCS/src/FormLayout.h	(revision 9)
@@ -0,0 +1,25 @@
+#ifndef LABELWIDGET_H
+#define LABELWIDGET_H
+
+#include "XmlWidget.h"
+
+class QFormLayout;
+class Layout;
+
+class FormLayout: public XmlWidget
+{
+
+    public:
+        FormLayout(Layout* parent,int row, int col,QString name,QString type);
+        ~FormLayout();
+
+    private:
+        bool IsUptodate(void);
+        virtual void SetUptodate(void)=0;
+        bool eventFilter(QObject *o, QEvent *e);
+
+    protected:
+        QFormLayout* object_layout;
+};
+
+#endif // LABELWIDGET_H
Index: trunk/tools/FlairGCS/src/GridLayout.cpp
===================================================================
--- trunk/tools/FlairGCS/src/GridLayout.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/GridLayout.cpp	(revision 9)
@@ -0,0 +1,21 @@
+#include "GridLayout.h"
+#include <QWidget>
+#include <QGridLayout>
+
+GridLayout::GridLayout(Layout* parent,int row, int col,QString name): Layout(parent,name,"GridLayout")
+{
+    widget = new QWidget();
+    widget->setObjectName(name);
+
+    visible_widget=widget;
+
+    parent->addWidget(widget,row,col);
+
+    widget->setLayout(getQGridLayout());
+}
+
+
+GridLayout::~GridLayout()
+{
+    widget->setParent(NULL);
+}
Index: trunk/tools/FlairGCS/src/GridLayout.h
===================================================================
--- trunk/tools/FlairGCS/src/GridLayout.h	(revision 9)
+++ trunk/tools/FlairGCS/src/GridLayout.h	(revision 9)
@@ -0,0 +1,17 @@
+#ifndef GRIDLAYOUT_H
+#define GRIDLAYOUT_H
+
+#include "Layout.h"
+
+class GridLayout: public Layout
+{
+
+    public:
+        GridLayout(Layout* parent,int row, int col,QString name);
+        ~GridLayout();
+
+    private:
+        QWidget* widget;
+};
+
+#endif // GRIDLAYOUT_H
Index: trunk/tools/FlairGCS/src/GroupBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/GroupBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/GroupBox.cpp	(revision 9)
@@ -0,0 +1,27 @@
+#include "GroupBox.h"
+#include <QGroupBox>
+#include <QGridLayout>
+
+GroupBox::GroupBox(Layout* parent,int row, int col,QString name): Layout(parent,name,"GroupBox")
+{
+    //creation et ajout QGroupBox
+    box = new QGroupBox(name);
+    box->setObjectName(name);
+
+    visible_widget=box;
+
+    parent->addWidget(box,row,col);
+    //parent->splitter->addWidget(box);
+
+    box->setLayout(getQGridLayout());
+}
+
+
+GroupBox::~GroupBox()
+{
+    //layout->removeItem(this);//ne semble pas necessaire
+
+    box->setParent(NULL);//sinon le delete layout detruit aussi this
+    //delete layout;
+    //delete box;
+}
Index: trunk/tools/FlairGCS/src/GroupBox.h
===================================================================
--- trunk/tools/FlairGCS/src/GroupBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/GroupBox.h	(revision 9)
@@ -0,0 +1,19 @@
+#ifndef GROUPBOX_H
+#define GROUPBOX_H
+
+#include "Layout.h"
+
+class QGroupBox;
+
+class GroupBox: public Layout
+{
+
+    public:
+        GroupBox(Layout* parent,int row, int col,QString name);
+        ~GroupBox();
+
+    private:
+        QGroupBox* box;
+};
+
+#endif // GROUPBOX_H
Index: trunk/tools/FlairGCS/src/Label.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Label.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Label.cpp	(revision 9)
@@ -0,0 +1,26 @@
+#include "Label.h"
+#include "Layout.h"
+#include <QLabel>
+
+Label::Label(Layout* parent,int row, int col,QString name):XmlWidget(name,"Label",parent)
+{
+
+    label = new QLabel();
+    label->setObjectName(name);
+    visible_widget=label;
+
+    parent->addWidget(label,row,col);
+
+    //pour ne pas faire de doublons qd on change le texte
+    SetIsExpandable(true);
+}
+
+Label::~Label()
+{
+
+}
+
+void Label::XmlEvent(QDomElement dom)
+{
+    label->setText(dom.attribute("value"));
+}
Index: trunk/tools/FlairGCS/src/Label.h
===================================================================
--- trunk/tools/FlairGCS/src/Label.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Label.h	(revision 9)
@@ -0,0 +1,22 @@
+#ifndef LABEL_H
+#define LABEL_H
+
+#include "XmlWidget.h"
+
+class Layout;
+class QLabel;
+
+class Label: public XmlWidget
+{
+    public:
+        Label(Layout* parent,int row, int col,QString name);
+        ~Label();
+
+    private:
+        void XmlEvent(QDomElement dom);
+        QLabel *label;
+
+
+};
+
+#endif // LABEL_H
Index: trunk/tools/FlairGCS/src/Landmark.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Landmark.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Landmark.cpp	(revision 9)
@@ -0,0 +1,72 @@
+#include "Landmark.h"
+#include <QPen>
+#include <QGeoMapTextObject>
+#include <QGeoMapPixmapObject>
+#include <QGraphicsGeoMap>
+
+using namespace QtMobility;
+
+Landmark::Landmark(QGraphicsGeoMap *geoMap, const QGeoCoordinate &coordinate,QString name,QString type)
+{
+    geoMap->addMapObject(this);
+    this->geoMap=geoMap;
+    pixmap = new QGeoMapPixmapObject();
+    pixmap->setCoordinate(coordinate);
+
+    if(type=="cross")
+    {
+        pixmap->setOffset(QPoint(-16, -16));
+        pixmap->setPixmap(QPixmap(":cross.png"));
+    }
+    else
+    {
+        pixmap->setOffset(QPoint(-2, -30));
+        pixmap->setPixmap(QPixmap(":landmark.png"));
+    }
+    addChildObject(pixmap);
+
+    QFont font;
+    font.setWeight(QFont::Bold);
+    text = new QGeoMapTextObject(coordinate,name, font, QPoint(0, 10));
+    text->setPen(QPen(Qt::NoPen));
+    text->setBrush(QBrush(Qt::red));
+    addChildObject(text);
+}
+
+Landmark::~Landmark()
+{
+    geoMap->removeMapObject(this);
+    clearChildObjects();
+}
+
+void Landmark::setText(QString string)
+{
+    text->setText(string);
+}
+
+void Landmark::setColor(Qt::GlobalColor color)
+{
+    text->setBrush(QBrush(color));
+}
+
+void Landmark::setCoordinate(const QGeoCoordinate &coordinate)
+{
+    pixmap->setCoordinate(coordinate);
+    text->setCoordinate(coordinate);
+}
+
+QGeoCoordinate Landmark::coordinate(void)
+{
+    return pixmap->coordinate();
+}
+
+void Landmark::RemoveLandmark(void)
+{
+    geoMap->removeMapObject(this);
+}
+
+void Landmark::AddLandmark(QGraphicsGeoMap *geoMap)
+{
+    geoMap->addMapObject(this);
+    this->geoMap=geoMap;
+}
Index: trunk/tools/FlairGCS/src/Landmark.h
===================================================================
--- trunk/tools/FlairGCS/src/Landmark.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Landmark.h	(revision 9)
@@ -0,0 +1,34 @@
+#ifndef LANDMARK_H
+#define LANDMARK_H
+
+#include <QGeoMapGroupObject>
+#include <QGeoCoordinate>
+
+namespace QtMobility {
+    class QGraphicsGeoMap;
+    class QGeoMapTextObject;
+    class QGeoMapPixmapObject;
+}
+
+
+class Landmark : public QtMobility::QGeoMapGroupObject
+{
+
+public:
+    Landmark(QtMobility::QGraphicsGeoMap *geoMap,const QtMobility::QGeoCoordinate &coordinate,QString name,QString type="landmark");
+    ~Landmark();
+
+    QtMobility::QGeoCoordinate coordinate(void);
+    void setCoordinate(const QtMobility::QGeoCoordinate &coordinate);
+    void setText(QString string);
+    void setColor(Qt::GlobalColor color);
+    void RemoveLandmark(void);
+    void AddLandmark(QtMobility::QGraphicsGeoMap *geoMap);
+
+private:
+    QtMobility::QGeoMapTextObject* text;
+    QtMobility::QGeoMapPixmapObject* pixmap;
+    QtMobility::QGraphicsGeoMap *geoMap;
+};
+
+#endif
Index: trunk/tools/FlairGCS/src/Layout.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Layout.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Layout.cpp	(revision 9)
@@ -0,0 +1,248 @@
+#include "Layout.h"
+#include "TabWidget.h"
+#include "GroupBox.h"
+#include "GridLayout.h"
+#include "SpinBox.h"
+#include "DoubleSpinBox.h"
+#include "Vector3DSpinBox.h"
+#include "CheckBox.h"
+#include "ComboBox.h"
+#include "PushButton.h"
+#include "TextEdit.h"
+#include "Label.h"
+#include "DataPlot1D.h"
+#include "DataPlot2D.h"
+#include "RangeFinderPlot.h"
+#include "Picture.h"
+#include "Map.h"
+#include <QGeoCoordinate>
+#include <QGridLayout>
+
+
+Layout::Layout(QWidget* parent,XmlWidget* xml,QString name,QString type): XmlWidget(name,type,xml) {
+    qgridlayout=new QGridLayout(parent);
+    Constructor(name);
+}
+
+Layout::Layout(Layout* parent,QString name,QString type): XmlWidget(name,type,parent) {
+    qgridlayout=new QGridLayout(new QWidget());
+    Constructor(name);
+}
+
+void Layout::Constructor(QString name) {
+    visible_widget=qgridlayout->parentWidget();
+    //if(visible_widget==NULL) printf("null\n");
+    qgridlayout->setObjectName(name);
+    //printf("layout\n%s\n",XmlDoc().toString().toLocal8Bit().constData());
+    SetIsContainer(true);
+    SetIsExpandable(true);
+
+    qgridlayout->setHorizontalSpacing(2);
+    qgridlayout->setVerticalSpacing(2);
+    qgridlayout->setContentsMargins (2,2,2,2);
+
+    //splitter = new QSplitter();
+    //addWidget(splitter);
+    /*
+    QWidget *widget = new QWidget();
+    //QHBoxLayout *parentLayout = new QHBoxLayout();
+    widget->setLayout(this);
+    parent->addWidget(widget);
+    //QTabWidget *tabWidget = new QTabWidget();
+    //parentLayout->addWidget(tabWidget);*/
+}
+
+Layout::~Layout() {
+    delete qgridlayout;
+}
+
+void Layout::addWidget(QWidget *widget, int row, int column) {
+    qgridlayout->addWidget(widget,row,column);
+}
+
+QGridLayout* Layout::getQGridLayout() {
+    return qgridlayout;
+}
+
+void Layout::XmlEvent(QDomElement dom) {
+    XmlWidget* widget=NULL;
+    QString type=dom.tagName();
+    QString name=dom.attribute("name");
+    QString old_name=dom.attribute("old_name");
+    int row=dom.attribute("row").toInt();
+    int col=dom.attribute("col").toInt();
+
+//initially rowCount()=1 and columnCount()=1 but count()=0 !
+    //new row
+    if(row==-1 && col==-1) {
+        row=qgridlayout->rowCount();
+        if(qgridlayout->count()==0) row=0;
+        col=0;
+    }
+    //last row last col
+    if(row==-1 && col==0) {
+        row=qgridlayout->rowCount()-1;
+        int i;
+        for(i=0;i<=qgridlayout->columnCount();i++) {
+            if(qgridlayout->itemAtPosition(row,i)==NULL) break;
+        }
+        col=i;
+    }
+    //if an item already exists at this position, put it on a new row
+    if(qgridlayout->itemAtPosition(row,col)!=NULL) {
+        printf("existe %s\n",name.toLocal8Bit().constData());
+        row=qgridlayout->rowCount();
+    }
+
+    if(type=="TabWidget") {
+        int position=dom.attribute("position").toInt();
+        widget = new TabWidget(this,row,col,name,(QTabWidget::TabPosition)position);
+    }
+    if(type=="GroupBox") {
+        widget = new GroupBox(this,row,col,name);
+    }
+    if(type=="GridLayout") {
+        widget = new GridLayout(this,row,col,name);
+    }
+    if(type=="SpinBox") {
+        int value=dom.attribute("value").toInt();
+        QString suffix=dom.attribute("suffix");
+        int min=dom.attribute("min").toInt();
+        int max=dom.attribute("max").toInt();
+        int step=dom.attribute("step").toInt();
+        widget= new SpinBox(this,row,col,name,suffix,value,min,max,step);
+    }
+    if(type=="DoubleSpinBox") {
+        QString value=dom.attribute("value");
+        QString suffix=dom.attribute("suffix");
+        double min=dom.attribute("min").toDouble();
+        double max=dom.attribute("max").toDouble();
+        double step=dom.attribute("step").toDouble();
+        int decimals=dom.attribute("decimals").toInt();
+        widget= new DoubleSpinBox(this,row,col,name,suffix,value,min,max,step,decimals);
+    }
+    if(type=="Vector3DSpinBox") {
+        QString value[3];
+        value[0]=dom.attribute("value_x");
+        value[1]=dom.attribute("value_y");
+        value[2]=dom.attribute("value_z");
+        double min=dom.attribute("min").toDouble();
+        double max=dom.attribute("max").toDouble();
+        double step=dom.attribute("step").toDouble();
+        int decimals=dom.attribute("decimals").toInt();
+        widget= new Vector3DSpinBox(this,row,col,name,value,min,max,step,decimals);
+    }
+    if(type=="CheckBox") {
+        int value=dom.attribute("value").toInt();
+        widget= new CheckBox(this,row,col,name,value);
+    }
+    if(type=="ComboBox") {
+        int value=dom.attribute("value").toInt();
+        widget= new ComboBox(this,row,col,name,value);
+    }
+    if(type=="PushButton") {
+        widget= new PushButton(this,row,col,name);
+    }
+    if(type=="DataPlot1D") {
+        float ymin=dom.attribute("min").toFloat();
+        float ymax=dom.attribute("max").toFloat();
+        int enabled=dom.attribute("enabled").toInt();
+        int period=dom.attribute("period").toInt();
+        if(enabled==1) {
+            widget = new DataPlot1D(this,row,col,name,ymin,ymax,true,period);
+        } else {
+            widget = new DataPlot1D(this,row,col,name,ymin,ymax,false,100);
+        }
+    }
+    if(type=="DataPlot2D") {
+        float xmin=dom.attribute("xmin").toFloat();
+        float xmax=dom.attribute("xmax").toFloat();
+        float ymin=dom.attribute("ymin").toFloat();
+        float ymax=dom.attribute("ymax").toFloat();
+        QString x_name=dom.attribute("x_name");
+        QString y_name=dom.attribute("y_name");
+        int enabled=dom.attribute("enabled").toInt();
+        int period=dom.attribute("period").toInt();
+        if(enabled==1) {
+            widget = new DataPlot2D(this,row,col,name,x_name,y_name,xmin,xmax,ymin,ymax,true,period);
+        } else {
+            widget = new DataPlot2D(this,row,col,name,x_name,y_name,xmin,xmax,ymin,ymax,false,100);
+        }
+    }
+    if(type=="RangeFinderPlot") {
+        float xmin=dom.attribute("xmin").toFloat();
+        float xmax=dom.attribute("xmax").toFloat();
+        float ymin=dom.attribute("ymin").toFloat();
+        float ymax=dom.attribute("ymax").toFloat();
+        QString x_name=dom.attribute("x_name");
+        QString y_name=dom.attribute("y_name");
+        QString data_type=dom.attribute("type");
+        float start_angle=dom.attribute("start_angle").toFloat();
+        float end_angle=dom.attribute("end_angle").toFloat();
+        uint32_t nb_samples=dom.attribute("nb_samples").toUInt();
+        int enabled=dom.attribute("enabled").toInt();
+        int period=dom.attribute("period").toInt();
+        int invert_axis=dom.attribute("invert_axis").toInt();
+        bool invert_axis_bool;
+        if(invert_axis==0) {
+            invert_axis_bool=false;
+        }else {
+            invert_axis_bool=true;
+        }
+        if(enabled==1) {
+            widget = new RangeFinderPlot(this,row,col,name,x_name,y_name,xmin,xmax,ymin,ymax,start_angle,end_angle,nb_samples,data_type,invert_axis,true,period);
+        } else {
+            widget = new RangeFinderPlot(this,row,col,name,x_name,y_name,xmin,xmax,ymin,ymax,start_angle,end_angle,nb_samples,data_type,invert_axis,false,100);
+        }
+    }
+    if(type=="Picture") {
+        int width=dom.attribute("width").toInt();
+        int height=dom.attribute("height").toInt();
+        int enabled=dom.attribute("enabled").toInt();
+        int period=dom.attribute("period").toInt();
+        if(enabled==1) {
+            widget = new Picture(this,row,col,name,width,height,true,period);
+        } else {
+            widget = new Picture(this,row,col,name,width,height,false,period);
+        }
+    }
+    if(type=="Map") {
+        int period=dom.attribute("period").toInt();
+        int enabled=dom.attribute("enabled").toInt();
+        int i=0;
+        QList<QtMobility::QGeoCoordinate> coordinates;
+        while(dom.hasAttribute("lat" +QString::number(i))) {
+            double latitude=dom.attribute("lat"+QString::number(i)).toDouble();
+            double longitude=dom.attribute("long"+QString::number(i)).toDouble();
+            double alt=dom.attribute("alt"+QString::number(i)).toDouble();
+            QtMobility::QGeoCoordinate coordinate=QtMobility::QGeoCoordinate(latitude,longitude,alt);
+            coordinates.append(coordinate);
+            i++;
+        }
+
+        if(enabled==1) {
+            widget = new Map(this,row,col,name,coordinates,true,period);
+        } else {
+            widget = new Map(this,row,col,name,coordinates,false,period);
+        }
+    }
+    if(type=="TextEdit") {
+        widget= new TextEdit(this,row,col,name);
+    }
+    if(type=="Label") {
+        widget= new Label(this,row,col,name);
+    }
+
+    if(widget!=NULL) {
+        if(old_name!="") {
+            widget->RenamedFrom(old_name);
+        }
+    }
+}
+
+bool Layout::IsUptodate(void) {
+    for(int i=0;i<childs->count();i++) {
+        if(childs->at(i)->IsUptodate()==false) return false;
+    }
+    return true;
+}
Index: trunk/tools/FlairGCS/src/Layout.h
===================================================================
--- trunk/tools/FlairGCS/src/Layout.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Layout.h	(revision 9)
@@ -0,0 +1,26 @@
+#ifndef LAYOUT_H
+#define LAYOUT_H
+
+#include "XmlWidget.h"
+
+class QWidget;
+class QGridLayout;
+
+class Layout:  public XmlWidget
+{
+    public:
+        Layout(QWidget* parent,XmlWidget* xml,QString name,QString type);
+        Layout(Layout* parent,QString name,QString type);
+        ~Layout();
+        bool IsUptodate(void);
+        void addWidget(QWidget *, int row, int column);
+        QGridLayout* getQGridLayout();
+
+        //QSplitter *splitter;
+    private:
+        void Constructor(QString name);
+        void XmlEvent(QDomElement dom);
+        QGridLayout* qgridlayout;
+};
+
+#endif // LAYOUT_H
Index: trunk/tools/FlairGCS/src/Manager.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Manager.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Manager.cpp	(revision 9)
@@ -0,0 +1,302 @@
+#include "Manager.h"
+#include "UdtSocket.h"
+#include "ConnectionLayout.h"
+#include "communication.h"
+#include <QDate>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QTabBar>
+#include <QTimer>
+#include <QThread>
+#include <QTextStream>
+#include <QVBoxLayout>
+#include <QModelIndex>
+//#include <qmetatype.h>
+#include <qendian.h>
+#include <iostream>
+#include <string>
+#include <fstream>
+#include <stdio.h>
+
+#ifndef WIN32
+   #include <arpa/inet.h>
+#else
+   #include <winsock2.h>
+   #include <ws2tcpip.h>
+#endif
+
+using namespace std;
+
+Manager::Manager(QString name,int port):QWidget() {
+    qRegisterMetaType<QModelIndex>("QModelIndex");//pour le file ui??
+    this->name=name;
+
+    setWindowTitle(name);
+
+    //manager layout
+    managerLayout = new QVBoxLayout;
+    setLayout(managerLayout);
+
+    //tab bar for multiple connections
+    tabBar=new QTabBar();
+    managerLayout->addWidget(tabBar);
+    connect(tabBar, SIGNAL(currentChanged(int)),this, SLOT(tabBarCurrentChanged(int)));
+    currentTab=0;
+
+    //layout boutons
+    button_layout = new QGridLayout();
+    managerLayout->addLayout(button_layout);
+
+    //boutons du button_Layout
+    send_button = new QPushButton("apply all");
+    reset_button = new QPushButton("reset all");
+    load_button = new QPushButton("load all locally");
+    save_button = new QPushButton("save all locally");
+    button_layout->addWidget(send_button,0,0);
+    button_layout->addWidget(reset_button,0,1);
+    button_layout->addWidget(load_button,0,2);
+    button_layout->addWidget(save_button,0,3);
+
+    connect(send_button, SIGNAL(clicked(bool)),this, SLOT(send()));
+    connect(reset_button, SIGNAL(clicked(bool)),this, SLOT(reset()));
+    connect(load_button, SIGNAL(clicked(bool)),this, SLOT(load()));
+    connect(save_button, SIGNAL(clicked(bool)),this, SLOT(save()));
+
+    UDT::startup();
+    serv = UDT::socket(AF_INET, SOCK_DGRAM, 0);
+
+    //for non blocking accept
+    bool blocking = false;
+    UDT::setsockopt(serv, 0, UDT_RCVSYN, &blocking, sizeof(bool));
+
+    sockaddr_in my_addr;
+    my_addr.sin_family = AF_INET;
+    my_addr.sin_port = htons(port);
+    my_addr.sin_addr.s_addr = INADDR_ANY;
+    memset(&(my_addr.sin_zero), '\0', 8);
+
+    if (UDT::ERROR == UDT::bind(serv, (sockaddr*)&my_addr, sizeof(my_addr))) {
+        printf("bind error, %s\n",UDT::getlasterror().getErrorMessage());
+    }
+
+    if (UDT::ERROR == UDT::listen(serv, 1)) {
+        printf("listen error, %s\n",UDT::getlasterror().getErrorMessage());
+    }
+
+    QTimer *timer = new QTimer(this);
+    connect(timer, SIGNAL(timeout()), this, SLOT(acceptConnections()));
+    timer->start(20);
+}
+
+Manager::~Manager() {
+    emit killUdtSockets();
+
+    //delete main_layout;
+    UDT::cleanup();
+}
+
+void Manager::acceptConnections(void) {
+    static UDTSOCKET first_socket=0;
+    UDTSOCKET socket;
+
+    sockaddr_in their_addr;
+    int namelen = sizeof(their_addr);
+
+    if (UDT::INVALID_SOCK == (socket = UDT::accept(serv, (sockaddr*)&their_addr, &namelen))) {
+        if(UDT::getlasterror().getErrorCode()!=6002)  printf("accept: %s, code %i\n",UDT::getlasterror().getErrorMessage(),UDT::getlasterror().getErrorCode());
+        return;
+    } else {
+        printf("connected to %s:%i\n",inet_ntoa(their_addr.sin_addr),their_addr.sin_port);
+
+        if(!first_socket) {
+            first_socket=socket;
+            return;
+        } else {
+            QThread* thread = new QThread(this);
+            UdtSocket* new_udt=new UdtSocket(first_socket,socket,name);
+            new_udt->moveToThread(thread);
+
+            newConnection(new_udt);
+
+            connect(this, SIGNAL(killUdtSockets()),thread, SLOT(quit()));
+            connect(this, SIGNAL(killUdtSockets()),new_udt, SLOT(kill()),Qt::BlockingQueuedConnection);
+
+            connect(thread, SIGNAL(started()), new_udt, SLOT(handleConnections()));
+
+            thread->start();
+            first_socket=0;
+        }
+    }
+}
+
+void Manager::newConnection(UdtSocket* socket) {
+
+    //no tabs to 2 tabs
+    if(connectionsLayout.count()==1) {
+        tabBar->addTab(hiddenTabName);
+        currentTab=0;
+        connectionsWidget.at(0)->show();
+    }
+
+    //layout utilisateur
+    ConnectionLayout* newLayout = new ConnectionLayout(socket,"interface");
+    connectionsLayout.append(newLayout);
+    connect(newLayout, SIGNAL(setRemoteName(QString)),this, SLOT(tabName(QString)));
+    connect(socket, SIGNAL(dataReady(char*,int)),newLayout, SLOT(receive(char*,int)));
+    connect(newLayout, SIGNAL(destroyed(QObject*)),this, SLOT(layoutDestroyed(QObject*)));
+    connect(socket, SIGNAL(destroyed()),newLayout, SLOT(deleteLater()));
+
+    //widget
+    QWidget* newWidget=new QWidget();
+    connectionsWidget.append(newWidget);
+    newWidget->setLayout(newLayout->getQGridLayout());
+    managerLayout->insertWidget(1,newWidget);
+    newWidget->hide();
+
+    if(connectionsLayout.count()==1) {//first connection
+        newWidget->show();
+    } else {//add a tab for the new connection
+        tabBar->addTab("unknown");
+    }
+}
+
+void Manager::tabBarCurrentChanged(int index) {
+    if(index>=0) {
+        connectionsWidget.at(currentTab)->hide();
+        connectionsWidget.at(index)->show();
+        currentTab=index;
+    } else {
+        currentTab=0;
+        connectionsWidget.at(0)->show();
+    }
+}
+
+void Manager::tabName(QString name) {
+    int index=connectionsLayout.indexOf((ConnectionLayout*)sender());
+    if(tabBar->count()==0) {
+        hiddenTabName=name;
+    } else {
+        tabBar->setTabText(index,name);
+    }
+}
+
+void Manager::layoutDestroyed(QObject* obj) {
+    int index=connectionsLayout.indexOf((ConnectionLayout*)obj);
+
+    if(tabBar->count()>1) {
+        tabBar->removeTab(index);
+    }
+
+    delete connectionsWidget.at(index);
+    connectionsWidget.removeAt(index);
+    connectionsLayout.removeOne((ConnectionLayout*)obj);
+
+    if(connectionsLayout.count()==1) {
+        hiddenTabName=tabBar->tabText(0);
+        tabBar->removeTab(0);
+    }
+}
+
+void Manager::load(void) {
+    QString dir_name= QFileDialog::getExistingDirectory(this, "Select a directory",0,0);
+
+    if(dir_name!="") {
+        for(int i=0;i<connectionsLayout.count();i++) {
+            QFile* file;
+            file = new QFile(dir_name+"/"+connectionsLayout.at(i)->getRemoteName()+".xml");
+            if(!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
+                QMessageBox::warning(this,"Warning","Enable to load "+connectionsLayout.at(i)->getRemoteName()+".xml");
+                continue;
+            }
+
+            QDomDocument doc;
+            QString errorMsg;
+            int errorLine;
+            int errorColumn;
+            if(!doc.setContent(file,&errorMsg,&errorLine,&errorColumn)) {
+                QMessageBox::critical(this,"Error","unable to read " +connectionsLayout.at(i)->getRemoteName()+".xml"
+                                   +" ("+errorMsg + " at " +QString::number(errorLine) +","+QString::number(errorColumn)+")");
+            } else {
+                connectionsLayout.at(i)->LoadXml(doc);
+            }
+            delete file;
+        }
+    }
+}
+
+void Manager::save(void) {
+    bool isUptodate=true;
+
+    for(int i=0;i<connectionsLayout.count();i++) {
+        if(!connectionsLayout.at(i)->IsUptodate()) {
+            isUptodate=false;
+            break;
+        }
+    }
+
+    if(!isUptodate) {
+        QMessageBox msgBox;
+        msgBox.setText("There are pending modifications");
+        msgBox.setInformativeText("Apply and save?");
+        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+        msgBox.setDefaultButton(QMessageBox::Yes);
+        int ret = msgBox.exec();
+
+        switch (ret) {
+           case QMessageBox::Yes:
+               send();
+               break;
+           case QMessageBox::Cancel:
+               return;
+               break;
+           default:
+               // should never be reached
+               break;
+        }
+    }
+
+    //create dirctory for storage
+    QDateTime dateTime = QDateTime::currentDateTime();
+    QString dir_name = "configs_"+dateTime.toString("yyyyMMdd_hhmm")+ "_" + name;
+    if(QDir().exists(dir_name)==true) {
+        dir_name = "configs_"+dateTime.toString("yyyyMMdd_hhmm_ss")+ "_" + name;
+    }
+    QDir().mkdir(dir_name);
+
+    for(int i=0;i<connectionsLayout.count();i++) {
+        QDomDocument* xml=new QDomDocument("remote_ui_xml");
+
+        connectionsLayout.at(i)->GetFullXml((QDomElement*)xml);
+
+        QFile fichier(dir_name+"/"+connectionsLayout.at(i)->getRemoteName()+".xml");
+        QString write_doc = (xml->ownerDocument()).toString();
+
+        if(!fichier.open(QIODevice::WriteOnly)) {
+            fichier.close();
+            QMessageBox::critical(this,"Error","Enable to write XML");
+            continue;
+        }
+        QTextStream stream(&fichier);
+        stream << write_doc; // On utilise l'opérateur << pour écrire write_doc dans le document XML.
+        fichier.close();
+
+        delete xml;
+    }
+
+    QMessageBox::information(this,"save all","saved to ./"+ dir_name);
+}
+
+void Manager::send(void) {
+    for(int i=0;i<connectionsLayout.count();i++) {
+        QDomDocument doc("remote_ui_xml");
+        connectionsLayout.at(i)->GetUpdateXml((QDomElement*)&doc);
+        //printf("merge\n%s\n",doc.toString().toLocal8Bit().constData());
+
+        connectionsLayout.at(i)->XmlToSend(doc);
+    }
+}
+
+void Manager::reset() {
+    for(int i=0;i<connectionsLayout.count();i++) connectionsLayout.at(i)->ResetAllChilds();
+}
Index: trunk/tools/FlairGCS/src/Manager.h
===================================================================
--- trunk/tools/FlairGCS/src/Manager.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Manager.h	(revision 9)
@@ -0,0 +1,58 @@
+#ifndef MANAGER_H
+#define MANAGER_H
+
+#include <QWidget>
+#include <udt.h>
+#include <qdom.h>
+
+class UdtSocket;
+class ConnectionLayout;
+class QVBoxLayout;
+class QTabBar;
+class QPushButton;
+class QGridLayout;
+
+class Manager : public QWidget
+{
+    Q_OBJECT
+
+    public:
+        Manager(QString name,int port);
+        ~Manager();
+
+    private:
+        UDTSOCKET serv ;
+        QVBoxLayout *managerLayout;
+        QList<ConnectionLayout*> connectionsLayout;
+        QList<QWidget*> connectionsWidget;
+        QTabBar* tabBar;
+        QString name,hiddenTabName;
+        int currentTab;
+
+        QPushButton *send_button;
+        QPushButton *reset_button;
+        QPushButton *load_button;
+        QPushButton *save_button;
+        QGridLayout *button_layout;
+
+        void newConnection(UdtSocket* socket) ;
+
+    private slots:
+        void acceptConnections(void);
+        void load(void);
+        void send(void);
+        void save(void);
+        void reset(void);
+        void layoutDestroyed(QObject* obj);
+        void tabBarCurrentChanged(int index);
+        void tabName(QString name);
+
+    signals:
+        void killUdtSockets(void);
+
+    protected:
+
+};
+
+#endif //MANAGER_H
+
Index: trunk/tools/FlairGCS/src/Map.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Map.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Map.cpp	(revision 9)
@@ -0,0 +1,338 @@
+#include "Map.h"
+#include "Landmark.h"
+#include "Layout.h"
+#include "mapwidget.h"
+#include <QNetworkProxy>
+#include <QFormLayout>
+#include <QInputDialog>
+#include <QtGlobal>
+#include <QMenu>
+#include <QGeoMappingManager>
+#include <QGeoServiceProvider>
+#include <QComboBox>
+#include <QToolButton>
+#include <QCoreApplication>
+#include <qendian.h>
+
+using namespace QtMobility;
+
+Map::Map(Layout* parent,int row, int col,QString name,QList<QGeoCoordinate> coordinates,bool enabled,int period):
+    DataRemote(name,"Map",parent,enabled,period)
+{
+    visible_widget=new QWidget();
+    visible_widget->setObjectName(name);
+    centeredpoint=0;
+
+    mapTypes[QGraphicsGeoMap::StreetMap] = tr("Street map");
+    mapTypes[QGraphicsGeoMap::SatelliteMapDay] = tr("Satellite map (day)");
+    mapTypes[QGraphicsGeoMap::SatelliteMapNight] = tr("Satellite map (night)");
+    mapTypes[QGraphicsGeoMap::TerrainMap] = tr("Terrain map");
+
+    mapWidget = new MapWidget(this,visible_widget);
+    geoMap = 0;
+
+
+    QVBoxLayout *map_layout = new QVBoxLayout();
+    parent->getQGridLayout()->addLayout(map_layout,row,col);
+    QHBoxLayout *tool_layout = new QHBoxLayout();
+    map_layout->addLayout(tool_layout,0);
+
+    QFormLayout* servicelayout = new QFormLayout();
+    serviceCombo = new QComboBox(visible_widget);
+    servicelayout->addRow("service: ",serviceCombo);
+    QFormLayout* maplayout = new QFormLayout();
+    mapTypeCombo = new QComboBox(visible_widget);
+    maplayout->addRow("map type: ",mapTypeCombo);
+    QFormLayout* proxylayout = new QFormLayout();
+    proxyCombo = new QComboBox(visible_widget);
+    proxylayout->addRow("proxy: ",proxyCombo);
+
+    if(findServices())
+    {
+        tool_layout->addLayout(servicelayout,0);
+        tool_layout->addLayout(maplayout,1);
+        tool_layout->addLayout(proxylayout,2);
+
+        zoomin=new QToolButton(visible_widget);
+        zoomout=new QToolButton(visible_widget);
+        zoomInAction = new QAction(QIcon(QPixmap(":zoomin.png")), tr("Zoom &In"),zoomin);
+        zoomOutAction = new QAction(QIcon(QPixmap(":zoomout.png")), tr("Zoom &Out"),zoomout);
+        zoomin->setDefaultAction(zoomInAction);
+        zoomout->setDefaultAction(zoomOutAction);
+        tool_layout->addWidget(zoomin,3);
+        tool_layout->addWidget(zoomout,4);
+        connect(zoomInAction, SIGNAL(triggered()), this, SLOT(zoomIn()));
+        connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOut()));
+
+        selectService(0);
+
+        findproxy();
+
+        connect(serviceCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(selectService(int)));
+        connect(mapTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeMapType(int)));
+        connect(proxyCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeproxy(int)));
+    }
+    else
+    {
+        printf("Error, no services!\n");
+        mapWidget->setEnabled(false);
+    }
+
+    map_layout->addWidget(mapWidget,1);
+    for(int i=0;i<coordinates.size();i++) {
+        mapWidget->AddLandmark((QGeoCoordinate &)coordinates.at(i));
+    }
+}
+
+Map::~Map()
+{
+}
+
+bool Map::findServices(void)
+{
+    QCoreApplication::addLibraryPath(qgetenv("OECORE_HOST_SYSROOT") + "/usr/lib/qt4/");
+
+    QStringList services = QGeoServiceProvider::availableServiceProviders();
+
+    if (services.isEmpty())
+    {
+        QGraphicsTextItem *item = mapWidget->scene()->addText(
+            tr("Failed to find any map services. Please ensure that "
+               "the location services plugins for Qt Mobility are "
+               "installed and, if necessary, set the IGEP_ROOT "
+               "environment variable to the good location."));
+
+        item->setTextWidth(300);
+
+        return false;
+    }
+
+    QMap<QString, QVariant> parameters;
+
+    foreach (QString name, services)
+    {
+
+        parameters["mapping.cache.directory"] = name;
+        parameters["mapping.cache.size"] = QString("500000000");
+
+        QGeoServiceProvider *service = new QGeoServiceProvider(name,parameters);
+
+        if (service->error() != QGeoServiceProvider::NoError) {
+            delete service;
+            continue;
+        }
+
+        QGeoMappingManager *manager = service->mappingManager();
+
+        if (manager)
+        {
+            serviceCombo->addItem(name);
+            managers.append(manager);
+        }
+    }
+
+    return true;
+}
+
+void Map::selectService(int item)
+{
+    QString name = serviceCombo-> currentText ();
+
+    QGeoCoordinate coordinate = QGeoCoordinate(0, 0);
+    QGraphicsGeoMap::MapType mapType = QGraphicsGeoMap::StreetMap;
+    int zoomLevel = 1;
+
+    if (geoMap) {
+        coordinate = geoMap->center();
+        mapType = geoMap->mapType();
+        zoomLevel = geoMap->zoomLevel();
+
+        mapWidget->RemoveLandmarks();
+        RemovePoints();
+        geoMap->deleteLater();
+    }
+
+    manager = managers[item];
+    geoMap = new QGraphicsGeoMap(manager);
+
+    mapWidget->AddLandmarks(geoMap);
+    AddPoints(geoMap);
+    geoMap->setCenter(coordinate);
+    geoMap->setMapType(mapType);
+
+    populateMapTypeCombo();
+    updateZoom(zoomLevel);
+
+    mapWidget->setMap(geoMap);
+    connect(geoMap, SIGNAL(zoomLevelChanged(qreal)), this, SLOT(updateZoom(qreal)));
+}
+
+void Map::changeMapType(int index)
+{
+    geoMap->setMapType(QGraphicsGeoMap::MapType(mapTypeCombo->itemData(index).toInt()));
+}
+
+void Map::populateMapTypeCombo(void)
+{
+    mapTypeCombo->clear();
+
+    foreach (QGraphicsGeoMap::MapType mapType, geoMap->supportedMapTypes()) {
+        if (mapTypes.contains(mapType))
+            mapTypeCombo->addItem(mapTypes[mapType], QVariant(mapType));
+    }
+
+    if (mapTypeCombo->count() > 0)
+        geoMap->setMapType(QGraphicsGeoMap::MapType(mapTypeCombo->itemData(0).toInt()));
+}
+
+void Map::zoomIn(void)
+{
+    updateZoom(geoMap->zoomLevel() + 1);
+}
+
+void Map::zoomOut(void)
+{
+    updateZoom(geoMap->zoomLevel() - 1);
+}
+
+void Map::updateZoom(qreal value)
+{
+    value = qBound(manager->minimumZoomLevel(), value, manager->maximumZoomLevel());
+
+    geoMap->setZoomLevel(value);
+    zoomin->setEnabled(geoMap->zoomLevel() < manager->maximumZoomLevel());
+    zoomout->setEnabled(geoMap->zoomLevel() > manager->minimumZoomLevel());
+}
+
+void Map::findproxy(void)
+{
+    proxyCombo->addItem("none");
+    proxyCombo->addItem("new");
+    proxyCombo->addItem("proxyweb.utc.fr:3128");
+}
+
+void Map::changeproxy(int index)
+{
+    if(index==0)
+    {
+        QNetworkProxy proxy;
+        proxy.setType(QNetworkProxy::NoProxy);
+        QNetworkProxy::setApplicationProxy(proxy);
+    }
+    else if(index==1)
+    {
+        bool ok;
+        QString text = QInputDialog::getText(visible_widget, tr("New proxy:"),
+                                          tr("proxy: "), QLineEdit::Normal,
+                                          "adress:port", &ok);
+        if(ok==true)
+        {
+            proxyCombo->addItem(text);
+            proxyCombo->setCurrentIndex(proxyCombo->count()-1);
+        }
+    }
+    else
+    {
+        QStringList string=proxyCombo->itemText(index).split(":");
+        QNetworkProxy proxy;
+        proxy.setType(QNetworkProxy::HttpProxy);
+        proxy.setHostName(string.at(0));
+        proxy.setPort(string.at(1).toInt());
+        QNetworkProxy::setApplicationProxy(proxy);
+        updateZoom(geoMap->zoomLevel());//refresh
+    }
+}
+
+void Map::SetUptodate(void) {
+    QList<Landmark*> *landmarks=mapWidget->Landmarks();
+    for(int i=0;i<landmarks->count();i++) {
+        RemoveAttribute("lat" +QString::number(i));
+        RemoveAttribute("long" +QString::number(i));
+
+        if(mapWidget->LandmarkToSend(i)) {
+            SetAttribute("lat" +QString::number( i ) ,landmarks->at(i)->coordinate().latitude());
+            SetAttribute("long" +QString::number( i ) ,landmarks->at(i)->coordinate().longitude());
+        }
+    }
+
+    mapWidget->SetUptodate();
+}
+
+bool Map::IsUptodate(void)
+{
+    return mapWidget->IsUptodate();
+}
+
+void Map::Reset(void)
+{
+    mapWidget->Reset();
+}
+
+void Map::setCenteredPoint(int i) {
+    centeredpoint=i;
+    if(isCentered()) geoMap->setCenter(points.at(i)->coordinate());
+}
+
+int Map::centeredPoint(void) {
+    return centeredpoint;
+}
+
+bool Map::isCentered(void) {
+    if(centeredpoint!=-1) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void Map::XmlEvent(QDomElement dom) {
+    if(dom.attribute("point")!="") {
+        receivesize+=3*sizeof(double);
+        if(mapWidget->isEnabled()) {
+            Landmark* landmark=new Landmark(geoMap,QGeoCoordinate(0,0,0),dom.attribute("point"),"cross");
+            landmark->setColor(Qt::black);
+            points.append(landmark);
+            mapWidget->AddPoint(dom.attribute("point"));
+        }
+    } else {
+        XmlSetup(dom);
+    }
+}
+
+void Map::BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian) {
+    if(IsEnabled()==false || RefreshRate_ms()!=period) return;
+
+    for(int i=0;i<points.count();i++) {
+        qint64 lat_raw;
+        double* lat=(double*)&lat_raw;
+        qint64 longitude_raw;
+        double* longitude=(double*)&longitude_raw;
+        qint64 alt_raw;
+        double* alt=(double*)&alt_raw;
+
+        memcpy(&lat_raw,*buf,sizeof(qint64));
+        *buf+=sizeof(qint64);
+        memcpy(&longitude_raw,*buf,sizeof(qint64));
+        *buf+=sizeof(qint64);
+        memcpy(&alt_raw,*buf,sizeof(qint64));
+        *buf+=sizeof(qint64);
+        if(big_endian==true) lat_raw=qFromBigEndian(lat_raw);
+        if(big_endian==true) longitude_raw=qFromBigEndian(longitude_raw);
+        if(big_endian==true) alt_raw=qFromBigEndian(alt_raw);
+        points.at(i)->setCoordinate(QGeoCoordinate(*lat,*longitude,*alt));
+
+        if(i==centeredpoint) geoMap->setCenter(points.at(i)->coordinate());
+    }
+}
+
+void Map::RemovePoints(void) {
+    for(int i=0;i<points.count();i++) {
+        points.at(i)->RemoveLandmark();
+    }
+}
+
+void Map::AddPoints(QGraphicsGeoMap *geoMap) {
+    for(int i=0;i<points.count();i++) {
+        points.at(i)->AddLandmark(geoMap);
+    }
+}
Index: trunk/tools/FlairGCS/src/Map.h
===================================================================
--- trunk/tools/FlairGCS/src/Map.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Map.h	(revision 9)
@@ -0,0 +1,68 @@
+#ifndef MAP_H
+#define MAP_H
+
+#include <stdint.h>
+#include "DataRemote.h"
+#include <QGeoCoordinate>
+#include <QGraphicsGeoMap>
+
+class Layout;
+class MapWidget;
+class QComboBox;
+class Landmark;
+class QToolButton;
+
+namespace QtMobility {
+    class QGeoMappingManager;
+    class QGraphicsGeoMap;
+    class QGeoServiceProvider;
+}
+
+class Map: public DataRemote
+{
+    Q_OBJECT
+
+    public:
+        Map(Layout* parent,int row, int col,QString name,QList<QtMobility::QGeoCoordinate> coordinates,bool enabled,int period);
+        ~Map();
+        void setCenteredPoint(int i);
+        int centeredPoint(void);
+        bool isCentered(void);
+
+    private:
+        MapWidget *mapWidget;
+        QtMobility::QGeoMappingManager *manager;
+        QList<QtMobility::QGeoMappingManager *> managers;
+        QtMobility::QGraphicsGeoMap *geoMap;
+        QtMobility::QGeoServiceProvider *service;
+        QComboBox *mapTypeCombo,*serviceCombo,*proxyCombo;
+        QHash<QtMobility::QGraphicsGeoMap::MapType, QString> mapTypes;
+        QToolButton *zoomin,*zoomout;
+        QAction *zoomInAction;
+        QAction *zoomOutAction;
+        QList<Landmark*> points;
+        int centeredpoint;
+
+        bool findServices(void);
+        void findproxy(void);
+        void populateMapTypeCombo();
+        bool IsUptodate(void);
+        void SetUptodate(void);
+        void Reset(void);
+        void XmlEvent(QDomElement dom);
+        void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian);
+
+        void RemovePoints(void);
+        void AddPoints(QtMobility::QGraphicsGeoMap *geoMap);
+
+    private slots:
+        void changeMapType(int index);
+        void selectService(int index);
+        void changeproxy(int index);
+        void updateZoom(qreal value);
+        void zoomIn(void);
+        void zoomOut(void);
+
+};
+
+#endif // MAP_H
Index: trunk/tools/FlairGCS/src/Picture.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Picture.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Picture.cpp	(revision 9)
@@ -0,0 +1,109 @@
+#include "Picture.h"
+#include "Layout.h"
+#include <QMenu>
+#include <QInputDialog>
+#include <QLabel>
+#include <QMouseEvent>
+#include <QGroupBox>
+#include <QVBoxLayout>
+
+Picture::Picture(Layout* parent,int row, int col,QString name,uint16_t width, uint16_t height,bool enabled,int period):DataRemote(name,"Picture",parent,enabled,period)
+{
+    box = new QGroupBox(name);
+    box->setObjectName(name);
+
+    parent->addWidget(box,row,col);
+
+    label=new QLabel();
+
+    layout = new QVBoxLayout;
+    layout->addWidget(label);
+    box->setLayout(layout);
+
+    visible_widget=box;
+
+    label->setAlignment(Qt::AlignCenter);
+
+    im_width=width;
+    im_height=height;
+    label->setMinimumSize(width,height);
+    label->setMaximumSize(width,height);
+    receivesize=width*height;
+
+    for(int i=0;i<256;i++)
+    {
+        color_table.append(qRgb(i,i,i));
+    }
+
+    label->installEventFilter(this);
+}
+
+
+Picture::~Picture()
+{
+    delete layout;
+}
+
+void Picture::BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian)
+{
+    if(big_endian) printf("Picture::BufEvent, big endian not handled\n");
+
+    if(IsEnabled()==false || RefreshRate_ms()!=period) return;
+
+    if((*buf_size)>=im_width*im_height)
+    {
+        QImage image= QImage((const uchar*)*buf,im_width,im_height,QImage::Format_Indexed8);//Format_RGB888);
+        *buf+=im_width*im_height;
+        image.setColorTable(color_table);
+
+        label->setPixmap(QPixmap::fromImage(image));
+    }
+    else
+        printf("buffer trop petit\n");
+}
+
+bool Picture::eventFilter(QObject *o, QEvent *e)
+{
+    if (  o == label )
+    {
+        switch(e->type())
+        {
+            case QEvent::MouseButtonPress:
+            {
+                mousePressEvent((QMouseEvent*)e);
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+    return label->eventFilter(o, e);
+}
+
+void Picture::mousePressEvent(QMouseEvent * event)
+{
+
+    if(event->x() > 0 && event->x() < label->width() &&
+       event->y() > 0 && event->y() < label->height() &&
+       event->button() == Qt::RightButton)
+    {
+
+        QMenu * menu = new QMenu("nom", label);
+        // ajout des actions
+        QAction *a,*z;
+
+        a=menu->addAction("get frame");
+        a->setEnabled(!auto_refresh);
+
+        appendmenu(menu);
+        z=execmenu(label,menu,event->globalPos());
+        delete menu;
+
+    }
+}
+
+void Picture::XmlEvent(QDomElement dom)
+{
+    XmlSetup(dom);
+}
Index: trunk/tools/FlairGCS/src/Picture.h
===================================================================
--- trunk/tools/FlairGCS/src/Picture.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Picture.h	(revision 9)
@@ -0,0 +1,41 @@
+#ifndef PICTURE_H
+#define PICTURE_H
+
+#include <stdint.h>
+#include "DataRemote.h"
+#include <QRgb>
+#include <QVector>
+
+class Layout;
+class QGroupBox;
+class QMouseEvent;
+class QLabel;
+class QVBoxLayout;
+
+class Picture: public DataRemote
+{
+    Q_OBJECT
+
+    public:
+        Picture(Layout* parent,int row, int col,QString name,uint16_t width, uint16_t height,bool enabled,int period);
+        ~Picture();
+
+    protected:
+        void mousePressEvent(QMouseEvent *event);
+
+    private:
+        QGroupBox* box;
+        QLabel *label;
+        QVBoxLayout *layout;
+        QVector<QRgb> color_table;
+        uint16_t im_width;
+        uint16_t im_height;
+
+        bool eventFilter(QObject *, QEvent *);
+        void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian);
+        void XmlEvent(QDomElement dom);
+
+
+};
+
+#endif // PICTURE_H
Index: trunk/tools/FlairGCS/src/PushButton.cpp
===================================================================
--- trunk/tools/FlairGCS/src/PushButton.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/PushButton.cpp	(revision 9)
@@ -0,0 +1,25 @@
+#include "PushButton.h"
+#include "ConnectionLayout.h"
+#include <QPushButton>
+
+PushButton::PushButton(Layout* parent,int row, int col,QString name):XmlWidget(name,"PushButton",parent)
+{
+    button=new QPushButton(name);
+    parent->addWidget(button,row,col);
+
+    SetValue("0");
+
+    connect(button, SIGNAL(clicked(bool)),this, SLOT(button_clicked(bool)));
+}
+
+PushButton::~PushButton()
+{
+    delete button;
+}
+
+void PushButton::button_clicked(bool state)
+{
+    SetValue("1");
+    connectionLayout()->XmlToSend(XmlDoc());
+    SetValue("0");
+}
Index: trunk/tools/FlairGCS/src/PushButton.h
===================================================================
--- trunk/tools/FlairGCS/src/PushButton.h	(revision 9)
+++ trunk/tools/FlairGCS/src/PushButton.h	(revision 9)
@@ -0,0 +1,25 @@
+#ifndef PUSHBUTTON_H
+#define PUSHBUTTON_H
+
+#include "XmlWidget.h"
+
+class QPushButton;
+class Layout;
+
+class PushButton: public XmlWidget
+{
+    Q_OBJECT
+
+    public:
+        PushButton(Layout* parent,int row, int col,QString name);
+        ~PushButton();
+
+    private:
+        QPushButton *button;
+
+    private slots:
+        void button_clicked(bool state);
+
+};
+
+#endif // PUSHBUTTON_H
Index: trunk/tools/FlairGCS/src/RangeFinderPlot.cpp
===================================================================
--- trunk/tools/FlairGCS/src/RangeFinderPlot.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/RangeFinderPlot.cpp	(revision 9)
@@ -0,0 +1,277 @@
+#include "RangeFinderPlot.h"
+#include "Layout.h"
+#include <stdlib.h>
+#include <qwt_plot_grid.h>
+#include <qwt_plot_magnifier.h>
+#include <qwt_scale_widget.h>
+#include <qwt_plot_panner.h>
+#include <qwt_plot_rescaler.h>
+#include <qwt_plot_shapeitem.h>
+#include <QMouseEvent>
+#include <QMenu>
+#include <QInputDialog>
+#include <qendian.h>
+#include <qmath.h>
+
+RangeFinderPlot::RangeFinderPlot(Layout* parent,int row, int col,QString name,
+                                 QString x_name,QString y_name,
+                                 float xmin, float xmax,float ymin, float ymax,
+                                 float start_angle,float end_angle,uint32_t nb_samples,QString data_type,
+                                 bool invert_axis,bool enabled,int period):
+    DataRemote(name,"RangeFinderPlot",parent,enabled,period)
+{
+    invert_axis=true;
+    this->start_angle=start_angle;
+    this->end_angle=end_angle;
+    this->nb_samples=nb_samples;
+    this->data_type=data_type;
+    this->invert_axis=invert_axis;
+
+    if(data_type=="float")
+    {
+        receivesize=nb_samples*sizeof(float);
+    }
+    else if(data_type=="int8_t")
+    {
+        receivesize=nb_samples*sizeof(int8_t);
+    }
+    else if(data_type=="int16_t")
+    {
+        receivesize=nb_samples*sizeof(int16_t);
+    }
+    else
+    {
+        printf("RangeFinderPlot::RangeFinderPlot unknown type %s\n",data_type.toLocal8Bit().constData());
+    }
+
+
+    plot=new QwtPlot(NULL);
+    plot->setEnabled(enabled);
+    //plot->setAutoReplot( false );
+
+    parent->addWidget(plot,row,col);
+    visible_widget=plot;
+
+    plot->setTitle(name);
+
+    // grid
+    QwtPlotGrid *grid = new QwtPlotGrid;
+    grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
+    grid->attach(plot);
+
+    plot->updateAxes();
+
+    //zoomer
+    QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(plot->canvas());
+    zoomer->setMouseButton(Qt::RightButton,Qt::ControlModifier);
+
+    //scroller
+    QwtPlotPanner *scroller =new QwtPlotPanner(plot->canvas());
+
+    // Axis
+    if(!invert_axis) {
+        plot->setAxisTitle(QwtPlot::xBottom, x_name);
+        setXAxisScale(xmin,xmax);
+
+        plot->setAxisTitle(QwtPlot::yLeft, y_name);
+        setYAxisScale(ymin,ymax);
+    } else {
+        plot->setAxisTitle(QwtPlot::xBottom, y_name);
+        setXAxisScale(ymin,ymax);
+
+        plot->setAxisTitle(QwtPlot::yLeft, x_name);
+        setYAxisScale(xmin,xmax);
+    }
+
+    QwtPlotRescaler* rescaler = new QwtPlotRescaler( plot->canvas() );
+    rescaler->setRescalePolicy( QwtPlotRescaler::Fixed );
+
+    //( void ) new QwtPlotMagnifier( plot->canvas() );
+
+    plot->canvas()->installEventFilter(this);
+
+    for(uint32_t i=0;i<nb_samples;i++)
+    {
+        addTriangle(start_angle+i*(end_angle-start_angle+1)/nb_samples,start_angle+(i+1)*(end_angle-start_angle+1)/nb_samples);
+    }
+}
+
+RangeFinderPlot::~RangeFinderPlot()
+{
+    delete plot;
+}
+
+void RangeFinderPlot::XmlEvent(QDomElement dom)
+{
+    XmlSetup(dom);
+}
+
+bool RangeFinderPlot::eventFilter(QObject *o, QEvent *e)
+{
+    if (o==plot->canvas())
+    {
+        switch(e->type())
+        {
+            case QEvent::MouseButtonPress:
+            {
+                mousePressEvent((QMouseEvent*)e);
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+    return plot->eventFilter(o, e);
+}
+
+
+//
+//  Set a plain canvas frame and align the scales to it
+//
+void RangeFinderPlot::alignScales(void)
+{
+    // The code below shows how to align the scales to
+    // the canvas frame, but is also a good example demonstrating
+    // why the spreaded API needs polishing.
+/*
+    plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
+    plot->canvas()->setLineWidth(1);
+*/
+    for ( int i = 0; i < QwtPlot::axisCnt; i++ )
+    {
+        QwtScaleWidget *scaleWidget = (QwtScaleWidget *)plot->axisWidget(i);
+        if ( scaleWidget )
+            scaleWidget->setMargin(0);
+
+        QwtScaleDraw *scaleDraw = (QwtScaleDraw *)plot->axisScaleDraw(i);
+        if ( scaleDraw )
+            scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
+    }
+}
+
+void RangeFinderPlot::setXAxisScale(float xmin,float xmax)
+{
+    xmin_orig=xmin;
+    xmax_orig=xmax;
+    plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
+
+}
+
+void RangeFinderPlot::setYAxisScale(float ymin,float ymax)
+{
+    ymin_orig=ymin;
+    ymax_orig=ymax;
+    plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
+}
+
+void RangeFinderPlot::BufEvent(char **buf,int *buf_size,uint16_t period,bool big_endian)
+{
+    plot->setEnabled(IsEnabled());
+    if(IsEnabled()==false || RefreshRate_ms()!=period) return;
+
+    for(uint32_t i=0;i<nb_samples;i++)
+    {
+        if(data_type=="float")
+        {
+            uint32_t data_raw;
+            float* data=(float*)&data_raw;
+
+            memcpy((void*)&data_raw,*buf,sizeof(uint32_t));
+            *buf+=sizeof(uint32_t);
+            if(big_endian==true) data_raw=qFromBigEndian(data_raw);
+            SetTriangle(i,*data);
+        }
+        else if(data_type=="int8_t")
+        {
+            int8_t data;
+            memcpy((void*)&data,*buf,sizeof(data));
+            *buf+=sizeof(data);
+            SetTriangle(i,data);
+        }
+        else if(data_type=="int16_t")
+        {
+            int16_t data;
+            memcpy((void*)&data,*buf,sizeof(data));
+            *buf+=sizeof(data);
+            if(big_endian==true) data=qFromBigEndian(data);
+            SetTriangle(i,data);
+        }
+        else
+        {
+            printf("RangeFinderPlot::BufEvent unknown type %s\n",data_type.toLocal8Bit().constData());
+        }
+     }
+
+    plot->replot();
+}
+
+void RangeFinderPlot::addTriangle(float angle_min, float angle_max)
+{
+    QwtPlotShapeItem *item = new QwtPlotShapeItem();
+
+    item->setRenderHint( QwtPlotItem::RenderAntialiased, true );
+    item->attach(plot);
+    triangles.append(item);
+
+}
+
+void RangeFinderPlot::SetTriangle(uint32_t id,float length)
+{
+    QPainterPath path;
+    QPolygonF triangle;
+    float angle_min=start_angle+id*(end_angle-start_angle+1)/nb_samples;
+    float angle_max=start_angle+(id+1)*(end_angle-start_angle+1)/nb_samples;
+
+    if(invert_axis) {
+        angle_min=90-angle_min;
+        angle_max=90-angle_max;
+    }
+
+    triangle += QPointF( 0,0 );
+    triangle += QPointF( length*cos(angle_min*M_PI/180.),length*sin(angle_min*M_PI/180.) );
+    triangle += QPointF( length*cos(angle_max*M_PI/180.),length*sin(angle_max*M_PI/180.) );
+
+    path.addPolygon( triangle );
+
+    path.closeSubpath();
+    triangles.at(id)->setShape(path);
+
+    QColor fillColor = "SandyBrown";
+    fillColor.setAlpha( 200 );
+
+    QPen pen( QColor("SandyBrown"), 1 );
+    pen.setJoinStyle( Qt::MiterJoin );
+    triangles.at(id)->setPen( pen );
+    triangles.at(id)->setBrush( fillColor );
+}
+
+//context menu
+void RangeFinderPlot::mousePressEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::RightButton)
+    {
+        QMenu *menu = new QMenu("nom", plot);
+        // ajout des actions
+        QAction *a,*z;
+
+        a=menu->addAction("reset y zoom");
+
+        appendmenu(menu);
+        z=execmenu(plot,menu,event->globalPos());
+        delete menu;
+
+        if(z==a)
+        {
+            //zoom to original size
+            if(!invert_axis) {
+                plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
+            } else {
+                plot->setAxisScale(QwtPlot::yLeft, xmin_orig, xmax_orig);
+            }
+            plot->replot();
+        }
+    }
+}
+
+
Index: trunk/tools/FlairGCS/src/RangeFinderPlot.h
===================================================================
--- trunk/tools/FlairGCS/src/RangeFinderPlot.h	(revision 9)
+++ trunk/tools/FlairGCS/src/RangeFinderPlot.h	(revision 9)
@@ -0,0 +1,46 @@
+#ifndef RANGEFINDERPLOT_H_INCLUDED
+#define RANGEFINDERPLOT_H_INCLUDED
+
+#include "DataRemote.h"
+#include <stdint.h>
+
+class QwtPlotShapeItem;
+class Layout;
+class QwtPlot;
+class QMouseEvent;
+
+class RangeFinderPlot :  public DataRemote
+{
+    Q_OBJECT
+
+    public:
+        RangeFinderPlot(Layout* parent,int row, int col,QString name,QString x_name,QString y_name,
+                        float xmin, float xmax,float ymin, float ymax,
+                        float start_angle,float end_angle,uint32_t nb_samples,QString data_type,
+                        bool invert_axis,bool enabled,int period);
+        ~RangeFinderPlot();
+
+    protected:
+         void mousePressEvent(QMouseEvent *event);
+
+    private:
+        void setYAxisScale(float ymin,float ymax);
+        void setXAxisScale(float xmin,float xmax);
+        void addTriangle(float angle_min, float angle_max);
+        void SetTriangle(uint32_t id,float length);
+        QwtPlot* plot;
+        void XmlEvent(QDomElement dom);
+        void alignScales(void);
+        float xmin_orig,xmax_orig,ymin_orig,ymax_orig;
+        float start_angle,end_angle;
+        uint32_t nb_samples;
+        QString data_type;
+        QList<QwtPlotShapeItem*> triangles;
+        bool invert_axis;
+
+        bool eventFilter(QObject *, QEvent *);
+        void BufEvent(char** buf,int *buf_size,uint16_t period,bool big_endian);
+};
+
+
+#endif // RANGEFINDERPLOT_H_INCLUDED
Index: trunk/tools/FlairGCS/src/Scope.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Scope.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Scope.cpp	(revision 9)
@@ -0,0 +1,276 @@
+#include "Scope.h"
+#include "Scrollbar.h"
+#include <qwt_plot_curve.h>
+#include <qwt_plot_grid.h>
+#include <qwt_plot_magnifier.h>
+#include <qwt_plot_canvas.h>
+#include <qwt_scale_widget.h>
+#include <qwt_legend_label.h>
+#include <qwt_legend.h>
+#include <qwt_plot_panner.h>
+#include <QMouseEvent>
+#include <QMenu>
+#include <QTimer>
+#include <QTime>
+#include <QApplication>
+
+#define WHEEL_DIVIDOR 30
+
+Scope::Scope(QString title,float ymin,float ymax,float view_size_s,unsigned int refresh_rate_ms,unsigned int history_size): QwtPlot() {
+    this->ymin=ymin;
+    this->ymax=ymax;
+    this->history_size=history_size;
+    this->view_size_s=view_size_s;
+    orig_view_size_s=view_size_s;
+
+    //scroll bar
+    scrollbar=new ScrollBar(Qt::Horizontal,canvas());
+    connect(scrollbar,SIGNAL(valueChanged(Qt::Orientation,float,float)),this,SLOT(scrollBarMoved(Qt::Orientation,float,float)));
+    scrolling=true;
+
+    //minimum size; sinon widget trop grand
+    setMinimumHeight(10);
+    setMinimumWidth(1);
+
+    alignScales();//is it necessary?
+
+    //  Initialize data
+    elapsed_time_s=0;
+
+    // Assign a title
+    setTitle(title);
+
+    // Axis
+    setAxisTitle(QwtPlot::xBottom, "Time (s)");
+    setAxisScale(QwtPlot::xBottom,0, view_size_s);
+
+    setAxisTitle(QwtPlot::yLeft, "Values");
+    setAxisScale(QwtPlot::yLeft, ymin, ymax);
+
+    // grid
+    QwtPlotGrid *grid = new QwtPlotGrid;
+    grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
+    grid->attach(this);
+
+    //zoomer
+    QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(canvas());
+    zoomer->setWheelModifiers( Qt::ControlModifier );
+    zoomer->setMouseButton(Qt::NoButton);
+    zoomer->setAxisEnabled(xBottom,0);
+
+    //scroller
+    QwtPlotPanner *scroller =new QwtPlotPanner(canvas());
+    scroller->setAxisEnabled(xBottom,0);
+
+    //legend
+    QwtLegend* new_legend=new QwtLegend();
+    new_legend->setDefaultItemMode(QwtLegendData::Checkable);
+    insertLegend(new_legend, QwtPlot::BottomLegend);
+
+    connect( new_legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( legendChecked( const QVariant &, bool ) ) );
+
+    QTimer *timer = new QTimer(this);
+    connect(timer, SIGNAL(timeout()), this, SLOT(replot()));
+    timer->start(refresh_rate_ms);
+}
+
+Scope::~Scope() {
+    for(int i=0;i<curves.count();i++) {
+        free(curves.at(i)->data_x);
+        free(curves.at(i)->data_y);
+        delete curves.at(i)->plot;
+        free(curves.at(i));
+    }
+}
+
+void Scope::resetXView(void) {
+    //setAxisScale(QwtPlot::xBottom,0, orig_view_size_s);
+    changeViewSize(orig_view_size_s);
+}
+
+void Scope::resetYView(void) {
+    setAxisScale(QwtPlot::yLeft, ymin, ymax);
+}
+
+bool Scope::eventFilter(QObject *o, QEvent *e) {
+    switch(e->type()) {
+        case QEvent::Resize: {
+            const int fw = ((QwtPlotCanvas *)canvas())->frameWidth();
+
+            QRect rect;
+            rect.setSize(((QResizeEvent *)e)->size());
+            rect.setRect(rect.x() + fw, rect.y() + fw,
+                rect.width() - 2 * fw, rect.height() - 2 * fw);
+
+            scrollbar->setGeometry(0, 0, rect.width(), 10);
+            return true;
+        }
+        case QEvent::Wheel: {
+            //ctrl+wheel is already handled for y zoom
+            if(!(QApplication::keyboardModifiers() & Qt::ControlModifier)) {
+                QWheelEvent *wheelevent = static_cast<QWheelEvent *> (e);
+                if(view_size_s+wheelevent->delta()/WHEEL_DIVIDOR>0) changeViewSize(view_size_s+wheelevent->delta()/WHEEL_DIVIDOR);
+            }
+            return true;
+        }
+        default:
+            break;
+    }
+    return QwtPlot::eventFilter(o, e);
+}
+
+void Scope::changeViewSize(float new_view_size_s) {
+    view_size_s=new_view_size_s;
+
+    if(scrolling==false) {
+        //4 cas: on utilise le temps au milieu de la vue actuelle
+
+        //le temps total est plus petit que le view_size_s, on affiche tout:
+        if(elapsed_time_s<view_size_s) {
+            scrolling=true;
+        } else {
+            double min=(min_scroll+max_scroll)/2-view_size_s/2;
+            double max=(min_scroll+max_scroll)/2+view_size_s/2;
+            //on va du debut jusqu'a view size
+            if( min<0) {
+                min=0;
+                max=view_size_s;
+            }
+            //on va de fin-viewsize jusqu'a la fin
+            if(max>elapsed_time_s) {
+                min=elapsed_time_s-view_size_s;
+                max=elapsed_time_s;
+            }
+            scrollbar->moveSlider(min,max);//move slider coupe le signal, on fait aussi le scrollbar
+            scrollBarMoved(Qt::Horizontal,min,max);
+        }
+    }
+}
+
+void Scope::legendChecked( const QVariant &itemInfo, bool on ) {
+    QwtPlotItem *plotItem=infoToItem(itemInfo);
+    if(plotItem) showCurve( plotItem, on );
+}
+
+void Scope::showCurve(QwtPlotItem *item, bool on) {
+    item->setVisible(on);
+
+    QwtLegend *lgd=qobject_cast<QwtLegend*>(legend());
+
+    QList<QWidget*> legendWidgets=lgd->legendWidgets(itemToInfo(item));
+
+    if(legendWidgets.size()==1) {
+        QwtLegendLabel *legendLabel=qobject_cast<QwtLegendLabel*>(legendWidgets[0]);
+
+        if(legendLabel) legendLabel->setChecked( on );
+    }
+}
+
+int Scope::addCurve(QPen pen,QString legend) {
+    Curve* curve=(Curve*)malloc(sizeof(Curve));
+    curve->data_x=(double*)calloc(history_size,sizeof(double));
+    curve->data_y=(double*)calloc(history_size,sizeof(double));
+    curve->index=0;
+    curve->min_index=0;
+    curve->max_index=0;
+
+    // Insert new curve
+    curve->plot=new QwtPlotCurve(legend);
+    curve->plot->attach(this);
+    curve->plot->setPen(pen);
+    curves.append(curve);
+
+    showCurve(curve->plot, true);
+
+    return curves.count()-1;
+}
+
+void Scope::updateCurve(Curve* curve) {
+        if(scrolling==true) {
+        curve->plot->setRawSamples(&curve->data_x[curve->min_index], &curve->data_y[curve->min_index], curve->max_index-curve->min_index);
+    }
+
+    if(curve->index==history_size) {
+        //printf("a revoir qd on arrive a la fin, il faudrait faire un realloc pour rien perdre\n");
+        //attention le setrawdata s'attend a ce que l'adresse change pas, ce qui n'est pas le cas avec lerealloc
+        //il faudra refaire un setrawdata ici
+        curve->index=0;
+        curve->min_index=0;
+        scrolling=true;
+    }
+
+    //determine les index pour la visualisation
+    if(scrolling==true) {
+        curve->max_index=curve->index;
+        computeMinIndex(curve,elapsed_time_s-view_size_s);
+    }
+
+    scrollbar->setBase(0,elapsed_time_s);
+    if(scrolling==true) {
+        scrollbar->moveSlider(elapsed_time_s-view_size_s,elapsed_time_s);
+
+        if(elapsed_time_s<view_size_s) {
+            setAxisScale(QwtPlot::xBottom,0, view_size_s);
+        } else {
+            setAxisScale(QwtPlot::xBottom,elapsed_time_s-view_size_s, elapsed_time_s);
+        }
+    } else {
+        scrollbar->moveSlider(min_scroll,max_scroll);
+    }
+}
+
+void Scope::alignScales(void) {
+    // The code below shows how to align the scales to
+    // the canvas frame, but is also a good example demonstrating
+    // why the spreaded API needs polishing.
+/*
+    plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
+    plot->canvas()->setLineWidth(1);
+*/
+    for(int i = 0;i<QwtPlot::axisCnt;i++) {
+        QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i);
+        if(scaleWidget) scaleWidget->setMargin(0);
+
+        QwtScaleDraw *scaleDraw=(QwtScaleDraw *)axisScaleDraw(i);
+        if(scaleDraw) scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
+    }
+}
+
+void Scope::scrollBarMoved(Qt::Orientation o, float min, float max)
+{
+    min_scroll=min;
+    max_scroll=max;
+
+    if(max==scrollbar->maxBaseValue()) {
+        scrolling=true;
+    } else {
+        scrolling=false;
+        setAxisScale(QwtPlot::xBottom,min,max);
+
+        //determine les index pour la visualisation
+        for(int i=0;i<curves.count();i++) {
+            computeMinIndex(curves.at(i),min);
+            computeMaxIndex(curves.at(i),max);
+            curves.at(i)->plot->setRawSamples(&curves.at(i)->data_x[curves.at(i)->min_index], &curves.at(i)->data_y[curves.at(i)->min_index], curves.at(i)->max_index-curves.at(i)->min_index);
+        }
+    }
+}
+
+//TODO: faire une dichotomie
+void Scope::computeMinIndex(Curve* curve,float displayed_min_time) {
+    if(curve->data_x[curve->index]>displayed_min_time) {
+        if(curve->data_x[curve->min_index]<displayed_min_time) {
+            while(curve->data_x[curve->min_index]<displayed_min_time && curve->min_index!=curve->index) curve->min_index++;
+        } else {
+            while(curve->data_x[curve->min_index]>displayed_min_time && curve->min_index!=0) curve->min_index--;
+        }
+    }
+}
+
+void Scope::computeMaxIndex(Curve* curve,float displayed_max_time) {
+    if(curve->data_x[curve->max_index]<displayed_max_time) {
+        while(curve->data_x[curve->max_index]<displayed_max_time && curve->max_index!=curve->index) curve->max_index++;
+    } else {
+        while(curve->data_x[curve->max_index]>displayed_max_time) curve->max_index--;
+    }
+}
Index: trunk/tools/FlairGCS/src/Scope.h
===================================================================
--- trunk/tools/FlairGCS/src/Scope.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Scope.h	(revision 9)
@@ -0,0 +1,57 @@
+#ifndef SCOPE_H_INCLUDED
+#define SCOPE_H_INCLUDED
+
+#include <qwt_plot.h>
+#include <QPen>
+
+class ScrollBar;
+class QwtPlotCurve;
+class QwtPlotItem;
+class QMouseEvent;
+
+class Scope: public QwtPlot {
+    Q_OBJECT
+
+    public:
+        Scope(QString title,float ymin, float ymax,float view_size_s=20,unsigned int refresh_rate_ms=40,unsigned int history_size=20000);
+        ~Scope();
+        int addCurve(QPen pen,QString legend);
+        void resetXView(void);
+        void resetYView(void);
+
+    protected:
+        struct Curve {
+            QwtPlotCurve* plot;
+            double* data_x;
+            double* data_y;
+            unsigned int index;
+            unsigned int min_index;
+            unsigned int max_index;
+        };
+        QList<Curve*> curves;
+        float elapsed_time_s;
+
+        void updateCurve(Curve* curve);
+        bool eventFilter(QObject *, QEvent *);
+
+    private:
+        float ymin,ymax;
+        float view_size_s,orig_view_size_s;
+        unsigned int history_size;
+        ScrollBar* scrollbar;
+        bool scrolling;
+        float min_scroll,max_scroll;
+
+        void alignScales(void);
+        void showCurve(QwtPlotItem *item, bool on);
+        void computeMinIndex(Curve* curve,float displayed_min_time);
+        void computeMaxIndex(Curve* curve,float displayed_max_time);
+        void changeViewSize(float new_view_size_s);
+
+    private slots:
+        void legendChecked(const QVariant &itemInfo, bool on );
+        void scrollBarMoved(Qt::Orientation o, float min, float max);
+};
+
+
+#endif // SCOPE_H_INCLUDED
Index: trunk/tools/FlairGCS/src/ScopeFixedStep.cpp
===================================================================
--- trunk/tools/FlairGCS/src/ScopeFixedStep.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/ScopeFixedStep.cpp	(revision 9)
@@ -0,0 +1,24 @@
+#include "ScopeFixedStep.h"
+#include "Scrollbar.h"
+#include <qwt_plot_curve.h>
+
+ScopeFixedStep::ScopeFixedStep(QString title,float ymin,float ymax,float step_s,float view_size_s,unsigned int refresh_rate_ms,unsigned int history_size): Scope(title,ymin,ymax,view_size_s,refresh_rate_ms,history_size) {
+    this->step_s=step_s;
+}
+
+ScopeFixedStep::~ScopeFixedStep() {
+
+}
+
+void ScopeFixedStep::plot(double* value) {
+    elapsed_time_s+=step_s;
+    for(int i=0;i<curves.count();i++) {
+        Curve* curve=curves.at(i);
+
+        curve->data_x[curve->index]=elapsed_time_s;
+        curve->data_y[curve->index]=value[i];
+        curve->index++;
+
+        updateCurve(curve);
+    }
+}
Index: trunk/tools/FlairGCS/src/ScopeFixedStep.h
===================================================================
--- trunk/tools/FlairGCS/src/ScopeFixedStep.h	(revision 9)
+++ trunk/tools/FlairGCS/src/ScopeFixedStep.h	(revision 9)
@@ -0,0 +1,18 @@
+#ifndef SCOPEFIXEDSTEP_H_INCLUDED
+#define SCOPEFIXEDSTEP_H_INCLUDED
+
+#include <Scope.h>
+
+
+class ScopeFixedStep: public Scope {
+    public:
+        ScopeFixedStep(QString title,float ymin, float ymax,float step_s,float view_size_s=20,unsigned int refresh_rate_ms=40,unsigned int history_size=20000);
+        ~ScopeFixedStep();
+        void plot(double* value);
+
+    protected:
+        float step_s;
+};
+
+
+#endif // SCOPEFIXEDSTEP_H_INCLUDED
Index: trunk/tools/FlairGCS/src/ScopeVariableStep.cpp
===================================================================
--- trunk/tools/FlairGCS/src/ScopeVariableStep.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/ScopeVariableStep.cpp	(revision 9)
@@ -0,0 +1,24 @@
+#include "ScopeVariableStep.h"
+#include "Scrollbar.h"
+#include <QTime>
+#include <qwt_plot_curve.h>
+
+ScopeVariableStep::ScopeVariableStep(QString title,float ymin,float ymax,float view_size_s,unsigned int refresh_rate_ms,unsigned int history_size): Scope(title,ymin,ymax,view_size_s,refresh_rate_ms,history_size) {
+
+}
+
+ScopeVariableStep::~ScopeVariableStep() {
+
+}
+
+void ScopeVariableStep::plot(double value,QTime time,unsigned int curve_index) {
+    static QTime start_time=QTime::currentTime();
+    Curve* curve=curves.at(curve_index);
+
+    elapsed_time_s=start_time.msecsTo(time)/1000.;
+    curve->data_x[curve->index]=elapsed_time_s;
+    curve->data_y[curve->index]=value;
+    curve->index++;
+
+    updateCurve(curve);
+}
Index: trunk/tools/FlairGCS/src/ScopeVariableStep.h
===================================================================
--- trunk/tools/FlairGCS/src/ScopeVariableStep.h	(revision 9)
+++ trunk/tools/FlairGCS/src/ScopeVariableStep.h	(revision 9)
@@ -0,0 +1,17 @@
+#ifndef SCOPEVARIABLESTEP_H_INCLUDED
+#define SCOPEVARIABLESTEP_H_INCLUDED
+
+#include <Scope.h>
+
+class ScopeVariableStep: public Scope {
+    public:
+        ScopeVariableStep(QString title,float ymin, float ymax,float view_size_s=20,unsigned int refresh_rate_ms=40,unsigned int history_size=20000);
+        ~ScopeVariableStep();
+        void plot(double value,QTime time,unsigned int curve_index=0);
+
+    private:
+
+};
+
+
+#endif // SCOPEVARIABLESTEP_H_INCLUDED
Index: trunk/tools/FlairGCS/src/Scrollbar.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Scrollbar.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Scrollbar.cpp	(revision 9)
@@ -0,0 +1,169 @@
+#include <qstyle.h>
+#include <qstyleoption.h>
+#include "Scrollbar.h"
+
+ScrollBar::ScrollBar(QWidget * parent):
+    QScrollBar(parent)
+{
+    init();
+}
+
+ScrollBar::ScrollBar(Qt::Orientation o,
+        QWidget *parent):
+    QScrollBar(o, parent)
+{
+    init();
+}
+
+ScrollBar::ScrollBar(float minBase, float maxBase,
+        Qt::Orientation o, QWidget *parent):
+    QScrollBar(o, parent)
+{
+    init();
+    setBase(minBase, maxBase);
+    moveSlider(minBase, maxBase);
+}
+
+void ScrollBar::init(void)
+{
+    d_inverted = orientation() == Qt::Vertical;
+    d_baseTicks = 1000000;
+    d_minBase = 0.0;
+    d_maxBase = 1.0;
+    moveSlider(d_minBase, d_maxBase);
+
+    connect(this, SIGNAL(sliderMoved(int)), SLOT(catchSliderMoved(int)));
+    connect(this, SIGNAL(valueChanged(int)), SLOT(catchValueChanged(int)));
+}
+
+void ScrollBar::setInverted(bool inverted)
+{
+    if ( d_inverted != inverted )
+    {
+        d_inverted = inverted;
+        moveSlider(minSliderValue(), maxSliderValue());
+    }
+}
+
+bool ScrollBar::isInverted(void) const
+{
+    return d_inverted;
+}
+
+void ScrollBar::setBase(float min, float max)
+{
+    if ( min != d_minBase || max != d_maxBase )
+    {
+        d_minBase = min;
+        d_maxBase = max;
+
+        moveSlider(minSliderValue(), maxSliderValue());
+    }
+}
+
+void ScrollBar::moveSlider(float min, float max)
+{
+    const int sliderTicks = qRound((max - min) /
+        (d_maxBase - d_minBase) * d_baseTicks);
+
+    // setRange initiates a valueChanged of the scrollbars
+    // in some situations. So we block
+    // and unblock the signals.
+
+    blockSignals(true);
+
+    setRange(sliderTicks / 2, d_baseTicks - sliderTicks / 2);
+    int steps = sliderTicks / 200;
+    if ( steps <= 0 )
+        steps = 1;
+
+    setSingleStep(steps);
+    setPageStep(sliderTicks);
+
+    int tick = mapToTick(min + (max - min) / 2);
+    if ( isInverted() )
+        tick = d_baseTicks - tick;
+
+    setSliderPosition(tick);
+    blockSignals(false);
+}
+
+float ScrollBar::minBaseValue(void) const
+{
+    return d_minBase;
+}
+
+float ScrollBar::maxBaseValue(void) const
+{
+    return d_maxBase;
+}
+
+void ScrollBar::sliderRange(int value, float &min, float &max) const
+{
+    if ( isInverted() )
+        value = d_baseTicks - value;
+
+    const int visibleTicks = pageStep();
+
+    min = mapFromTick(value - visibleTicks / 2);
+    max = mapFromTick(value + visibleTicks / 2);
+}
+
+float ScrollBar::minSliderValue(void) const
+{
+    float min, dummy;
+    sliderRange(value(), min, dummy);
+
+    return min;
+}
+
+float ScrollBar::maxSliderValue(void) const
+{
+    float max, dummy;
+    sliderRange(value(), dummy, max);
+
+    return max;
+}
+
+int ScrollBar::mapToTick(float v) const
+{
+    return (int) ( ( v - d_minBase) / (d_maxBase - d_minBase ) * d_baseTicks );
+}
+
+float ScrollBar::mapFromTick(int tick) const
+{
+    return d_minBase + ( d_maxBase - d_minBase ) * tick / d_baseTicks;
+}
+
+void ScrollBar::catchValueChanged(int value)
+{
+    float min, max;
+    sliderRange(value, min, max);
+    Q_EMIT valueChanged(orientation(), min, max);
+}
+
+void ScrollBar::catchSliderMoved(int value)
+{
+    float min, max;
+    sliderRange(value, min, max);
+    Q_EMIT sliderMoved(orientation(), min, max);
+}
+
+int ScrollBar::extent(void) const
+{
+    QStyleOptionSlider opt;
+    opt.init(this);
+    opt.subControls = QStyle::SC_None;
+    opt.activeSubControls = QStyle::SC_None;
+    opt.orientation = orientation();
+    opt.minimum = minimum();
+    opt.maximum = maximum();
+    opt.sliderPosition = sliderPosition();
+    opt.sliderValue = value();
+    opt.singleStep = singleStep();
+    opt.pageStep = pageStep();
+    opt.upsideDown = invertedAppearance();
+    if (orientation() == Qt::Horizontal)
+        opt.state |= QStyle::State_Horizontal;
+    return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
+}
Index: trunk/tools/FlairGCS/src/Scrollbar.h
===================================================================
--- trunk/tools/FlairGCS/src/Scrollbar.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Scrollbar.h	(revision 9)
@@ -0,0 +1,53 @@
+#ifndef _SCROLLBAR_H
+#define _SCROLLBAR_H 1
+
+#include <qscrollbar.h>
+
+class ScrollBar: public QScrollBar
+{
+    Q_OBJECT
+
+public:
+    ScrollBar(QWidget *parent = NULL);
+    ScrollBar(Qt::Orientation, QWidget *parent = NULL);
+    ScrollBar(float minBase, float maxBase,
+        Qt::Orientation o, QWidget *parent = NULL);
+
+    void setInverted(bool);
+    bool isInverted(void) const;
+
+    float minBaseValue(void) const;
+    float maxBaseValue(void) const;
+
+    float minSliderValue(void) const;
+    float maxSliderValue(void) const;
+
+    int extent(void) const;
+
+Q_SIGNALS:
+    void sliderMoved(Qt::Orientation, float, float);
+    void valueChanged(Qt::Orientation, float, float);
+
+public Q_SLOTS:
+    virtual void setBase(float min, float max);
+    virtual void moveSlider(float min, float max);
+
+protected:
+    void sliderRange(int value, float &min, float &max) const;
+    int mapToTick(float) const;
+    float mapFromTick(int) const;
+
+private Q_SLOTS:
+    void catchValueChanged(int value);
+    void catchSliderMoved(int value);
+
+private:
+    void init(void);
+
+    bool d_inverted;
+    float d_minBase;
+    float d_maxBase;
+    int d_baseTicks;
+};
+
+#endif
Index: trunk/tools/FlairGCS/src/SpinBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/SpinBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/SpinBox.cpp	(revision 9)
@@ -0,0 +1,69 @@
+#include "SpinBox.h"
+#include <QFormLayout>
+#include "Layout.h"
+#include <QSpinBox>
+
+SpinBox::SpinBox(Layout* parent,int row, int col,QString name,QString suffix,int value,int min,int max,int step): FormLayout(parent,row,col,name,"SpinBox")
+{
+    spinbox = new QSpinBox();
+
+    spinbox->setRange(min,max);
+    spinbox->setSingleStep(step);
+    spinbox->setValue(value);
+    spinbox->setSuffix(suffix);
+    spinbox_value=value;
+
+    object_layout->addRow(name,spinbox);
+
+    connect(spinbox,SIGNAL(valueChanged(int)),this, SLOT(valuechanged(int)));
+
+    SetValue(QString::number(spinbox_value));
+}
+
+SpinBox::~SpinBox()
+{
+    delete spinbox;
+}
+
+void SpinBox::SetUptodate(void)
+{
+    ui_to_var();
+    ui_to_xml();
+    visible_widget->setPalette(black_pal);
+
+}
+
+void SpinBox::ui_to_var(void)
+{
+    spinbox_value=spinbox->value();
+}
+
+void SpinBox::ui_to_xml(void)
+{
+    SetValue(QString::number(spinbox->value()));
+}
+
+void SpinBox::Reset(void)
+{
+    spinbox->setValue(spinbox_value);
+}
+
+void SpinBox::LoadEvent(QDomElement dom)
+{
+    if(spinbox->isEnabled()==true)
+    {
+        spinbox->setValue((dom.attribute("value")).toInt());
+    }
+}
+
+void SpinBox::valuechanged(int value)
+{
+    if(value!=spinbox_value)
+    {
+        visible_widget->setPalette(red_pal);
+    }
+    else
+    {
+        visible_widget->setPalette(black_pal);
+    }
+}
Index: trunk/tools/FlairGCS/src/SpinBox.h
===================================================================
--- trunk/tools/FlairGCS/src/SpinBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/SpinBox.h	(revision 9)
@@ -0,0 +1,31 @@
+#ifndef SPINBOX_H
+#define SPINBOX_H
+
+#include "FormLayout.h"
+
+class Layout;
+class QSpinBox;
+
+class SpinBox: public FormLayout
+{
+    Q_OBJECT
+
+    public:
+        SpinBox(Layout* parent,int row, int col,QString name,QString suffix,int value,int min,int max,int step);
+        ~SpinBox();
+
+    private:
+        QSpinBox* spinbox;
+        int spinbox_value;
+        void SetUptodate(void);
+        void Reset(void);
+        void LoadEvent(QDomElement dom);
+
+        void ui_to_var(void);
+        void ui_to_xml(void);
+
+    private slots:
+        void valuechanged(int value);
+};
+
+#endif // SPINBOX_H
Index: trunk/tools/FlairGCS/src/Tab.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Tab.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Tab.cpp	(revision 9)
@@ -0,0 +1,18 @@
+#include "Tab.h"
+#include "TabWidget.h"
+#include <QGridLayout>
+
+Tab::Tab(TabWidget* parent,QString name,int position): Layout(new QWidget(),parent,name,"Tab") {
+    parent_tab=parent;
+    onglet = getQGridLayout()->parentWidget();
+    onglet->setObjectName(name);
+    if(position==-1) {
+        parent->tab->addTab(onglet, name);
+    } else {
+        parent->tab->insertTab(position,onglet, name);
+    }
+}
+
+Tab::~Tab() {
+    parent_tab->tab->removeTab(parent_tab->tab->indexOf(onglet));
+}
Index: trunk/tools/FlairGCS/src/Tab.h
===================================================================
--- trunk/tools/FlairGCS/src/Tab.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Tab.h	(revision 9)
@@ -0,0 +1,21 @@
+#ifndef TAB_H
+#define TAB_H
+
+#include "Layout.h"
+
+class TabWidget;
+
+class Tab: public Layout
+{
+
+    public:
+        Tab(TabWidget* parent,QString name,int position);
+        ~Tab();
+
+    private:
+        TabWidget *parent_tab;
+        QWidget* onglet;
+
+};
+
+#endif // TAB_H
Index: trunk/tools/FlairGCS/src/TabWidget.cpp
===================================================================
--- trunk/tools/FlairGCS/src/TabWidget.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/TabWidget.cpp	(revision 9)
@@ -0,0 +1,46 @@
+#include "TabWidget.h"
+#include "Tab.h"
+#include <stdio.h>
+#include "Layout.h"
+
+//#include "qledindicator.h"
+
+TabWidget::TabWidget(Layout* parent,int row,int col,QString name,QTabWidget::TabPosition position):XmlWidget(name,"TabWidget",parent)
+{
+    tab=new QTabWidget();
+//tab->setTabShape(QTabWidget::Triangular);
+//tab->setDocumentMode(true);
+    parent->addWidget(tab,row,col);
+    tab->setTabPosition(position);
+    SetIsContainer(true);
+    SetIsExpandable(true);
+    visible_widget=tab;
+
+    //QLedIndicator* led=new QLedIndicator(tab);
+    //tab->setCornerWidget(led,Qt::TopLeftCorner);
+}
+
+TabWidget::~TabWidget()
+{
+}
+
+void TabWidget::XmlEvent(QDomElement dom)
+{
+    QString type=dom.tagName();
+    QString name=dom.attribute("name");
+    int position=dom.attribute("position").toInt();
+
+    if(type=="Tab")
+    {
+        Tab* layout = new Tab(this,name,position);
+    }
+}
+
+bool TabWidget::IsUptodate(void)
+{
+    for(int i=0;i<childs->count();i++)
+    {
+        if(childs->at(i)->IsUptodate()==false) return false;
+    }
+    return true;
+}
Index: trunk/tools/FlairGCS/src/TabWidget.h
===================================================================
--- trunk/tools/FlairGCS/src/TabWidget.h	(revision 9)
+++ trunk/tools/FlairGCS/src/TabWidget.h	(revision 9)
@@ -0,0 +1,25 @@
+#ifndef TABWIDGET_H
+#define TABWIDGET_H
+
+#include "XmlWidget.h"
+#include <QTabWidget>
+
+class Layout;
+
+class TabWidget: public XmlWidget
+{
+    friend class Tab;
+
+    public:
+        TabWidget(Layout* parent,int row,int col,QString name,QTabWidget::TabPosition position);
+        ~TabWidget();
+        bool IsUptodate(void);
+
+    private:
+        QTabWidget* tab;
+        void XmlEvent(QDomElement dom);
+
+
+};
+
+#endif // TABWIDGET_H
Index: trunk/tools/FlairGCS/src/TextEdit.cpp
===================================================================
--- trunk/tools/FlairGCS/src/TextEdit.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/TextEdit.cpp	(revision 9)
@@ -0,0 +1,33 @@
+#include "TextEdit.h"
+#include "Layout.h"
+#include <QPushButton>
+#include <QGridLayout>
+#include <QTextEdit>
+
+TextEdit::TextEdit(Layout* parent,int row, int col,QString name):XmlWidget(name,"TextEdit",parent)
+{
+
+    visible_widget = new QWidget();
+    visible_widget->setObjectName(name);
+
+    layout = new QGridLayout(visible_widget);
+    clear= new QPushButton("Effacer");
+    text=new QTextEdit();
+
+    layout->addWidget(text,0,0);
+    layout->addWidget(clear,1,0);
+
+    connect(clear, SIGNAL(clicked(bool)),text, SLOT(clear()));
+
+    parent->addWidget(visible_widget,row,col);
+}
+
+TextEdit::~TextEdit()
+{
+
+}
+
+void TextEdit::XmlEvent(QDomElement dom)
+{
+    text->append(dom.attribute("value"));
+}
Index: trunk/tools/FlairGCS/src/TextEdit.h
===================================================================
--- trunk/tools/FlairGCS/src/TextEdit.h	(revision 9)
+++ trunk/tools/FlairGCS/src/TextEdit.h	(revision 9)
@@ -0,0 +1,24 @@
+#ifndef TEXTEDIT_H
+#define TEXTEDIT_H
+
+#include "XmlWidget.h"
+
+class QTextEdit;
+class QPushButton;
+class QGridLayout;
+class Layout;
+
+class TextEdit: public XmlWidget
+{
+    public:
+        TextEdit(Layout* parent,int row, int col,QString name);
+        ~TextEdit();
+
+    private:
+        QGridLayout *layout;
+        QPushButton *clear;
+        QTextEdit *text;
+        void XmlEvent(QDomElement dom);
+};
+
+#endif // TEXTEDIT_H
Index: trunk/tools/FlairGCS/src/UdtSocket.cpp
===================================================================
--- trunk/tools/FlairGCS/src/UdtSocket.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/UdtSocket.cpp	(revision 9)
@@ -0,0 +1,209 @@
+#include "UdtSocket.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <QApplication>
+#include <QtEndian>
+#include <QDir>
+#include <QDate>
+#include "file_ui.h"
+#include "communication.h"
+
+#ifndef WIN32
+   #include <arpa/inet.h>
+#else
+   #include <winsock2.h>
+   #include <ws2tcpip.h>
+#endif
+
+using namespace std;
+
+UdtSocket::UdtSocket(UDTSOCKET file_socket,UDTSOCKET com_socket,QString name): QObject() {
+    this->file_socket=file_socket;
+    this->com_socket=com_socket;
+    this->name=name;
+    stop=false;
+    file_dialog=new file_ui();
+
+    bool blocking = true;
+    UDT::setsockopt(file_socket, 0, UDT_RCVSYN, &blocking, sizeof(bool));
+
+    heartbeat_timer = new QTimer(this);
+    connect(heartbeat_timer, SIGNAL(timeout()), this, SLOT(heartbeat()));
+    heartbeat_timer->start(200);
+}
+
+UdtSocket::~UdtSocket() {
+    heartbeat_timer->stop();
+
+    UDT::close(file_socket);
+    UDT::close(com_socket);
+
+    file_dialog->deleteLater();
+}
+
+//send signal to uav, to check connectivity through a watchdog
+//this is necessary because we use udt (udp based), and we cannot check disconnection of ground station
+void UdtSocket::heartbeat(void) {
+    char data=WATCHDOG_HEADER;
+    write(&data,1);
+}
+
+void UdtSocket::kill(void) {
+    printf("disconnected\n");
+    stop=true;
+    deleteLater();
+}
+
+void UdtSocket::handleConnections(void) {
+    while(!stop) {
+        int eid = UDT::epoll_create();
+        if(eid<0) {
+            printf("epoll_create error: %s\n",UDT::getlasterror().getErrorMessage());
+        }
+
+        if(UDT::epoll_add_usock(eid,file_socket)<0) {
+            if(UDT::getlasterror().getErrorCode()==5004) {
+                printf("epoll_add_usock\n");
+                break;
+            } else {
+                printf("epoll_add_usock error: %s\n",UDT::getlasterror().getErrorMessage());
+            }
+        }
+        if(UDT::epoll_add_usock(eid,com_socket)<0) {
+            if(UDT::getlasterror().getErrorCode()==5004) {
+                printf("epoll_add_usock\n");
+                break;
+            } else {
+                printf("epoll_add_usock error: %s\n",UDT::getlasterror().getErrorMessage());
+            }
+        }
+
+        set<UDTSOCKET> readfds;
+
+        int rv=UDT::epoll_wait(eid, &readfds,NULL, 10) ;
+
+        if(rv == -1) {
+            if(UDT::getlasterror().getErrorCode()!=6003) printf("prob %i\n",UDT::getlasterror().getErrorCode());
+            //printf("wait\n");
+        } else if(rv == 0) {
+            printf("timeout\n"); // a timeout occured
+        } else {
+            /*
+            if(UDT::getlasterror().getErrorCode()==2001) {
+                UDT::epoll_release(eid);
+            }*/
+            for (set<UDTSOCKET>::iterator i = readfds.begin(); i != readfds.end(); i++) {
+                //printf("a\n");
+                if(*i==file_socket) receiveFile();
+                if(*i==com_socket) receiveData();
+            }
+        }
+
+        UDT::epoll_remove_usock(eid,file_socket);
+        UDT::epoll_remove_usock(eid,com_socket);
+        UDT::epoll_release(eid);
+
+        QCoreApplication::processEvents();
+    }
+    kill();
+}
+
+void UdtSocket::receiveFile(void) {
+    char* recv_buf;
+    int bytesRead;
+    static bool flag_new_seq=true;
+    static QString folder_name;
+
+    //receive file info
+    recv_buf= (char*)malloc(1024);
+    bytesRead = UDT::recvmsg(file_socket,recv_buf,1024);
+
+    if(bytesRead<=0) {
+        free(recv_buf);
+        return;
+    }
+
+    int size;
+    memcpy(&size,&recv_buf[1],sizeof(int));
+    if(recv_buf[0]==FILE_INFO_BIG_ENDIAN) size=qFromBigEndian(size);
+
+    //printf("file_ui recu %i %x\n",bytesRead,recv_buf[0]);
+    if((recv_buf[0]==FILE_INFO_LITTLE_ENDIAN || recv_buf[0]==FILE_INFO_BIG_ENDIAN) && size>0) {
+        if(flag_new_seq==true) {
+            //create directory for storage
+            QDateTime dateTime = QDateTime::currentDateTime();
+            folder_name = dateTime.toString("yyyyMMdd_hhmm")+ "_" + name;
+            if(QDir().exists(folder_name)==true) {
+                folder_name = dateTime.toString("yyyyMMdd_hhmm_ss")+ "_" + name;
+            }
+            QDir().mkdir(folder_name);
+
+            flag_new_seq=false;
+            file_dialog->log("Creating directory " +folder_name);
+        }
+
+        QString file_name= QString::fromAscii((const char*)&recv_buf[5],bytesRead-5);
+        QString file_path=folder_name + "/" + file_name;
+        file_dialog->log(QString("receiving %1 (%2 bytes)").arg(file_name).arg(size));
+        QFile fichier(file_path);
+
+        if(!fichier.open(QIODevice::WriteOnly)) {
+            file_dialog->log("      could not write to file!");
+        } else {
+            //receive file
+            recv_buf= (char*)realloc((void*)recv_buf,size);
+            bytesRead = UDT::recvmsg(file_socket,recv_buf,size);
+            if(bytesRead!=size) {
+                file_dialog->log(QString("      error receiving file! (%1/%2)").arg(bytesRead).arg(size));
+                free(recv_buf);
+                return;
+            } else {
+                file_dialog->log("      ok");
+            }
+
+            QDataStream stream(&fichier);
+            stream.writeRawData(recv_buf,size);
+            fichier.close();
+
+            file_dialog->addFile(file_path);
+        }
+
+        free(recv_buf);
+    } else if(recv_buf[0]==END) {
+        file_dialog->endOfFiles();
+        flag_new_seq=true;
+    }
+}
+
+void UdtSocket::receiveData(void) {
+    while(1) {
+        int buf_size;
+        int opt_size;
+        UDT::getsockopt(com_socket,0,UDT_RCVBUF,&buf_size,&opt_size);
+
+        char* buf=(char*)malloc(buf_size);
+        int size;
+        size = UDT::recvmsg(com_socket,buf, buf_size);
+        buf=(char*)realloc(buf,size+1);
+
+        if(size>0) {
+            buf[size]=0;
+            emit dataReady(buf,size+1);
+        } else {
+            //if(UDT::getlasterror().getErrorCode()!=6002) printf("udt socket: %s\n",UDT::getlasterror().getErrorMessage());
+            free(buf);
+            break;
+        }
+    }
+}
+
+void UdtSocket::write(const char* buf, qint64 size) {
+    //printf("write\n%s\n",buf);
+    qint64 sent=UDT::sendmsg(com_socket,buf,size, -1, true);
+    if(sent!=size) {
+        printf("erreur envoi: %s\n",UDT::getlasterror().getErrorMessage());
+        if(UDT::getlasterror().getErrorCode()==2001) {
+           stop=true;
+        }
+    }
+}
Index: trunk/tools/FlairGCS/src/UdtSocket.h
===================================================================
--- trunk/tools/FlairGCS/src/UdtSocket.h	(revision 9)
+++ trunk/tools/FlairGCS/src/UdtSocket.h	(revision 9)
@@ -0,0 +1,38 @@
+#ifndef UDTSOCKET_H
+#define UDTSOCKET_H
+
+#include <udt.h>
+#include <QObject>
+#include <QTimer>
+
+class file_ui;
+
+class UdtSocket : public QObject
+{
+    Q_OBJECT
+
+    public:
+        UdtSocket(UDTSOCKET file_socket,UDTSOCKET com_socket,QString name);
+        ~UdtSocket();
+
+    private:
+        UDTSOCKET file_socket,com_socket;
+        file_ui* file_dialog;
+        bool stop;
+        QString name;
+        QTimer *heartbeat_timer;
+        void receiveData(void);
+        void receiveFile(void);
+
+    signals:
+        void dataReady(char*,int size);
+
+    public slots:
+        void handleConnections(void);
+        void kill(void);
+        void write(const char* buf, qint64 size);
+    private slots:
+        void heartbeat(void);
+};
+
+#endif // UDTSOCKET_H
Index: trunk/tools/FlairGCS/src/Vector3DSpinBox.cpp
===================================================================
--- trunk/tools/FlairGCS/src/Vector3DSpinBox.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/Vector3DSpinBox.cpp	(revision 9)
@@ -0,0 +1,166 @@
+#include "Vector3DSpinBox.h"
+#include <QLineEdit>
+#include <QMenu>
+#include <QContextMenuEvent>
+//#include <QGridLayout>
+#include <QFormLayout>
+#include <QGroupBox>
+#include "Layout.h"
+
+
+Vector3DSpinBox::Vector3DSpinBox(Layout* parent,int row, int col,QString name,QString value[3],float min,float max,float step,int decimals): XmlWidget(name,"Vector3DSpinBox",parent) {
+    for(int i=0;i<3;i++) {
+        doublespinbox[i].setRange(min,max);
+        doublespinbox[i].setSingleStep(step);
+        doublespinbox[i].setDecimals(decimals);
+    }
+
+    adjust_decimals(value);
+
+    for(int i=0;i<3;i++) {
+        doublespinbox[i].setValue(value[i].toDouble());
+        doublespinbox_value[i]=doublespinbox[i].cleanText();
+
+        //event filter for qdoublespinbox and its child (qlinedit and incremnt qbuttons)
+        doublespinbox[i].installEventFilter(this);
+        QObjectList o_list = doublespinbox[i].children();
+        for(int j = 0; j < o_list.length(); j++) {
+            QLineEdit *cast = qobject_cast<QLineEdit*>(o_list[j]);
+            if(cast)
+                cast->installEventFilter(this);
+        }
+
+        connect(&doublespinbox[i],SIGNAL(valueChanged(const QString &)),this, SLOT(valuechanged(const QString &)));
+    }
+
+    SetValues(value);
+
+    //creation et ajout QGroupBox
+    box = new QGroupBox(name);
+    box->setObjectName(name);
+    visible_widget=box;
+    parent->addWidget(box,row,col);
+    qgridlayout=new QGridLayout(new QWidget());
+    box->setLayout(qgridlayout);
+
+    AddElement("x:",0);
+    AddElement("y:",1);
+    AddElement("z:",2);
+}
+
+Vector3DSpinBox::~Vector3DSpinBox() {
+}
+
+void Vector3DSpinBox::SetValues(QString value[3]) {
+    SetAttribute("value_x",value[0]);
+    SetAttribute("value_y",value[1]);
+    SetAttribute("value_z",value[2]);
+}
+
+void Vector3DSpinBox::AddElement(QString name,int index) {
+    QWidget* widget=new QWidget();
+    QFormLayout* object_layout = new QFormLayout(widget);
+    object_layout->setHorizontalSpacing(2);
+    object_layout->setVerticalSpacing(2);
+    object_layout->setContentsMargins (2,2,2,2);
+
+    object_layout->addRow(name,&doublespinbox[index]);
+
+    qgridlayout->addWidget(widget,index,0);
+}
+
+void Vector3DSpinBox::adjust_decimals(QString value[3]) {
+    for(int i=0;i<3;i++) {
+        //auto adjust decimals
+        QLocale locale;
+        value[i].remove(locale.groupSeparator());
+
+        QStringList parts = value[i].split(locale.decimalPoint());
+        if(parts.count() == 2) {
+            doublespinbox[i].setDecimals(parts[1].size());
+        }
+    }
+}
+
+bool Vector3DSpinBox::eventFilter(QObject *object, QEvent *event) {
+    for(int i=0;i<3;i++) {
+        if(object==&doublespinbox[i] && event->type()==QEvent::MouseButtonPress) {
+            if (((QMouseEvent*)event)->button() == Qt::RightButton) {
+                QMenu * menu = new QMenu("menu", doublespinbox);
+                QAction *a,*b,*c,*z;
+
+                a=menu->addAction("add decimal");
+                b=menu->addAction("remove decimal");
+
+                if(doublespinbox[i].decimals()==0) b->setEnabled(false);
+                z=menu->exec(((QMouseEvent*)event)->globalPos());
+
+                if(z==a) doublespinbox[i].setDecimals(doublespinbox[i].decimals()+1);
+                if(z==b) doublespinbox[i].setDecimals(doublespinbox[i].decimals()-1);
+                delete menu;
+                return true;
+            }
+        }
+    }
+    return object->eventFilter(object, event);
+}
+
+void Vector3DSpinBox::SetUptodate(void) {
+    ui_to_var();
+    ui_to_xml();
+    visible_widget->setPalette(black_pal);
+}
+
+void Vector3DSpinBox::ui_to_var(void) {
+    for(int i=0;i<3;i++) {
+        doublespinbox_value[i]=doublespinbox[i].cleanText();
+    }
+}
+
+void Vector3DSpinBox::ui_to_xml(void) {
+    SetAttribute("value_x",doublespinbox[0].cleanText());
+    SetAttribute("value_y",doublespinbox[1].cleanText());
+    SetAttribute("value_z",doublespinbox[2].cleanText());
+}
+
+void Vector3DSpinBox::Reset(void) {
+    //le setvalue fait un arrondi pour l'affichage, la variable n'est donc plus egale
+    //on reprend la valeur de la boite et on force la couleur a noir
+    adjust_decimals(doublespinbox_value);
+    for(int i=0;i<3;i++) {
+        doublespinbox[i].setValue(doublespinbox_value[i].toDouble());
+        doublespinbox_value[i]= doublespinbox[i].cleanText();
+    }
+    visible_widget->setPalette(black_pal);
+}
+
+void Vector3DSpinBox::LoadEvent(QDomElement dom) {
+    if(doublespinbox[0].isEnabled()) {
+        doublespinbox[0].setValue((dom.attribute("value_x")).toDouble());
+    }
+    if(doublespinbox[1].isEnabled()) {
+        doublespinbox[1].setValue((dom.attribute("value_y")).toDouble());
+    }
+    if(doublespinbox[2].isEnabled()) {
+        doublespinbox[2].setValue((dom.attribute("value_z")).toDouble());
+    }
+}
+
+void Vector3DSpinBox::valuechanged(const QString &value) {
+    for(int i=0;i<3;i++) {
+        if((QDoubleSpinBox*)sender()==&doublespinbox[i] && value!=doublespinbox_value[i]) {
+            visible_widget->setPalette(red_pal);
+            return;
+        }
+    }
+    visible_widget->setPalette(black_pal);
+}
+
+bool Vector3DSpinBox::IsUptodate(void) {
+    //si le widget n'est pas enabled, sa palette est differente de rouge (greyed) donc on renvoit true
+    //permet de ne pas envoyer les modifs d'un widget disabled
+    //if(label->palette()==red_pal) return false;
+    if(visible_widget->palette()==red_pal) return false;
+    return true;
+}
+
Index: trunk/tools/FlairGCS/src/Vector3DSpinBox.h
===================================================================
--- trunk/tools/FlairGCS/src/Vector3DSpinBox.h	(revision 9)
+++ trunk/tools/FlairGCS/src/Vector3DSpinBox.h	(revision 9)
@@ -0,0 +1,40 @@
+#ifndef VECTOR3DSPINBOX_H
+#define VECTOR3DSPINBOX_H
+
+#include "XmlWidget.h"
+#include <QDoubleSpinBox>
+
+class Layout;
+class QGroupBox;
+class QGridLayout;
+
+class Vector3DSpinBox: public XmlWidget
+{
+    Q_OBJECT
+
+    public:
+        //handle value as string, becouse double value are not exact
+        Vector3DSpinBox(Layout* parent,int row, int col,QString name,QString value[3],float min,float max,float step,int decimals);
+        ~Vector3DSpinBox();
+
+    private:
+        QGridLayout* qgridlayout;
+        QGroupBox* box;
+        QDoubleSpinBox doublespinbox[3];
+        QString doublespinbox_value[3];
+        void AddElement(QString name,int index);
+        void SetUptodate(void);
+        void SetValues(QString value[3]);
+        void Reset(void);
+        void LoadEvent(QDomElement dom);
+        void ui_to_var(void);
+        void ui_to_xml(void);
+        bool eventFilter(QObject *o, QEvent *e);
+        void adjust_decimals(QString value[3]);
+        bool IsUptodate(void);
+
+    private slots:
+        void valuechanged(const QString &value);
+};
+
+#endif // VECTOR3DSPINBOX_H
Index: trunk/tools/FlairGCS/src/XmlWidget.cpp
===================================================================
--- trunk/tools/FlairGCS/src/XmlWidget.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/XmlWidget.cpp	(revision 9)
@@ -0,0 +1,329 @@
+#include "XmlWidget.h"
+#include <QWidget>
+#include "ConnectionLayout.h"
+#include <stdio.h>
+
+XmlWidget::XmlWidget(QString name,QString type,XmlWidget* parent):QObject()
+{
+    childs=new QList<XmlWidget*>;
+    isContainer=false;
+    isExpandable=false;
+    visible_widget=NULL;
+    parent_widget=parent;
+
+    red_pal.setColor( QPalette::Text, QColor(255,0,0) );
+    red_pal.setColor( QPalette::Foreground, QColor(255,0,0) );
+    red_pal_greyed.setColor( QPalette::Text, QColor(128,0,0) );
+    red_pal_greyed.setColor( QPalette::Foreground, QColor(128,0,0) );
+
+    black_pal.setColor( QPalette::Text, QColor(0,0,0) );
+    black_pal.setColor( QPalette::Foreground, QColor(0,0,0) );
+    black_pal_greyed.setColor( QPalette::Text, QColor(128,128,128) );
+    black_pal_greyed.setColor( QPalette::Foreground, QColor(128,128,128) );
+
+    setObjectName(name);
+
+    if(parent!=NULL)
+    {
+        parent->childs->append(this);
+
+        document=parent->document.cloneNode(true).toDocument();
+
+        write_elem = QDomElement(document.createElement(type));
+        write_elem.setAttribute("name", name);
+        //recupere le node le plus profond
+        QDomNode node=document.firstChild();
+        while(node.firstChild().isNull()==false)
+        {
+            node=node.firstChild();
+        }
+        node.appendChild(write_elem);
+    }
+    else
+    {
+        document=QDomDocument("remote_ui_xml");
+        write_elem = QDomElement(document.createElement(type));
+        write_elem.setAttribute("name", name);
+        document.appendChild(write_elem);
+    }
+}
+
+XmlWidget::~XmlWidget()
+{
+    if(parent_widget!=NULL) parent_widget->childs->removeOne(this);
+
+    //on efface les widgets enfants
+    //dans le delete child on modifie le child du parent, donc on se refere toujours au premier
+    while(childs->count()!=0) {
+        delete childs->first();
+    }
+
+    delete childs;
+    if(visible_widget!=NULL) {
+        delete visible_widget;
+    }
+}
+
+QString XmlWidget::Name(void)
+{
+    return  write_elem.attribute("name");
+}
+
+void XmlWidget::SetIsContainer(bool status) {
+    isContainer=status;
+}
+
+void XmlWidget::SetIsExpandable(bool status) {
+    isExpandable=status;
+}
+
+XmlWidget* XmlWidget::GetXmlWidget(QString name,QString type)
+{
+    //printf("recherche %s %s\n",name.toLocal8Bit().constData(),type.toLocal8Bit().constData());
+
+    for(int i=0;i<childs->count();i++)
+    {
+        //printf("child name %s\n",childs->at(i)->write_elem.attribute("name").toLocal8Bit().constData());
+        //printf("child tag %s\n",childs->at(i)->write_elem.tagName().toLocal8Bit().constData());
+        if(childs->at(i)->write_elem.attribute("name")==name && childs->at(i)->write_elem.tagName()==type) return childs->at(i);
+
+    }
+    return NULL;
+}
+
+
+void XmlWidget::ParseXml(QDomElement to_parse) {
+
+    if(to_parse.isNull()) return;
+
+    QString type=to_parse.tagName();
+    QString name=to_parse.attribute("name");
+
+//printf("parse %s %s\n",type.toLocal8Bit().constData(),name.toLocal8Bit().constData());
+    XmlWidget* match;
+    match=GetXmlWidget(name,type);
+
+    if(match==NULL) {
+        //printf("not match\n");
+        XmlEvent(to_parse);
+    } else {
+        //printf("match\n");
+        //si on a une balise IsEnabled, on ne traite que ca
+        if(match->visible_widget!=NULL) {
+            if(to_parse.attribute("IsEnabled")=="0") {
+                match->visible_widget->setEnabled(false);
+                return;
+            }
+            if(to_parse.attribute("IsEnabled")=="1") {
+                match->visible_widget->setEnabled(true);
+                return;
+            }
+        }
+
+        //si on a une balise delete, on ne traite que ca
+        if(to_parse.attribute("Delete")=="1") {
+            //printf("delete flag\n");
+            if(match->isContainer==true && match->childs->count()!=0) {
+                //printf("non vide %s\n",match->objectName().toLocal8Bit().constData());
+                return;
+            }
+
+            delete match;
+            return;
+        }
+
+        if(to_parse.firstChild().isNull()==true && match->isExpandable==false) {
+            QString new_name;
+            printf("possible doublon\n");
+            for(int i=0;i<65535;i++) {
+                new_name=QString("%1_%2").arg(name).arg(i);
+                bool continuer=false;
+                for(int i=0;i<childs->count();i++) {
+                    if(childs->at(i)->write_elem.attribute("name")==new_name) {
+                        continuer=true;
+                        break;
+                    }
+                }
+                if(continuer==false) break;
+            }
+            printf("new_name %s\n",new_name.toLocal8Bit().constData());
+            to_parse.setAttribute("name",new_name);
+            to_parse.setAttribute("old_name",name);
+
+            XmlEvent(to_parse);
+
+            //return -1;//ou retourner le xml a renvoyer pour chager de nom
+        } else {
+            if(to_parse.firstChild().toElement().isNull()) {
+                match->XmlEvent(to_parse);
+                return;
+            } else {
+                match->ParseXml(to_parse.firstChild().toElement());
+            }
+        }
+    }
+}
+
+void XmlWidget::LoadXml(QDomElement to_parse) {
+    if(to_parse.isNull()) return;
+
+    LoadEvent(to_parse);
+
+    QDomElement elem=to_parse.firstChild().toElement();
+
+    while(!elem.isNull()) {
+
+        QString type=elem.tagName();
+        QString name=elem.attribute("name");
+//printf("%s %s\n",type.toLocal8Bit().constData(),name.toLocal8Bit().constData());
+        XmlWidget* match;
+        match=GetXmlWidget(name,type);
+
+        if(match!=NULL) {
+            //printf("match\n");
+            match->LoadXml(elem);
+        }
+        elem=elem.nextSibling().toElement();
+    }
+}
+
+void XmlWidget::GetFullXml(QDomElement* doc) {
+    QDomDocument tmp_doc=XmlDoc();
+    merge((QDomElement*)&tmp_doc,doc);
+
+    for(int i=0;i<childs->count();i++) {
+        childs->at(i)->GetFullXml(doc);
+    }
+}
+
+void XmlWidget::GetUpdateXml(QDomElement* doc) {
+    if(IsUptodate()==false && isContainer==false) {
+        SetUptodate();
+        QDomDocument tmp_doc=XmlDoc();
+        merge((QDomElement*)&tmp_doc,doc);
+    }
+
+    for(int i=0;i<childs->count();i++) {
+        childs->at(i)->GetUpdateXml(doc);
+    }
+}
+
+void XmlWidget::ResetAllChilds(void)
+{
+    Reset();
+    for(int i=0;i<childs->count();i++)
+    {
+        childs->at(i)->ResetAllChilds();
+    }
+}
+
+void XmlWidget::merge(QDomElement* from,QDomElement* into)
+{
+    QDomElement tmp_into,tmp_from;
+    tmp_from=from->firstChildElement();
+
+    while(tmp_from.isNull()==false)
+    {
+        //search corresponding child
+        bool match=false;
+        tmp_into=into->firstChildElement(tmp_from.tagName());
+        while(tmp_into.isNull()==false)
+        {
+            if(tmp_into.attribute("name")==tmp_from.attribute("name"))
+            {
+               merge(&tmp_from,&tmp_into);
+               match=true;
+               break;
+            }
+            tmp_into=tmp_into.nextSiblingElement(tmp_from.tagName());
+        }
+
+        if(match==false)
+        {
+            into->appendChild(tmp_from.cloneNode());
+        }
+
+        tmp_from=tmp_from.nextSiblingElement();
+    }
+}
+
+QDomDocument XmlWidget::XmlDoc(void)
+{
+    return document.cloneNode(true).toDocument();
+}
+
+QDomElement* XmlWidget::AddXmlChild(QString type)
+{
+    QDomElement* elem;
+
+    elem = new QDomElement(document.createElement(type));
+    write_elem.appendChild(*elem);
+
+    return elem;
+}
+
+void XmlWidget::RemoveXmlChild(QDomElement* element)
+{
+    write_elem.removeChild(*element);
+    delete element;
+}
+
+void XmlWidget::ClearDoc(void)
+{
+    document.clear();
+}
+
+void XmlWidget::SetValue(QString value)
+{
+    write_elem.setAttribute("value",value);
+}
+
+void XmlWidget::SetAttribute(const QString& name, const QString& value)
+{
+     write_elem.setAttribute(name,value);
+}
+
+void XmlWidget::SetAttribute(const QString& name, qlonglong value)
+{
+    write_elem.setAttribute(name,value);
+}
+
+void XmlWidget::SetAttribute(const QString& name, qulonglong value)
+{
+    write_elem.setAttribute(name,value);
+}
+
+void XmlWidget::SetAttribute(const QString& name, float value)
+{
+    write_elem.setAttribute(name,value);
+}
+
+void XmlWidget::SetAttribute(const QString& name, double value)
+{
+    write_elem.setAttribute(name,value);
+}
+
+void XmlWidget::RemoveAttribute(const QString& name) {
+    write_elem.removeAttribute(name);
+}
+
+void XmlWidget::RenamedFrom(QString old_name)
+{
+    QString name=write_elem.attribute("name");
+    SetAttribute("name",old_name);
+    SetAttribute("new_name",name);
+    connectionLayout()->XmlToSend(XmlDoc());
+    SetAttribute("name",name);
+    write_elem.removeAttribute("new_name");
+
+}
+
+ConnectionLayout* XmlWidget::connectionLayout(void)
+{
+    if(parent_widget!=NULL) {
+        return (ConnectionLayout*)(parent_widget->connectionLayout());
+    } else {
+        return (ConnectionLayout*)this;
+    }
+}
+
Index: trunk/tools/FlairGCS/src/XmlWidget.h
===================================================================
--- trunk/tools/FlairGCS/src/XmlWidget.h	(revision 9)
+++ trunk/tools/FlairGCS/src/XmlWidget.h	(revision 9)
@@ -0,0 +1,66 @@
+#ifndef XMLWIDGET_H
+#define XMLWIDGET_H
+
+#include <QObject>
+#include <stdint.h>
+#include <qdom.h>
+#include <QPalette>
+
+class QWidget;
+class ConnectionLayout;
+
+class XmlWidget:public QObject
+{
+    Q_OBJECT
+
+    public:
+        XmlWidget(QString name,QString type,XmlWidget* parent);
+        ~XmlWidget();
+        QDomDocument XmlDoc(void);
+        void ParseXml(QDomElement to_parse);
+        void GetFullXml(QDomElement* doc);
+        void GetUpdateXml(QDomElement* doc);
+        void ResetAllChilds(void);
+        virtual bool IsUptodate(void){return true;};
+        void LoadXml(QDomElement to_parse);
+        void RenamedFrom(QString old_name);
+        QString Name(void);
+
+    private:
+        QDomDocument document;
+        QDomElement write_elem;
+        XmlWidget* GetXmlWidget(QString name,QString type);
+        static void merge(QDomElement* from,QDomElement* into);
+        bool isExpandable;//true if we can receive extra frame for this widget (ex combobox, plots, layout)
+        bool isContainer;//true if it can contain other widget (ex layout), isExpandable is also true in this case
+        virtual void SetUptodate(void){};
+        virtual void Reset(void){};
+        XmlWidget* parent_widget;
+
+    protected:
+        QList<XmlWidget*> *childs;
+        ConnectionLayout* connectionLayout(void);
+        QWidget* visible_widget;
+        QPalette red_pal,red_pal_greyed;
+        QPalette black_pal,black_pal_greyed;
+        void SetIsContainer(bool status);
+        void SetIsExpandable(bool status);
+        virtual void XmlEvent(QDomElement dom){};
+        virtual void LoadEvent(QDomElement dom){};
+        QDomElement* AddXmlChild(QString type);
+        void RemoveXmlChild(QDomElement* element);
+        void ClearDoc(void);
+        void SetValue(QString value);
+        void SetAttribute(const QString& name, const QString& value);
+        void SetAttribute(const QString& name, qlonglong value);
+        void SetAttribute(const QString& name, qulonglong value);
+        inline void SetAttribute(const QString& name, int value)
+            { SetAttribute(name, qlonglong(value)); }
+        inline void SetAttribute(const QString& name, uint value)
+            { SetAttribute(name, qulonglong(value)); }
+        void SetAttribute(const QString& name, float value);
+        void SetAttribute(const QString& name, double value);
+        void RemoveAttribute(const QString& name);
+};
+
+#endif // XMLWIDGET_H
Index: trunk/tools/FlairGCS/src/file_ui.cpp
===================================================================
--- trunk/tools/FlairGCS/src/file_ui.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/file_ui.cpp	(revision 9)
@@ -0,0 +1,409 @@
+#include "file_ui.h"
+#include <stdio.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <QDir>
+#include <QDate>
+#include <QTextStream>
+#include <QGridLayout>
+#include <io_hdfile.h>
+#include <QtEndian>
+#include <QComboBox>
+#include <QPushButton>
+#include <QTextEdit>
+#include <QDialog>
+#include <QStringList>
+#include <QFormLayout>
+
+#ifndef WIN32
+   #include <arpa/inet.h>
+#else
+   #include <winsock2.h>
+   #include <ws2tcpip.h>
+#endif
+
+
+using namespace std;
+
+file_ui::file_ui()
+{
+    dialog=new QDialog();
+    dialog->setWindowTitle("log files");
+    QGridLayout *main_layout = new QGridLayout(dialog);
+    ok_button= new QPushButton("Ok",dialog);
+    log_text=new QTextEdit(dialog);
+    log_text->setReadOnly(true);
+    input_text=new QTextEdit(dialog);
+    input_text->setText("add your log comment here");
+    input_cleared=false;
+
+    ok_button->setEnabled(false);
+
+    main_layout->addWidget(log_text,0,0);
+    main_layout->addWidget(input_text,1,0);
+
+    QWidget *widget=new QWidget(dialog);
+    QFormLayout *formLayout = new QFormLayout(widget);
+    csv_combo = new QComboBox(widget);
+    formLayout->addRow(tr("save all log with following base time"), csv_combo);
+    csv_combo->addItem("(no base time)");
+    main_layout->addWidget(widget,2,0);
+    main_layout->addWidget(ok_button,3,0);
+
+    connect(ok_button, SIGNAL(clicked()),this, SLOT(save()), Qt::QueuedConnection);
+    connect(this, SIGNAL(showDialog()),dialog, SLOT(show()), Qt::QueuedConnection);
+    connect(this, SIGNAL(appendToLog(QString)),log_text, SLOT(append(QString)), Qt::QueuedConnection);
+    connect(input_text, SIGNAL(cursorPositionChanged()),this, SLOT(clearInputText()), Qt::QueuedConnection);
+
+    file_names=new QStringList();
+}
+
+file_ui::~file_ui()
+{
+    delete dialog;
+}
+
+void file_ui::log(QString text) {
+    appendToLog(text);
+}
+
+void file_ui::addFile(QString file_path) {
+    //framework sends dbt file then txt file
+    //when we receive txt, we have both files
+    //and we can convert it to .csv
+    if(file_path.endsWith(".dbt")==true) {
+        QString name=file_path.section('/', -1);//remove path for displaying on combobox
+        csv_combo->addItem(name.replace(QString(".dbt"), QString(".csv")));
+        file_names->append(file_path.replace(QString(".dbt"), QString(".csv")));
+    }
+
+    if(file_path.endsWith(".txt")==true) {
+        dbt2csv(file_path.replace(QString(".txt"), QString(".dbt")));
+    }
+
+    if(file_names->size()==1) {
+        input_cleared=false;
+        showDialog();
+    }
+}
+
+void file_ui::endOfFiles(void) {
+    ok_button->setEnabled(true);
+
+    qint64 max_file_size=0;
+    for(int i=0;i<file_names->count();i++) {
+        QFileInfo info(file_names->at(i));
+        if(info.size()>max_file_size) {
+            max_file_size=info.size();
+            csv_combo->setCurrentIndex(i+1);//first item of combobox is already taken
+        }
+    }
+}
+
+void file_ui::dbt2csv(QString file_path)
+{
+    hdfile_t *dbtFile = NULL;
+    char *data;
+    QStringList data_type;
+
+    QString filename=file_path.section('/', -1);//remove path for displaying on logs
+    appendToLog(QString("converting %1 to csv").arg(filename));
+
+    //open csv file
+    QString csv_filename=file_path;
+    csv_filename.replace(QString(".dbt"), QString(".csv"));
+    QFile csv_file(csv_filename);
+
+    if(!csv_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        appendToLog("      error opening csv file!");
+        return;
+    }
+    QTextStream out(&csv_file);
+
+    //open txt file
+    QString txt_filename=file_path;
+    txt_filename.replace(QString(".dbt"), QString(".txt"));
+    QFile txt_file(txt_filename);
+
+    if(!txt_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        appendToLog("      error opening txt file!");
+        return;
+    }
+
+    //read txt file
+    QTextStream txt_in(&txt_file);
+    txt_in.readLine();//time us
+    txt_in.readLine();//time ns
+    while(1)
+    {
+        if(txt_in.atEnd()==true) break;
+        QString txt_line=txt_in.readLine();
+        data_type.append(txt_line.section("(",-1));//on part de la fin pour trouver la premiere parenthese ouvrante
+        //printf("type %s\n",txt_line.section("(",-1).toLocal8Bit().constData());
+    }
+    txt_file.close();
+
+    dbtFile=open_hdfile(file_path.toLocal8Bit().data(),READ_MODE);
+
+    if (!dbtFile)
+    {
+        appendToLog("      error opening dbt file!");
+        return;
+    }
+    data=(char*)malloc(dbtFile->h.DataSize);
+    if(data==NULL)
+    {
+        appendToLog("      error malloc!");
+        return;
+    }
+
+    bool dataWritten=false;
+    while(1)
+    {
+        road_time_t time;
+        road_timerange_t tr = 0;
+        int offset=0;
+        QTextStream csv_line;
+
+        if(read_hdfile(dbtFile,(void*)data,&time,&tr)==0) {
+            break;
+        }
+        dataWritten=true;
+
+        out << time << "," << tr;
+        for(int i=0;i<data_type.size();i++)
+        {
+            if(data_type.at(i)=="float)")
+            {
+                float* value=(float*)(data+offset);
+                offset+=sizeof(float);
+                out << "," << *value;
+            }
+            else if(data_type.at(i)=="int8_t)")
+            {
+                int8_t* value=(int8_t*)(data+offset);
+                offset+=sizeof(int8_t);
+                float fl=(float)*value;
+                out << "," << *value;
+            }
+            else
+            {
+                appendToLog(QString("      unhandled type: %1").arg(data_type.at(i)));
+            }
+        }
+
+        out << "\n";
+    }
+
+    if(!dataWritten) {
+        //empty file!
+        out <<  "0,0";//timr
+        for(int i=0;i<data_type.size();i++) {
+            out << ",0";
+        }
+        out << "\n";
+    }
+
+    csv_file.close();
+    close_hdfile(dbtFile);
+    if(data!=NULL) free(data);
+
+    appendToLog("      ok");
+}
+
+void file_ui::clearInputText(void){
+    if(input_cleared==false) {
+        input_cleared=true;
+        input_text->clear();
+    }
+}
+
+void file_ui::save(void)
+{
+    save_comment();
+    if(csv_combo->currentIndex()!=0)
+    {
+        save_csv();
+        save_txt();
+    }
+
+    log_text->clear();
+    input_cleared=true;//avoid clearing it with setText
+    input_text->setText("add your log comment here");
+    file_names->clear();
+    csv_combo->clear();
+    csv_combo->addItem(QString("(no base time)"));
+
+    dialog->setVisible(false);
+    ok_button->setEnabled(false);
+    emit finished();
+}
+
+void file_ui::save_comment(void)
+{
+    QString folder_name=file_names->at(0).section('/', 0,-2);
+
+    QString filename=folder_name+"/commentaire.txt";
+    QFile file(filename);
+    if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) printf("file_ui::save_comment: erreur ouverture fichier %s\n",filename.toLocal8Bit().constData());
+    QTextStream out(&file);
+
+    out<<input_text->toPlainText();
+    file.close();
+}
+
+void file_ui::save_csv(void)
+{
+    //global csv file
+    QString folder_name=file_names->at(0).section('/', 0,-2);
+    QString filename=folder_name + "/all_logs.csv" ;
+    QFile global_file(filename);
+    if(!global_file.open(QIODevice::WriteOnly | QIODevice::Text)) printf("file_ui::save_csv: erreur ouverture fichier %s\n",filename.toLocal8Bit().constData());
+    QTextStream out(&global_file);
+
+    //reference csv file
+    filename=file_names->at(csv_combo->currentIndex()-1);
+    QFile ref_file(filename);
+    //printf("file_ui::save_csv: ref %s\n",filename.toLocal8Bit().constData());
+    if(!ref_file.open(QIODevice::ReadOnly | QIODevice::Text)) printf("file_ui::save_csv: erreur ouverture ficher %s\n",filename.toLocal8Bit().constData());
+
+    //other csv files
+    int j=0;
+    QFile m_file[file_names->count()-1];
+    QTextStream m_in[file_names->count()-1];
+    for(int i=0;i<file_names->count();i++)
+    {
+        if(i==csv_combo->currentIndex()-1) continue;
+        filename=file_names->at(i);
+        m_file[j].setFileName(filename);
+        if(!m_file[j].open(QIODevice::ReadOnly | QIODevice::Text)) printf("file_ui::save_csv: erreur ouverture ficher %s\n",filename.toLocal8Bit().constData());
+        m_in[j].setDevice(&m_file[j]);
+        j++;
+    }
+
+    //init
+    QTextStream ref_in(&ref_file);
+    QString m_line[file_names->count()-1];
+    QString m_line_prev[file_names->count()-1];
+    for(int i=0;i<file_names->count()-1;i++)
+    {
+        m_line[i]=m_in[i].readLine();
+        m_line_prev[i]=m_line[i];
+    }
+
+    //organize csv files in one file
+    while(1)
+    {
+        if(ref_in.atEnd()==true) break;
+        QString ref_line=ref_in.readLine();
+
+        qint64 ref_us=ref_line.section(',',0,0).toLongLong();
+        int ref_ns=ref_line.section(',',1,1).toInt();
+        //printf("ref %lld %i\n",ref_us,ref_ns);
+
+        for(int i=0;i<file_names->count()-1;i++)
+        {
+            qint64 csv_us=m_line[i].section(',',0,0).toLongLong();
+            int csv_ns=m_line[i].section(',',1,1).toInt();
+            //printf("m %lld %i\n",csv_us,csv_ns);
+
+            while(is_greater(ref_us,csv_us,ref_ns,csv_ns)==true)
+            {
+                m_line_prev[i]=m_line[i];
+                if(m_in[i].atEnd()==true) break;
+                m_line[i]=m_in[i].readLine();
+                csv_us=m_line[i].section(',',0,0).toLongLong();
+                csv_ns=m_line[i].section(',',1,1).toInt();
+                //printf("m %lld %i\n",csv_us,csv_ns);
+            }
+            csv_us=m_line_prev[i].section(',',0,0).toLongLong();
+            csv_ns=m_line_prev[i].section(',',1,1).toInt();
+            //printf("m ok %lld %i\n",csv_us,csv_ns);
+
+            ref_line+="," + m_line_prev[i].section(',',2);
+        }
+
+        out<<ref_line << "\n";
+    }
+
+    global_file.close();
+    ref_file.close();
+    for(int i=0;i<file_names->count()-1;i++) m_file[i].close();
+}
+
+void file_ui::save_txt(void)
+{
+    //global txt file
+    QString folder_name=file_names->at(0).section('/', 0,-2);
+    QString filename=folder_name + "/all_logs.txt";
+    QFile global_file(filename);
+    if(!global_file.open(QIODevice::WriteOnly | QIODevice::Text)) printf("file_ui::save_txt: erreur ouverture ficher %s\n",filename.toLocal8Bit().constData());
+    QTextStream out(&global_file);
+
+    //reference txt file
+    filename=file_names->at(csv_combo->currentIndex()-1);
+    filename.replace(QString(".csv"), QString(".txt"));
+    QFile ref_file(filename);
+    if(!ref_file.open(QIODevice::ReadOnly | QIODevice::Text)) printf("file_ui::save_txt: erreur ouverture ficher %s\n",filename.toLocal8Bit().constData());
+
+    QTextStream ref_in(&ref_file);
+    QString current_line=ref_in.readLine();
+    int nb_lines=1;
+    while(current_line!=NULL)
+    {
+        out<<current_line << "\n";;
+        current_line=ref_in.readLine();
+        nb_lines++;
+    }
+
+    //other txt files
+    for(int i=0;i<file_names->count();i++)
+    {
+        if(i==csv_combo->currentIndex()-1) continue;
+        filename=file_names->at(i);
+        filename.replace(QString(".csv"), QString(".txt"));
+        QFile txt_file(filename);
+        if(!txt_file.open(QIODevice::ReadOnly | QIODevice::Text)) printf("file_ui::save_txt: erreur ouverture ficher %s\n",filename.toLocal8Bit().constData());
+        QTextStream txt_in(&txt_file);
+        txt_in.readLine();//time us
+        txt_in.readLine();//time ns
+        current_line=txt_in.readLine();
+        while(current_line!=NULL)
+        {
+            out<< nb_lines << ":" << current_line.section(':',1) << "\n";;
+            current_line=txt_in.readLine();
+            nb_lines++;
+        }
+        txt_file.close();
+
+    }
+    global_file.close();
+    ref_file.close();
+}
+
+
+bool file_ui::is_greater(qint64 ref_us,qint64 csv_us,int ref_ns,int csv_ns)
+{
+    if(ref_us==csv_us)
+    {
+        if(ref_ns>csv_ns)
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    if(ref_us>csv_us)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
Index: trunk/tools/FlairGCS/src/file_ui.h
===================================================================
--- trunk/tools/FlairGCS/src/file_ui.h	(revision 9)
+++ trunk/tools/FlairGCS/src/file_ui.h	(revision 9)
@@ -0,0 +1,48 @@
+#ifndef FILE_UI_H
+#define FILE_UI_H
+
+#include <QObject>
+
+class QStringList;
+class QDialog;
+class QTextEdit;
+class QPushButton;
+class QComboBox;
+class QCloseEvent;
+
+class file_ui:public QObject
+{
+    Q_OBJECT
+
+    public:
+        file_ui();
+        ~file_ui();
+        void log(QString text);
+        void addFile(QString file_path);
+        void endOfFiles(void);
+
+    private:
+        QDialog *dialog;
+        QStringList *file_names;
+        QTextEdit *log_text,*input_text;
+        QPushButton *ok_button;
+        QComboBox *csv_combo;
+        void save_comment(void);
+        void save_csv(void);
+        void save_txt(void);
+        void dbt2csv(QString file_path);
+        bool is_greater(qint64 ref_us,qint64 csv_us,int ref_ns,int csv_ns);
+        void closeEvent(QCloseEvent * e);
+        bool input_cleared;
+
+    private slots:
+        void save(void);
+        void clearInputText(void);
+
+    signals:
+        void showDialog(void);
+        void appendToLog(QString);
+        void finished();
+};
+
+#endif // FILE_UI_H
Index: trunk/tools/FlairGCS/src/main.cpp
===================================================================
--- trunk/tools/FlairGCS/src/main.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/main.cpp	(revision 9)
@@ -0,0 +1,64 @@
+#include <QApplication>
+#include <QCleanlooksStyle>
+#include <QLocale>
+#include <qmetatype.h>
+#include <tclap/CmdLine.h>
+
+#include "Manager.h"
+#include "svnversion.h"
+
+using namespace TCLAP;
+using namespace std;
+
+string name;
+int port;
+
+void parseOptions(int argc, char** argv) {
+	try {
+        CmdLine cmd("Command description message", ' ', "0.1");
+
+        ValueArg<string> nameArg("n","name","uav name",false,"x4-0","string");
+        cmd.add( nameArg );
+
+        ValueArg<int> portArg("p","port","port number",false,9000,"int");
+        cmd.add( portArg );
+
+        cmd.parse( argc, argv );
+
+        // Get the value parsed by each arg.
+        name= nameArg.getValue();
+        port = portArg.getValue();
+
+	} catch (ArgException &e) {// catch any exceptions
+        cerr << "error: " << e.error() << " for arg " << e.argId() << endl;
+    }
+}
+
+int main(int argc, char *argv[]) {
+
+    union {
+        uint32_t i;
+        char c[4];
+    } bint = {0x01020304};
+
+    if(bint.c[0] == 1) {
+        printf("error, ground station is only compatible with little endian\n");
+        return -1;
+    }
+
+    printf(SVN_REV);
+
+    parseOptions(argc,argv);
+    printf("listening on port %i\n",port);
+
+    qRegisterMetaType<const char*>("const char*");
+    QLocale::setDefault(QLocale::C);
+    QApplication app(argc, argv);
+    app.setStyle(new QCleanlooksStyle);
+
+    Manager manager(QString::fromStdString(name),port);
+
+    manager.show();
+
+    app.exec();
+}
Index: trunk/tools/FlairGCS/src/mapwidget.cpp
===================================================================
--- trunk/tools/FlairGCS/src/mapwidget.cpp	(revision 9)
+++ trunk/tools/FlairGCS/src/mapwidget.cpp	(revision 9)
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of Qt. It was originally
+** published as part of Qt Quarterly.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QGeoCoordinate>
+#include <QGraphicsScene>
+
+#include <QTimer>
+#include <QMenu>
+#include "mapwidget.h"
+#include "Landmark.h"
+#include "Map.h"
+
+using namespace QtMobility;
+
+MapWidget::MapWidget(Map* map,QWidget *parent)
+    : QGraphicsView(parent) {
+    setCursor(Qt::ArrowCursor);
+    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+    geoMap = 0;
+    dragging = false;
+    pressed = false;
+    landmark_match=NULL;
+    is_uptodate=true;
+    this->map=map;
+
+    m_scene = new QGraphicsScene(this);
+    setScene(m_scene);
+    setMouseTracking(true);
+
+    landmarks=new QList<Landmark*>;
+    landmarks_old=new QList<Landmark*>;
+}
+
+QGraphicsScene *MapWidget::scene(void) const
+{
+    return m_scene;
+}
+
+void MapWidget::setMap(QGraphicsGeoMap *geoMap)
+{
+    m_scene->clear();
+    m_scene->addItem(geoMap);
+    this->geoMap = geoMap;
+    geoMap->resize(m_scene->sceneRect().width(), m_scene->sceneRect().height());
+}
+
+void MapWidget::mousePressEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::LeftButton)
+    {
+        pressed = true;
+        dragStartPosition = event->pos();
+        QTimer::singleShot(qApp->startDragTime(), this, SLOT(initDrag()));
+        event->accept();
+    }
+
+    if (event->button() == Qt::RightButton)
+    {
+        QMenu *menu = new QMenu("nom", this);
+
+        if(cursor().shape()!=Qt::PointingHandCursor)
+        {
+            QAction *b,*z;//*a,
+            QList<QAction*> go_to_actions;
+            QList<QAction*> centered_actions;
+
+            QMenu *centered_menu=menu->addMenu("centered");
+            for(int i=0;i<points.count();i++)
+            {
+                QAction* action=centered_menu->addAction(points.at(i));
+                centered_actions.append(action);
+                action->setCheckable(true);
+                if(map->centeredPoint()==i)
+                {
+                    action->setChecked(true);
+                }
+                else
+                {
+                    action->setChecked(false);
+                }
+            }
+
+            menu->addSeparator();
+
+            b=menu->addAction("place checkpoint");
+            QMenu *go_to_menu=menu->addMenu("go to");
+            for(int i=0;i<landmarks->count();i++)
+            {
+                QAction* action=go_to_menu->addAction(QString("checkpoint %1").arg(i+1));
+                go_to_actions.append(action);
+            }
+            if(landmarks->count()==0) go_to_menu->setEnabled(false);
+
+            map->appendmenu(menu);
+            z=map->execmenu(this,menu,event->globalPos());
+
+            for(int i=0;i<centered_actions.count();i++)
+            {
+                if(z==centered_actions.at(i))
+                {
+                    if(centered_actions.at(i)->isChecked())
+                    {
+                        map->setCenteredPoint(i);
+                    }
+                    else
+                    {
+                        map->setCenteredPoint(-1);
+                    }
+
+                    break;
+                }
+            }
+
+            if(z==b)
+            {
+                Landmark* landmark=new Landmark(geoMap,geoMap->screenPositionToCoordinate(event->pos()),QString("%1").arg(landmarks->count()+1));
+                landmarks->append(landmark);
+                is_uptodate=false;
+            }
+            for(int i=0;i<go_to_actions.count();i++)
+            {
+                if(z==go_to_actions.at(i))
+                {
+                    map->setCenteredPoint(-1);
+                    geoMap->setCenter(landmarks->at(i)->coordinate());
+                    break;
+                }
+            }
+
+        }
+        else
+        {
+            QAction *a,*z;
+            a=menu->addAction("delete");
+            z=menu->exec(event->globalPos());
+
+            if(z==a)
+            {
+                int i;
+                for(i=0;i<landmarks->count();i++)
+                {
+                    if(landmarks->at(i)->contains(geoMap->screenPositionToCoordinate(event->pos())))
+                    {
+                        delete landmarks->at(i);
+                        landmarks->removeAt(i);
+                        break;
+                    }
+                }
+                for(int j=i;j<landmarks->count();j++)
+                {
+                    landmarks->at(j)->setText(QString("%1").arg(j+1));
+                }
+            }
+        }
+
+        delete menu;
+    }
+}
+
+void MapWidget::initDrag(void)
+{
+    if (pressed && map->isCentered() && landmark_match==NULL) {
+        dragging = true;
+    }
+}
+
+void MapWidget::mouseMoveEvent(QMouseEvent *event)
+{
+    if (!geoMap)
+        return;
+
+    Qt::CursorShape new_cursor;
+    if(dragging==true)
+    {
+        new_cursor=Qt::ClosedHandCursor;
+    }
+    else
+    {
+        if(map->isCentered())
+        {
+            if(pressed==true)
+            {
+                new_cursor=Qt::ForbiddenCursor;
+            }
+            else
+            {
+                new_cursor=Qt::ArrowCursor;
+            }
+        }
+        else
+        {
+            new_cursor=Qt::OpenHandCursor;
+        }
+        if(landmark_match!=NULL) new_cursor=Qt::PointingHandCursor;
+    }
+
+
+    for(int i=0;i<landmarks->count();i++)
+    {
+        if(landmarks->at(i)->contains(geoMap->screenPositionToCoordinate(event->pos())))
+        {
+            if(pressed && landmark_match==NULL)
+            {
+                landmark_match=landmarks->at(i);
+                landmark_match->setColor(Qt::red);
+                is_uptodate=false;
+            }
+            new_cursor=Qt::PointingHandCursor;
+            break;
+        }
+    }
+
+    if(new_cursor!=cursor().shape()) setCursor(new_cursor);
+
+    QPoint v = event->pos() - dragStartPosition;
+
+    if (dragging) {
+        geoMap->pan(-v.x(), -v.y());
+        dragStartPosition = event->pos();
+
+    } else if(landmark_match!=NULL){
+        landmark_match->setCoordinate(geoMap->screenPositionToCoordinate(event->pos()));
+
+    } else if (pressed && !map->isCentered() &&
+        v.manhattanLength() >= qApp->startDragDistance()) {
+        dragging = true;
+
+    } else {
+        dragStartPosition = event->pos();
+        emit positionChanged(geoMap->screenPositionToCoordinate(event->pos()));
+    }
+
+    event->accept();
+}
+
+void MapWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+    pressed = false;
+    landmark_match=NULL;
+
+    if (dragging) {
+        QPoint v = event->pos() - dragStartPosition;
+        geoMap->pan(-v.x(), -v.y());
+        dragging = false;
+    }
+
+    event->accept();
+}
+
+void MapWidget::resizeEvent(QResizeEvent *event)
+{
+    if (geoMap) {
+        m_scene->setSceneRect(QRectF(0, 0, event->size().width(), event->size().height()));
+        geoMap->resize(event->size().width(), event->size().height());
+    }
+
+    QGraphicsView::resizeEvent(event);
+}
+
+void MapWidget::wheelEvent(QWheelEvent *event)
+{
+    int steps = event->delta() / 120;
+    int zoom = qBound(geoMap->minimumZoomLevel(), geoMap->zoomLevel() + steps,
+                      geoMap->maximumZoomLevel());
+
+    if (zoom != geoMap->zoomLevel()) geoMap->setZoomLevel(zoom);
+    //if(!centered) geoMap->setCenter(geoMap->screenPositionToCoordinate(event->pos()));
+}
+
+void MapWidget::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    if(!map->isCentered()) geoMap->setCenter(geoMap->screenPositionToCoordinate(event->pos()));
+}
+
+bool MapWidget::IsUptodate(void)
+{
+    return is_uptodate;
+}
+
+void MapWidget::SetUptodate(void)
+{
+    for(int i=0;i<landmarks_old->count();i++)
+    {
+        delete landmarks_old->at(i);
+    }
+    landmarks_old->clear();
+
+    for(int i=0;i<landmarks->count();i++)
+    {
+        landmarks->at(i)->setColor(Qt::white);
+        Landmark* landmark=new Landmark(geoMap,landmarks->at(i)->coordinate(),QString("%1").arg(landmarks->count()+1));
+        landmarks_old->append(landmark);
+        landmarks_old->at(i)->setVisible(false);
+    }
+
+    is_uptodate=true;
+}
+
+void MapWidget::Reset(void)
+{
+    for(int i=0;i<landmarks->count();i++)
+    {
+        delete landmarks->at(i);
+    }
+    landmarks->clear();
+
+    for(int i=0;i<landmarks_old->count();i++)
+    {
+        Landmark* landmark=new Landmark(geoMap,landmarks_old->at(i)->coordinate(),QString("%1").arg(landmarks->count()+1));
+        landmarks->append(landmark);
+        landmarks->at(i)->setColor(Qt::white);
+    }
+
+    is_uptodate=true;
+}
+
+QList<Landmark*>* MapWidget::Landmarks(void)
+{
+    return landmarks;
+}
+
+bool MapWidget::LandmarkToSend(int index)
+{
+    if(index>=landmarks_old->count()) return true;
+
+    if(landmarks->at(index)->coordinate()!=landmarks_old->at(index)->coordinate())
+        return true;
+    else
+        return false;
+}
+void MapWidget::RemoveLandmarks(void)
+{
+    for(int i=0;i<landmarks->count();i++)
+    {
+        landmarks->at(i)->RemoveLandmark();
+    }
+    for(int i=0;i<landmarks_old->count();i++)
+    {
+        landmarks_old->at(i)->RemoveLandmark();
+    }
+}
+
+void MapWidget::AddLandmarks(QGraphicsGeoMap *geoMap)
+{
+    for(int i=0;i<landmarks->count();i++)
+    {
+        landmarks->at(i)->AddLandmark(geoMap);
+    }
+    for(int i=0;i<landmarks_old->count();i++)
+    {
+        landmarks_old->at(i)->AddLandmark(geoMap);
+    }
+}
+
+void MapWidget::AddLandmark(const QGeoCoordinate &coordinate)
+{
+    Landmark* landmark=new Landmark(geoMap,coordinate,QString("%1").arg(landmarks->count()+1));
+    landmarks->append(landmark);
+    landmark->setColor(Qt::white);
+    landmark=new Landmark(geoMap,coordinate,QString("%1").arg(landmarks_old->count()+1));
+    landmarks_old->append(landmark);
+    landmark->setColor(Qt::white);
+    landmark->setVisible(false);
+}
+
+void MapWidget::AddPoint(QString name)
+{
+    points.append(name);
+}
Index: trunk/tools/FlairGCS/src/mapwidget.h
===================================================================
--- trunk/tools/FlairGCS/src/mapwidget.h	(revision 9)
+++ trunk/tools/FlairGCS/src/mapwidget.h	(revision 9)
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of Qt. It was originally
+** published as part of Qt Quarterly.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAPWIDGET_H
+#define MAPWIDGET_H
+
+#include <QGraphicsView>
+#include <QGraphicsGeoMap>
+
+class QGraphicsScene;
+class Map;
+class Landmark;
+
+using namespace QtMobility;
+
+class MapWidget : public QGraphicsView
+{
+    Q_OBJECT
+
+    public:
+        MapWidget(Map* map,QWidget *parent = 0);
+        void setMap(QtMobility::QGraphicsGeoMap *geoMap);
+        QGraphicsScene *scene() const;
+        bool IsUptodate(void);
+        void SetUptodate(void);
+        void Reset(void);
+        QList<Landmark*>* Landmarks(void);
+        bool LandmarkToSend(int index);
+        void AddLandmark(const QGeoCoordinate &coordinate);
+        void RemoveLandmarks(void);
+        void AddLandmarks(QGraphicsGeoMap *geoMap);
+        void AddPoint(QString name);
+
+    signals:
+        void positionChanged(const QGeoCoordinate &coordinate);
+
+    protected:
+        void mousePressEvent(QMouseEvent *event);
+        void mouseMoveEvent(QMouseEvent *event);
+        void mouseReleaseEvent(QMouseEvent *event);
+        void resizeEvent(QResizeEvent *event);
+        void wheelEvent(QWheelEvent *event);
+        void mouseDoubleClickEvent(QMouseEvent *event);
+
+    private slots:
+        void initDrag();
+
+    private:
+        QGraphicsGeoMap *geoMap;
+        bool dragging;
+        QPoint dragStartPosition;
+        bool pressed;
+        bool is_uptodate;
+
+        QGraphicsScene *m_scene;
+        QList<Landmark*> *landmarks;
+        QList<Landmark*> *landmarks_old;
+        QList<QString> points;
+        Landmark *landmark_match;
+        Map* map;
+};
+
+#endif
Index: trunk/tools/FlairGCS/src/ressources.qrc
===================================================================
--- trunk/tools/FlairGCS/src/ressources.qrc	(revision 9)
+++ trunk/tools/FlairGCS/src/ressources.qrc	(revision 9)
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+  <file>zoomin.png</file>
+  <file>zoomout.png</file>
+  <file>landmark.png</file>
+  <file>cross.png</file>
+</qresource>
+</RCC>
