diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9759542..3c5c203 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 2.8)
-option( INSTALL_QCANUPO2_PLUGIN "Check to install qCanupo2 plugin" OFF )
+option( INSTALL_Q3DMASC_PLUGIN "Check to install q3DMASC plugin" OFF )
-if (INSTALL_QCANUPO2_PLUGIN)
+if (INSTALL_Q3DMASC_PLUGIN)
#New classification plugin (Dimitri Lague/OSUR)
-project( QCANUPO2_PLUGIN_DLL )
+project( Q3DMASC_PLUGIN_DLL )
#need OpenCV
find_package( OpenCV REQUIRED )
@@ -16,6 +16,7 @@ project( QCANUPO2_PLUGIN_DLL )
#include the whole CC directory (easier)
include_directories( ${CloudCompare_SOURCE_DIR} )
+ #include_directories( ${OpenCV_INCLUDE_DIR} )
#we need the "order choice" dialog
file( GLOB CC_PLUGIN_CUSTOM_HEADER_LIST ${CloudCompare_SOURCE_DIR}/ccOrderChoiceDlg*.h )
diff --git a/Logo_cnrs_eub_eec.png b/Logo_cnrs_eub_eec.png
new file mode 100644
index 0000000..69467bb
Binary files /dev/null and b/Logo_cnrs_eub_eec.png differ
diff --git a/classifyDisclaimerDlg.ui b/classifyDisclaimerDlg.ui
new file mode 100644
index 0000000..c8f0091
--- /dev/null
+++ b/classifyDisclaimerDlg.ui
@@ -0,0 +1,112 @@
+
+
+ ClassifyDisclaimerDialog
+
+
+
+ 0
+ 0
+ 460
+ 250
+
+
+
+ q3DMASC_classify (disclaimer)
+
+
+
+ :/CC/plugin/qCanupoPlugin/iconClassify.png:/CC/plugin/qCanupoPlugin/iconClassify.png
+
+
+ -
+
+
-
+
+
+
+ 150
+ 174
+
+
+
+
+
+
+ :/CC/plugin/q3DMASC/Logo_cnrs_eub_eec.png
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; font-weight:600; color:#1f497d;">3D Multi-cloud, Multi-Attribute, multi-Scale, multi Class classification (3DMASC)</span></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; font-style:italic; color:#1f497d;">Le Guennec, A., Lague, D., Corpetti, Th., Lefevre, S.</span></p>
+<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Calibri,sans-serif'; font-size:10pt; font-style:italic; color:#1f497d; background-color:#ffffff;"><br /></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d; background-color:#ffffff;">Funded by Université Européenne de Bretagne, Centre National de la Recherche Scientifique and EEC Marie-Curie actions</span></p>
+<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d; background-color:#ffffff;"><br /></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d;">Enjoy!</span></p></body></html>
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ ClassifyDisclaimerDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ ClassifyDisclaimerDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/iconClassify.png b/iconClassify.png
new file mode 100644
index 0000000..9437a2d
Binary files /dev/null and b/iconClassify.png differ
diff --git a/iconCreate.png b/iconCreate.png
new file mode 100644
index 0000000..663b3ae
Binary files /dev/null and b/iconCreate.png differ
diff --git a/info.json b/info.json
new file mode 100644
index 0000000..dffa0c4
--- /dev/null
+++ b/info.json
@@ -0,0 +1,26 @@
+{
+ "type": "Standard",
+ "name": "3DMASC",
+ "icon": ":/CC/plugin/q3DMASC/iconCreate.png",
+ "description": "Create or apply a classifier on a point cloud.",
+ "authors": [
+ {
+ "name": "Dimitri Lague (OSUR/CNRS)"
+ }
+ ],
+ "maintainers": [
+ {
+ "name": "Dimitri Lague (OSUR/CNRS)"
+ }
+ ],
+ "references": [
+ {
+ "text": "Dimitri Lague, Geosciences Rennes",
+ "url": "https://geosciences.univ-rennes1.fr/interlocuteurs/dimitri-lague"
+ },
+ {
+ "text": "Documentation",
+ "url": "http://www.cloudcompare.org/doc/wiki/index.php?title=3DMASC_(plugin)"
+ }
+ ]
+}
diff --git a/q3DMASC.cpp b/q3DMASC.cpp
new file mode 100644
index 0000000..7000fa8
--- /dev/null
+++ b/q3DMASC.cpp
@@ -0,0 +1,171 @@
+//##########################################################################
+//# #
+//# CLOUDCOMPARE PLUGIN: q3DMASC #
+//# #
+//# This program is free software; you can redistribute it and/or modify #
+//# it under the terms of the GNU General Public License as published by #
+//# the Free Software Foundation; version 2 or later of the License. #
+//# #
+//# This program is distributed in the hope that it will be useful, #
+//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+//# GNU General Public License for more details. #
+//# #
+//# COPYRIGHT: Dimitri Lague / CNRS / UEB #
+//# #
+//##########################################################################
+
+#include "q3DMASC.h"
+
+//local
+#include "q3DMASCDisclaimerDialog.h"
+
+//qCC_db
+#include
+
+//Qt
+#include
+#include
+#include
+#include
+#include
+
+q3DMASCPlugin::q3DMASCPlugin(QObject* parent/*=0*/)
+ : QObject(parent)
+ , ccStdPluginInterface( ":/CC/plugin/q3DMASCPlugin/info.json" )
+ , m_classifyAction(0)
+ , m_trainAction(0)
+{
+}
+
+void q3DMASCPlugin::onNewSelection(const ccHObject::Container& selectedEntities)
+{
+ if (m_classifyAction)
+ {
+ //classification: only one point cloud
+ m_classifyAction->setEnabled(selectedEntities.size() == 1 && selectedEntities[0]->isA(CC_TYPES::POINT_CLOUD));
+ }
+
+ if (m_trainAction)
+ {
+ m_trainAction->setEnabled(m_app && m_app->dbRootObject() && m_app->dbRootObject()->getChildrenNumber() != 0); //need some loaded entities to train the classifier!
+ }
+
+ m_selectedEntities = selectedEntities;
+}
+
+QList q3DMASCPlugin::getActions()
+{
+ QList group;
+
+ if (!m_trainAction)
+ {
+ m_trainAction = new QAction("Train classifier", this);
+ m_trainAction->setToolTip("Train classifier");
+ m_trainAction->setIcon(QIcon(QString::fromUtf8(":/CC/plugin/q3DMASCPlugin/iconCreate.png")));
+ connect(m_trainAction, SIGNAL(triggered()), this, SLOT(doTrainAction()));
+ }
+ group.push_back(m_trainAction);
+
+ if (!m_classifyAction)
+ {
+ m_classifyAction = new QAction("Classify", this);
+ m_classifyAction->setToolTip("Classify cloud");
+ m_classifyAction->setIcon(QIcon(QString::fromUtf8(":/CC/plugin/q3DMASCPlugin/iconClassify.png")));
+ connect(m_classifyAction, SIGNAL(triggered()), this, SLOT(doClassifyAction()));
+ }
+ group.push_back(m_classifyAction);
+
+ return group;
+}
+
+#include
+
+void q3DMASCPlugin::doClassifyAction()
+{
+ if (!m_app)
+ {
+ assert(false);
+ return;
+ }
+
+ //disclaimer accepted?
+ if (!ShowClassifyDisclaimer(m_app))
+ {
+ return;
+ }
+
+ if (m_selectedEntities.empty() || !m_selectedEntities.front()->isA(CC_TYPES::POINT_CLOUD))
+ {
+ m_app->dispToConsole("Select one and only one point cloud!", ccMainAppInterface::ERR_CONSOLE_MESSAGE);
+ return;
+ }
+
+ ccPointCloud* cloud = static_cast(m_selectedEntities.front());
+
+ struct RTParams
+ {
+ int maxDepth = 25; //To be left as a parameter of the training plugin (default 25)
+ int minSampleCount = 1; //To be left as a parameter of the training plugin (default 1)
+ int maxCategories = 0; //Normally not important as there’s no categorical variable
+ const bool calcVarImportance = true; //Must be true
+ int activeVarCount = 0; //USE 0 as the default parameter (works best)
+ int maxTreeCount = 100; //Left as a parameter of the training plugin (default: 100)
+ };
+ RTParams params;
+
+ unsigned sampleCount = cloud->size();
+ unsigned attributesPerSample = cloud->getNumberOfScalarFields();
+
+ //NUMBER_OF_TRAINING_SAMPLES = number of points
+ //ATTRIBUTES_PER_SAMPLE = number of scalar fields
+ cv::Mat training_data = cv::Mat(sampleCount, attributesPerSample, CV_32FC1);
+ cv::Mat train_labels = cv::Mat(attributesPerSample, 1, CV_32FC1);
+
+ cv::Ptr rtrees;
+ rtrees = cv::ml::RTrees::create();
+ rtrees->setMaxDepth(params.maxDepth);
+ rtrees->setMinSampleCount(params.minSampleCount);
+ rtrees->setCalculateVarImportance(params.calcVarImportance);
+ rtrees->setActiveVarCount(params.activeVarCount);
+ cv::TermCriteria terminationCriteria(cv::TermCriteria::MAX_ITER, params.maxTreeCount, std::numeric_limits::epsilon());
+ rtrees->setTermCriteria(terminationCriteria);
+
+ //rtrees->setRegressionAccuracy(0);
+ //rtrees->setUseSurrogates(false);
+ //rtrees->setMaxCategories(params.maxCategories); //not important?
+ //rtrees->setPriors(cv::Mat());
+
+ rtrees->train(training_data, cv::ml::ROW_SAMPLE, train_labels);
+
+}
+
+//OpenCV
+
+void q3DMASCPlugin::doTrainAction()
+{
+ //disclaimer accepted?
+ if (!ShowTrainDisclaimer(m_app))
+ return;
+
+ //if (m_selectedEntities.size() != 2
+ // || !m_selectedEntities[0]->isA(CC_TYPES::POINT_CLOUD)
+ // || !m_selectedEntities[1]->isA(CC_TYPES::POINT_CLOUD))
+ //{
+ // m_app->dispToConsole("Select two point clouds!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
+ // return;
+ //}
+ //
+ //ccPointCloud* cloud1 = static_cast(m_selectedEntities[0]);
+ //ccPointCloud* cloud2 = static_cast(m_selectedEntities[1]);
+}
+
+void q3DMASCPlugin::registerCommands(ccCommandLineInterface* cmd)
+{
+ if (!cmd)
+ {
+ assert(false);
+ return;
+ }
+ //cmd->registerCommand(ccCommandLineInterface::Command::Shared(new CommandCanupoClassif));
+}
diff --git a/qCanupo2Plugin.h b/q3DMASC.h
similarity index 55%
rename from qCanupo2Plugin.h
rename to q3DMASC.h
index 9cc2a97..4f8e7f0 100644
--- a/qCanupo2Plugin.h
+++ b/q3DMASC.h
@@ -1,57 +1,62 @@
//##########################################################################
//# #
-//# CLOUDCOMPARE PLUGIN: qCanupo2 #
+//# CLOUDCOMPARE PLUGIN: q3DMASC #
//# #
//# This program is free software; you can redistribute it and/or modify #
//# it under the terms of the GNU General Public License as published by #
-//# the Free Software Foundation; version 2 of the License. #
+//# the Free Software Foundation; version 2 or later of the License. #
//# #
//# This program is distributed in the hope that it will be useful, #
//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
//# GNU General Public License for more details. #
//# #
-//# COPYRIGHT: OSUR #
+//# COPYRIGHT: Dimitri Lague / CNRS / UEB #
//# #
//##########################################################################
-#ifndef QCANUPO2_PLUGIN_HEADER
-#define QCANUPO2_PLUGIN_HEADER
+#ifndef Q_3DMASC_PLUGIN_HEADER
+#define Q_3DMASC_PLUGIN_HEADER
//qCC
#include
-//! New classification plugin (Dimitri Lague / OSUR)
-class qCanupo2Plugin : public QObject, public ccStdPluginInterface
+//qCC_db
+#include
+
+//! 3DMASC plugin
+/** 3D Multi-cloud, multi-Attribute, multi-Scale, multi-Class classification
+**/
+class q3DMASCPlugin : public QObject, public ccStdPluginInterface
{
Q_OBJECT
Q_INTERFACES(ccStdPluginInterface)
- //replace qDummy by the plugin name (IID should be unique - let's hope your plugin name is unique ;)
- Q_PLUGIN_METADATA(IID "cccorp.cloudcompare.plugin.qCanupo2")
+ Q_PLUGIN_METADATA(IID "cccorp.cloudcompare.plugin.q3DMASC" FILE "info.json")
public:
//! Default constructor
- explicit qCanupo2Plugin(QObject* parent = 0);
-
- //inherited from ccPluginInterface
- virtual QString getName() const override { return "CANUPO V2"; }
- virtual QString getDescription() const override { return "CANUPO V2 Classification (D. Lague, A. le Guennec)"; }
- virtual QIcon getIcon() const override;
+ q3DMASCPlugin(QObject* parent = nullptr);
//inherited from ccStdPluginInterface
void onNewSelection(const ccHObject::Container& selectedEntities) override;
virtual QList getActions() override;
+ virtual void registerCommands(ccCommandLineInterface* cmd) override;
protected slots:
- void doAction();
+ void doClassifyAction();
+ void doTrainAction();
protected:
- //! Default action
- QAction* m_action;
+ //! Calssift action
+ QAction* m_classifyAction;
+ //! Train action
+ QAction* m_trainAction;
+
+ //! Currently selected entities
+ ccHObject::Container m_selectedEntities;
};
-#endif //QCANUPO2_PLUGIN_HEADER
-
+#endif //Q_3DMASC_PLUGIN_HEADER
diff --git a/q3DMASC.qrc b/q3DMASC.qrc
new file mode 100644
index 0000000..6fa4b2e
--- /dev/null
+++ b/q3DMASC.qrc
@@ -0,0 +1,7 @@
+
+
+ iconClassify.png
+ iconCreate.png
+ Logo_cnrs_eub_eec.png
+
+
diff --git a/q3DMASCDisclaimerDialog.h b/q3DMASCDisclaimerDialog.h
new file mode 100644
index 0000000..3db831d
--- /dev/null
+++ b/q3DMASCDisclaimerDialog.h
@@ -0,0 +1,84 @@
+//##########################################################################
+//# #
+//# CLOUDCOMPARE PLUGIN: q3DMASC #
+//# #
+//# This program is free software; you can redistribute it and/or modify #
+//# it under the terms of the GNU General Public License as published by #
+//# the Free Software Foundation; version 2 or later of the License. #
+//# #
+//# This program is distributed in the hope that it will be useful, #
+//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+//# GNU General Public License for more details. #
+//# #
+//# COPYRIGHT: Dimitri Lague / CNRS / UEB #
+//# #
+//##########################################################################
+
+#ifndef Q3DMASC_DISCLAIMER_DIALOG_HEADER
+#define Q3DMASC_DISCLAIMER_DIALOG_HEADER
+
+#include
+#include
+
+//qCC_plugins
+#include
+
+//Qt
+#include
+
+//! Dialog for displaying the 3DSMAC/UEB disclaimer
+class TrainDisclaimerDialog : public QDialog, public Ui::TrainDisclaimerDialog
+{
+public:
+ //! Default constructor
+ TrainDisclaimerDialog(QWidget* parent = 0)
+ : QDialog(parent)
+ , Ui::TrainDisclaimerDialog()
+ {
+ setupUi(this);
+ }
+};
+
+//whether disclaimer has already been displayed (and accepted) or not
+static bool s_trainDisclaimerAccepted = false;
+
+static bool ShowTrainDisclaimer(ccMainAppInterface* app)
+{
+ if (!s_trainDisclaimerAccepted)
+ {
+ //if the user "cancels" it, then he refuses the diclaimer!
+ s_trainDisclaimerAccepted = TrainDisclaimerDialog(app ? app->getMainWindow() : 0).exec();
+ }
+
+ return s_trainDisclaimerAccepted;
+}
+
+//! Dialog for displaying the M3C2/UEB disclaimer
+class ClassifyDisclaimerDialog : public QDialog, public Ui::ClassifyDisclaimerDialog
+{
+public:
+ //! Default constructor
+ ClassifyDisclaimerDialog(QWidget* parent = 0)
+ : QDialog(parent)
+ , Ui::ClassifyDisclaimerDialog()
+ {
+ setupUi(this);
+ }
+};
+
+//whether disclaimer has already been displayed (and accepted) or not
+static bool s_classifyDisclaimerAccepted = false;
+
+static bool ShowClassifyDisclaimer(ccMainAppInterface* app)
+{
+ if (!s_classifyDisclaimerAccepted)
+ {
+ //if the user "cancels" it, then he refuses the diclaimer!
+ s_classifyDisclaimerAccepted = ClassifyDisclaimerDialog(app ? app->getMainWindow() : 0).exec();
+ }
+
+ return s_classifyDisclaimerAccepted;
+}
+
+#endif //Q3DMASC_DISCLAIMER_DIALOG_HEADER
diff --git a/qCanupo2Plugin.cpp b/qCanupo2Plugin.cpp
deleted file mode 100644
index 4c8a807..0000000
--- a/qCanupo2Plugin.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//##########################################################################
-//# #
-//# CLOUDCOMPARE PLUGIN: qDummy #
-//# #
-//# This program is free software; you can redistribute it and/or modify #
-//# it under the terms of the GNU General Public License as published by #
-//# the Free Software Foundation; version 2 of the License. #
-//# #
-//# This program is distributed in the hope that it will be useful, #
-//# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-//# GNU General Public License for more details. #
-//# #
-//# COPYRIGHT: XXX #
-//# #
-//##########################################################################
-
-#include "qCanupo2Plugin.h"
-
-//Qt
-#include
-
-qCanupo2Plugin::qCanupo2Plugin(QObject* parent/*=0*/)
- : QObject(parent)
- , m_action(0)
-{
-}
-
-void qCanupo2Plugin::onNewSelection(const ccHObject::Container& selectedEntities)
-{
- //if (m_action)
- // m_action->setEnabled(!selectedEntities.empty());
-}
-
-QList qCanupo2Plugin::getActions()
-{
- if (!m_action)
- {
- m_action = new QAction(getName(),this);
- m_action->setToolTip(getDescription());
- m_action->setIcon(getIcon());
- //connect appropriate signal
- connect(m_action, SIGNAL(triggered()), this, SLOT(doAction()));
- }
-
- return QList{m_action};
-}
-
-void qCanupo2Plugin::doAction()
-{
- //m_app should have already been initialized by CC when plugin is loaded!
- //(--> pure internal check)
- assert(m_app);
- if (!m_app)
- return;
-
- m_app->dispToConsole("[qCanupo2Plugin] Hello world!",ccMainAppInterface::STD_CONSOLE_MESSAGE); //a standard message is displayed in the console
- m_app->dispToConsole("[qCanupo2Plugin] Warning: dummy plugin shouldn't be used as is!",ccMainAppInterface::WRN_CONSOLE_MESSAGE); //a warning message is displayed in the console
- m_app->dispToConsole("Dummy plugin shouldn't be used as is!",ccMainAppInterface::ERR_CONSOLE_MESSAGE); //an error message is displayed in the console AND an error box will pop-up!
-}
-
-QIcon qCanupo2Plugin::getIcon() const
-{
- return QIcon(":/CC/plugin/qCanupo2/icon.png");
-}
diff --git a/qCanupo2Plugin.qrc b/qCanupo2Plugin.qrc
deleted file mode 100644
index b3a6622..0000000
--- a/qCanupo2Plugin.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- icon.png
-
-
diff --git a/trainDisclaimerDlg.ui b/trainDisclaimerDlg.ui
new file mode 100644
index 0000000..510681f
--- /dev/null
+++ b/trainDisclaimerDlg.ui
@@ -0,0 +1,113 @@
+
+
+ TrainDisclaimerDialog
+
+
+
+ 0
+ 0
+ 460
+ 250
+
+
+
+ q3DSMAC_create (disclaimer)
+
+
+
+ :/CC/plugin/qCanupoPlugin/iconCreate.png:/CC/plugin/qCanupoPlugin/iconCreate.png
+
+
+ -
+
+
-
+
+
+
+ 150
+ 174
+
+
+
+
+
+
+ :/CC/plugin/q3DMASC/Logo_cnrs_eub_eec.png
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; font-weight:600; color:#1f497d;">Classifier creation (3DSMAC)</span></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; font-style:italic; color:#1f497d;">Le Guennec, A., Lague, D., Corpetti, Th., Lefevre, S.</span></p>
+<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Calibri,sans-serif'; font-size:10pt; font-style:italic; color:#1f497d; background-color:#ffffff;"><br /></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d; background-color:#ffffff;">Funded by Université Européenne de Bretagne, Centre National de la Recherche Scientifique and EEC Marie-Curie actions</span></p>
+<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d; background-color:#ffffff;"><br /></p>
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;"><span style=" font-family:'Calibri,sans-serif'; font-size:10pt; color:#1f497d;">Enjoy!</span></p></body></html>
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ TrainDisclaimerDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ TrainDisclaimerDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+