From 98e48a3585448f5f12442a0f1304f15e759f18f7 Mon Sep 17 00:00:00 2001
From: "d.kilic" <d.kilic@fz-juelich.de>
Date: Tue, 6 Jul 2021 09:17:44 +0000
Subject: [PATCH] Resolve "Add Support for mutliple MoCap-Files" - changed
 dialogue "Open MoCap" to "Manage MoCap" - enable loading multiple MoCap-Files
 (or same with different offset) - enable unloading MoCap-Files - save all
 files in pet and load when opening project

---
 CMakeLists.txt                 |   3 +
 include/moCapPersonMetadata.h  |   4 +-
 include/moCapSelectionWidget.h |  38 +++++++++++
 include/openMoCapDialog.h      |   4 +-
 include/petrack.h              |   1 -
 src/moCapPersonMetadata.cpp    |   8 +--
 src/moCapSelectionWidget.cpp   |  97 ++++++++++++++++++++++++++++
 src/openMoCapDialog.cpp        |  95 +++++++++++++++-------------
 src/petrack.cpp                |   4 +-
 ui/moCapSelectionWidget.ui     | 105 +++++++++++++++++++++++++++++++
 ui/openMoCapDialog.ui          | 111 ++++++++++++++++++++-------------
 11 files changed, 374 insertions(+), 96 deletions(-)
 create mode 100644 include/moCapSelectionWidget.h
 create mode 100644 src/moCapSelectionWidget.cpp
 create mode 100644 ui/moCapSelectionWidget.ui

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b187aa3cd..5c26888be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,6 +326,7 @@ target_sources(petrack_core PRIVATE
     include/openMoCapDialog.h
     include/moCapPersonMetadata.h
     include/pMessageBox.h
+    include/moCapSelectionWidget.h
     )
 
 target_sources(petrack_core PRIVATE
@@ -384,6 +385,7 @@ target_sources(petrack_core PRIVATE
     src/openMoCapDialog.cpp
     src/moCapPersonMetadata.cpp
     src/pMessageBox.cpp
+    src/moCapSelectionWidget.cpp
     ui/about.ui
     ui/codeMarker.ui
     ui/colorMarker.ui
@@ -392,6 +394,7 @@ target_sources(petrack_core PRIVATE
     ui/stereo.ui
     ui/control.ui
     ui/openMoCapDialog.ui
+    ui/moCapSelectionWidget.ui
 )
 
 target_sources(petrack PRIVATE
diff --git a/include/moCapPersonMetadata.h b/include/moCapPersonMetadata.h
index a8d0de67f..e09c581bf 100644
--- a/include/moCapPersonMetadata.h
+++ b/include/moCapPersonMetadata.h
@@ -46,12 +46,12 @@ public:
     MoCapPersonMetadata& operator=(const MoCapPersonMetadata&) = default;
     MoCapPersonMetadata& operator=(MoCapPersonMetadata&&) = default;
     ~MoCapPersonMetadata() = default;
-    MoCapPersonMetadata(std::string filepath, MoCapSystem system, int samplerate, double offset);
+    MoCapPersonMetadata(std::string filepath, MoCapSystem system, double samplerate, double offset);
 
     void setFilepath(const std::string &filepath, MoCapSystem system);
     void setSamplerate(double samplerate);
     void setOffset(double offset);
-    void setMetadata(const std::string &filepath, MoCapSystem, int samplerate, double offset);
+    void setMetadata(const std::string &filepath, MoCapSystem, double samplerate, double offset);
     MoCapSystem getSystem() const;
     double getSamplerate() const;
     double getOffset() const;
diff --git a/include/moCapSelectionWidget.h b/include/moCapSelectionWidget.h
new file mode 100644
index 000000000..837af10a0
--- /dev/null
+++ b/include/moCapSelectionWidget.h
@@ -0,0 +1,38 @@
+#ifndef MOCAPSELECTIONWIDGET_H
+#define MOCAPSELECTIONWIDGET_H
+
+#include <QWidget>
+
+#include "moCapPersonMetadata.h"
+
+namespace Ui {
+    class MoCapSelectionWidget;
+}
+class OpenMoCapDialog;
+
+class MoCapSelectionWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit MoCapSelectionWidget(QWidget *parent, const QMap<QString, MoCapSystem>& moCapSystems);
+    explicit MoCapSelectionWidget(QWidget *parent, const QMap<QString, MoCapSystem>& moCapSystems, const MoCapPersonMetadata& metadata);
+    MoCapSelectionWidget(const MoCapSelectionWidget&) = delete;
+    MoCapSelectionWidget(MoCapSelectionWidget&&) = delete;
+    MoCapSelectionWidget& operator=(const MoCapSelectionWidget&) = delete;
+    MoCapSelectionWidget& operator=(MoCapSelectionWidget&&) = delete;
+    ~MoCapSelectionWidget() override;
+
+    void setFileName();
+    MoCapPersonMetadata getMetadata() const;
+
+    bool isFilledOut() const;
+
+private:
+    Ui::MoCapSelectionWidget *mUi;
+    const QMap<QString, MoCapSystem>& mMoCapSystems;
+    bool mFilledOut = false;
+
+};
+
+#endif // MOCAPSELECTIONWIDGET_H
diff --git a/include/openMoCapDialog.h b/include/openMoCapDialog.h
index 2a4b55044..707d41574 100644
--- a/include/openMoCapDialog.h
+++ b/include/openMoCapDialog.h
@@ -52,9 +52,11 @@ public:
     OpenMoCapDialog& operator=(OpenMoCapDialog&&) = delete;
     ~OpenMoCapDialog() override;
 
-    void setFileName();
     void clickedOk();
 
+private slots:
+    void on_btnAddSelection_clicked();
+
 private:
     Ui::OpenMoCapDialog *mUi;
     QMap<QString, MoCapSystem> mMoCapSystems;
diff --git a/include/petrack.h b/include/petrack.h
index a338d6fdc..43d8cabb9 100644
--- a/include/petrack.h
+++ b/include/petrack.h
@@ -39,7 +39,6 @@
 #include "autoCalib.h"
 #include "coordItem.h"
 #include "extrCalibration.h"
-#include "openMoCapDialog.h"
 #include "moCapPerson.h"
 #include "moCapController.h"
 
diff --git a/src/moCapPersonMetadata.cpp b/src/moCapPersonMetadata.cpp
index 37aa6252d..4f3926100 100644
--- a/src/moCapPersonMetadata.cpp
+++ b/src/moCapPersonMetadata.cpp
@@ -20,12 +20,12 @@
 #include <QFileInfo>
 #include "moCapPersonMetadata.h"
 
-MoCapPersonMetadata::MoCapPersonMetadata(std::string filepath, MoCapSystem system, int samplerate, double offset){
+MoCapPersonMetadata::MoCapPersonMetadata(std::string filepath, MoCapSystem system, double samplerate, double offset){
     setMetadata(filepath, system, samplerate, offset);
 }
 
 
-void MoCapPersonMetadata::setMetadata(const std::string &filepath, MoCapSystem system, int samplerate, double offset){
+void MoCapPersonMetadata::setMetadata(const std::string &filepath, MoCapSystem system, double samplerate, double offset){
     setSamplerate(samplerate);
     setOffset(offset);
     setFilepath(filepath, system);
@@ -86,8 +86,8 @@ double MoCapPersonMetadata::getOffset() const {
 
 bool operator==(const MoCapPersonMetadata &lhs, const MoCapPersonMetadata &rhs){
     return (lhs.getFilepath().compare(rhs.getFilepath()) == 0
-            && lhs.getOffset() == rhs.getOffset()
-            && lhs.getSamplerate() == rhs.getSamplerate()
+            && std::abs(lhs.getOffset() - rhs.getOffset()) < 1e-4
+            && std::abs(lhs.getSamplerate() - rhs.getSamplerate()) < 1e-4
             && lhs.getSystem() == rhs.getSystem());
 }
 
diff --git a/src/moCapSelectionWidget.cpp b/src/moCapSelectionWidget.cpp
new file mode 100644
index 000000000..d216f82f0
--- /dev/null
+++ b/src/moCapSelectionWidget.cpp
@@ -0,0 +1,97 @@
+#include <QFileDialog>
+
+#include "moCapSelectionWidget.h"
+#include "ui_moCapSelectionWidget.h"
+#include "openMoCapDialog.h"
+
+MoCapSelectionWidget::MoCapSelectionWidget(QWidget *parent, const QMap<QString, MoCapSystem>& moCapSystems) :
+    QWidget(parent),
+    mUi(new Ui::MoCapSelectionWidget),
+    mMoCapSystems(moCapSystems)
+{
+    mUi->setupUi(this);
+
+    constexpr int defaultSampleRate = 60;
+    constexpr double offsetRange = 5;
+
+    mUi->btnDelete->setIcon(QApplication::style()->standardIcon(QStyle::SP_TrashIcon));
+    mUi->cbInputSystem->addItems(QStringList(moCapSystems.keys()));
+    mUi->cbInputSystem->setCurrentIndex(0);
+    mUi->sampleRateSpinBox->setRange(1, 300);
+    mUi->sampleRateSpinBox->setValue(defaultSampleRate);
+    mUi->offSetSpinBox->setRange(-offsetRange, offsetRange);
+    mUi->offSetSpinBox->setSingleStep(0.01);
+
+    connect(mUi->browseFileButton, &QPushButton::clicked, this, &MoCapSelectionWidget::setFileName);
+    connect(mUi->btnDelete, &QPushButton::clicked, this, &MoCapSelectionWidget::deleteLater);
+}
+
+/**
+ * @brief constructs a widget with the data from a Metadata-Object
+ * @param parent Widget parent (Qt)
+ * @param moCapSystems Map from QString in Combobox to MoCapSystem-Enum
+ * @param metadata Metadata which should be represented by this widget
+ */
+MoCapSelectionWidget::MoCapSelectionWidget(QWidget *parent, const QMap<QString, MoCapSystem> &moCapSystems, const MoCapPersonMetadata &metadata) :
+    MoCapSelectionWidget(parent, moCapSystems)
+{
+    auto usedMoCapSystem = std::find(moCapSystems.begin(), moCapSystems.end(), metadata.getSystem());
+    if(usedMoCapSystem != moCapSystems.end()){
+        mUi->cbInputSystem->setCurrentText(usedMoCapSystem.key());
+    }
+    mUi->sampleRateSpinBox->setValue(metadata.getSamplerate());
+    mUi->offSetSpinBox->setValue(metadata.getOffset());
+    mUi->filePathLabel->setText(QString::fromStdString(metadata.getFilepath()));
+    mFilledOut = true;
+}
+
+/**
+ * @brief Let user select a MoCapFile
+ *
+ * This method opens a file dialog which enabled the user
+ * to select a file fitting to the given MoCapSystem (e.g. c3d)
+ *
+ * If a file is selected, the widget counts as filled out.
+ *
+ * This method is called by a Signal('browse File'-Button).
+ */
+void MoCapSelectionWidget::setFileName(){
+    std::stringstream extensionsString;
+    extensionsString << "All MoCap File Types (";
+    for(const auto &extension: moCapFileExtensions){
+        extensionsString << " *." << extension.second;
+    }
+    extensionsString << ")";
+    QString filename = QFileDialog::getOpenFileName(this, tr("Open C3D File"), QDir::currentPath(),
+                                                    QString::fromStdString(extensionsString.str()));
+    mUi->filePathLabel->clear();
+    mUi->filePathLabel->setText(filename);
+    mFilledOut = !filename.isEmpty();
+}
+
+/**
+ * @brief Returns contained info as Metadata-Object
+ *
+ * This method returns the values saved in this widget as
+ * a MoCapPersonMetadata-Object.
+ * @return Metadata with data from this widget
+ */
+MoCapPersonMetadata MoCapSelectionWidget::getMetadata() const
+{
+        return MoCapPersonMetadata(mUi->filePathLabel->text().toStdString(),
+                                   mMoCapSystems[mUi->cbInputSystem->currentText()],
+                                   mUi->sampleRateSpinBox->value(),
+                               mUi->offSetSpinBox->value());
+}
+
+bool MoCapSelectionWidget::isFilledOut() const
+{
+    return mFilledOut;
+}
+
+MoCapSelectionWidget::~MoCapSelectionWidget()
+{
+    delete mUi;
+}
+
+#include "moc_moCapSelectionWidget.cpp"
diff --git a/src/openMoCapDialog.cpp b/src/openMoCapDialog.cpp
index d51d66878..96e6d5a28 100644
--- a/src/openMoCapDialog.cpp
+++ b/src/openMoCapDialog.cpp
@@ -24,52 +24,32 @@
 #include "ui_openMoCapDialog.h"
 #include "moCapPersonMetadata.h"
 
+#include "moCapSelectionWidget.h"
+
 OpenMoCapDialog::OpenMoCapDialog(QWidget *parent, MoCapController &controller) :
         QDialog(parent),
         mUi(new Ui::OpenMoCapDialog),
         mController(controller),
         mParent(parent)
 {
-    constexpr int defaultSampleRate = 60;
-    constexpr double offsetRange = 5;
-
     mUi->setupUi(this);
+
+
+
     mMoCapSystems = QMap<QString, MoCapSystem>();
     setWindowFlags(windowFlags().setFlag(Qt::WindowContextHelpButtonHint, false));
     mMoCapSystems.insert("XSensC3D", MoCapSystem::XSensC3D);
-    mUi->cbInputSystem->addItems(QStringList(mMoCapSystems.keys()));
-    mUi->cbInputSystem->setCurrentIndex(0);
-    mUi->sampleRateSpinBox->setRange(1, 300);
-    mUi->sampleRateSpinBox->setValue(defaultSampleRate);
-    mUi->offSetSpinBox->setRange(-offsetRange, offsetRange);
-    mUi->offSetSpinBox->setSingleStep(0.01);
-    mUi->filePathLineEdit->setReadOnly(true);
-    mUi->pushButtonOK->setDisabled(true);
+
+    const auto loadedMetadata = mController.getAllMoCapPersonMetadata();
+    for(const auto& metadata : loadedMetadata){
+        mUi->moCapSelections->layout()->addWidget(new MoCapSelectionWidget(this, mMoCapSystems, metadata));
+    }
+
     connect(mUi->pushButtonOK, &QPushButton::clicked, this, &OpenMoCapDialog::clickedOk);
     connect(mUi->pushButtonCancel, &QPushButton::clicked, this, &OpenMoCapDialog::close);
-    connect(mUi->browseFileButton, &QPushButton::clicked, this, &OpenMoCapDialog::setFileName);
 }
 
-/**
- * @brief Opens QFileDialog and enables ok-Button if the selected filename isn't empty.
- *
- * This method is called by a Signal('browse File'-Button).
- * The selected Filename is shown(read-only) in the LineEdit-Field.
- */
 
-void OpenMoCapDialog::setFileName(){
-    std::stringstream extensionsString;
-    extensionsString << "All MoCap File Types (";
-    for(const auto &extension: moCapFileExtensions){
-        extensionsString << " *." << extension.second;
-    }
-    extensionsString << ")";
-    QString filename = QFileDialog::getOpenFileName(this, tr("Open C3D File"), QDir::currentPath(),
-                                                                 QString::fromStdString(extensionsString.str()));
-    mUi->filePathLineEdit->clear();
-    mUi->filePathLineEdit->insert(filename);
-    mUi->pushButtonOK->setDisabled(filename.isEmpty());
-}
 
 /**
  * @brief Sets FileAttributes of MoCapController and calls readMoCapFile
@@ -77,20 +57,39 @@ void OpenMoCapDialog::setFileName(){
  * This method is called by a Signal(Ok-Button) and closes the window if no errors occur.
  */
 void OpenMoCapDialog::clickedOk() {
-    QString filePath = mUi->filePathLineEdit->text();
-    int samplerate = mUi->sampleRateSpinBox->value();
-    double offset = mUi->offSetSpinBox->value();
-    MoCapSystem system = mMoCapSystems.value(mUi->cbInputSystem->currentText());
-    std::stringstream errormsg;
-    try{
-        std::vector<MoCapPersonMetadata> metadata;
-        MoCapPersonMetadata currentMetadata(filePath.toStdString(), system, samplerate, offset);
-        metadata.push_back(currentMetadata);
-        mController.readMoCapFiles(metadata);
-        this->close();
-    }catch(std::exception &e){
-        errormsg << e.what() << "\n";
-        QMessageBox::critical(mParent, "PeTrack", QString::fromStdString(errormsg.str()));
+    bool allDataIsValid = true;
+    std::vector<MoCapPersonMetadata> metadata;
+
+    for(int i = 0; i < mUi->moCapSelections->layout()->count(); ++i)
+    {
+        auto selectionWidget = dynamic_cast<const MoCapSelectionWidget*>(mUi->moCapSelections->layout()->itemAt(i)->widget());
+        if(selectionWidget == nullptr || !selectionWidget->isFilledOut())
+        {
+            continue;
+        }
+
+        try{
+            MoCapPersonMetadata currentMetadata = selectionWidget->getMetadata();
+            metadata.push_back(currentMetadata);
+        }catch(std::exception &e){
+            allDataIsValid = false;
+            std::stringstream errormsg;
+            errormsg << e.what() << "\n";
+            QMessageBox::critical(mParent, "PeTrack", QString::fromStdString(errormsg.str()));
+        }
+    }
+
+
+    if(allDataIsValid)
+    {
+        try {
+            mController.readMoCapFiles(metadata);
+            this->close();
+        }  catch (std::exception &e) {
+            std::stringstream errormsg;
+            errormsg << e.what() << "\n";
+            QMessageBox::critical(mParent, "PeTrack", QString::fromStdString(errormsg.str()));
+        }
     }
 }
 
@@ -99,3 +98,9 @@ OpenMoCapDialog::~OpenMoCapDialog()
 {
     delete mUi;
 }
+
+void OpenMoCapDialog::on_btnAddSelection_clicked()
+{
+    mUi->moCapSelections->layout()->addWidget(new MoCapSelectionWidget(this, mMoCapSystems));
+}
+
diff --git a/src/petrack.cpp b/src/petrack.cpp
index 3c82cb828..f9fffaf8f 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -52,6 +52,8 @@
 #include "pMessageBox.h"
 #include "trackingRoiItem.h"
 #include "recognitionRoiItem.h"
+#include "openMoCapDialog.h"
+
 #include "aboutDialog.h"
 
 #ifdef AVI
@@ -1445,7 +1447,7 @@ void Petrack::createActions()
     //mOpenCameraAct->setShortcut(tr("Ctrl+C")); // because of some reason it is sometimes fired with Ctrl+LeftMouseButton ==> so disabled (it's also not really needed)
     connect(mOpenCameraAct, SIGNAL(triggered()), this, SLOT(openCameraLiveStream()));
 
-    mOpenMoCapAct = new QAction(tr("Open MoCap File"), this);
+    mOpenMoCapAct = new QAction(tr("Manage MoCap Files"), this);
     connect(mOpenMoCapAct, &QAction::triggered, this, &Petrack::openMoCapFile);
 
     mSaveSeqVidAct = new QAction(tr("Save Video"), this);
diff --git a/ui/moCapSelectionWidget.ui b/ui/moCapSelectionWidget.ui
new file mode 100644
index 000000000..d12968d8b
--- /dev/null
+++ b/ui/moCapSelectionWidget.ui
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MoCapSelectionWidget</class>
+ <widget class="QWidget" name="MoCapSelectionWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>544</width>
+    <height>71</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0">
+     <item>
+      <widget class="QPushButton" name="browseFileButton">
+       <property name="text">
+        <string>Browse File</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLabel" name="filePathLabel">
+       <property name="text">
+        <string>File</string>
+       </property>
+       <property name="textInteractionFlags">
+        <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="btnDelete">
+       <property name="styleSheet">
+        <string notr="true"/>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Offset(sec):</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="offSetSpinBox"/>
+     </item>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Samplerate(Hz):</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="sampleRateSpinBox"/>
+     </item>
+     <item>
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>System:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="cbInputSystem"/>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/ui/openMoCapDialog.ui b/ui/openMoCapDialog.ui
index c1cc55a1f..30f49ef15 100644
--- a/ui/openMoCapDialog.ui
+++ b/ui/openMoCapDialog.ui
@@ -6,73 +6,100 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>258</width>
-    <height>150</height>
+    <width>529</width>
+    <height>151</height>
    </rect>
   </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
   <property name="windowTitle">
    <string>Dialog</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
-    <layout class="QGridLayout" name="gridLayout">
-     <property name="horizontalSpacing">
-      <number>6</number>
+    <widget class="QScrollArea" name="scrollArea">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
      </property>
-     <item row="1" column="0">
-      <widget class="QLabel" name="label_2">
-       <property name="text">
-        <string>Offset (seconds)</string>
-       </property>
-      </widget>
-     </item>
-     <item row="3" column="2">
-      <widget class="QLineEdit" name="filePathLineEdit"/>
-     </item>
-     <item row="4" column="2">
-      <widget class="QComboBox" name="cbInputSystem"/>
-     </item>
-     <item row="1" column="2">
-      <widget class="QDoubleSpinBox" name="offSetSpinBox"/>
-     </item>
-     <item row="4" column="0">
-      <widget class="QLabel" name="label_3">
-       <property name="text">
-        <string>Input System</string>
+     <property name="horizontalScrollBarPolicy">
+      <enum>Qt::ScrollBarAsNeeded</enum>
+     </property>
+     <property name="sizeAdjustPolicy">
+      <enum>QAbstractScrollArea::AdjustToContents</enum>
+     </property>
+     <property name="widgetResizable">
+      <bool>true</bool>
+     </property>
+     <widget class="QWidget" name="moCapSelections">
+      <property name="geometry">
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>509</width>
+        <height>69</height>
+       </rect>
+      </property>
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <property name="sizeConstraint">
+        <enum>QLayout::SetDefaultConstraint</enum>
        </property>
-      </widget>
-     </item>
-     <item row="0" column="0">
-      <widget class="QLabel" name="label">
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>0</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QPushButton" name="btnAddSelection">
        <property name="text">
-        <string>Samplerate (Hz)</string>
+        <string>+</string>
        </property>
       </widget>
      </item>
-     <item row="0" column="2">
-      <widget class="QSpinBox" name="sampleRateSpinBox"/>
-     </item>
-     <item row="5" column="0">
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
       <widget class="QPushButton" name="pushButtonCancel">
        <property name="text">
         <string>Cancel</string>
        </property>
       </widget>
      </item>
-     <item row="5" column="2">
+     <item>
       <widget class="QPushButton" name="pushButtonOK">
        <property name="text">
         <string>OK</string>
        </property>
       </widget>
      </item>
-     <item row="3" column="0">
-      <widget class="QPushButton" name="browseFileButton">
-       <property name="text">
-        <string>Browse MoCap-File</string>
-       </property>
-      </widget>
-     </item>
     </layout>
    </item>
   </layout>
-- 
GitLab