diff --git a/CMakeLists.txt b/CMakeLists.txt
index d7df653c4cf5c8deb13154eaaa1df552efb201b1..a8adbab03252d28ea14a2edf67cd4ce1e4f8e2df 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@
 cmake_minimum_required( VERSION 3.1 FATAL_ERROR )
 
 # visimpl project and version
-project( visimpl VERSION 1.5.1 )
+project( visimpl VERSION 1.5.2 )
 set( visimpl_VERSION_ABI 6 )
 
 SET( VISIMPL_LICENSE "GPL")
diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp
index 4214721b734431a41ebd172c38cd0420693da959..2f10157ae8ccdf4f00c302b32be675a54202fa9e 100644
--- a/visimpl/MainWindow.cpp
+++ b/visimpl/MainWindow.cpp
@@ -857,6 +857,7 @@ namespace visimpl
     _selectionManager->setWindowModality( Qt::WindowModal );
     _selectionManager->setMinimumHeight( 300 );
     _selectionManager->setMinimumWidth( 500 );
+    _selectionManager->setWindowIcon(QIcon( ":/visimpl.png" ));
 
     connect( _selectionManager, SIGNAL( selectionChanged( void ) ), this,
              SLOT( selectionManagerChanged( void ) ) );
diff --git a/visimpl/SelectionManagerWidget.cpp b/visimpl/SelectionManagerWidget.cpp
index 9e3175e7b7f27bd853ea33524e092bbd83086cff..821dec4d2d52edf10296b4440ddf26dfc43855f8 100644
--- a/visimpl/SelectionManagerWidget.cpp
+++ b/visimpl/SelectionManagerWidget.cpp
@@ -21,16 +21,40 @@
  */
 
 // ViSimpl
-#include "SelectionManagerWidget.h"
-
-// Qt
-#include <QGridLayout>
-#include <QGroupBox>
-#include <QLabel>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QTextStream>
-#include <QShortcut>
+#include <qabstractitemmodel.h>
+#include <qabstractitemview.h>
+#include <qalgorithms.h>
+#include <qboxlayout.h>
+#include <qchar.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfiledialog.h>
+#include <qflags.h>
+#include <qgridlayout.h>
+#include <qgroupbox.h>
+#include <qicon.h>
+#include <qiodevice.h>
+#include <qitemselectionmodel.h>
+#include <qkeysequence.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlist.h>
+#include <qlistview.h>
+#include <qmessagebox.h>
+#include <qnamespace.h>
+#include <qobject.h>
+#include <qobjectdefs.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qshortcut.h>
+#include <qstandarditemmodel.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtabwidget.h>
+#include <qtextstream.h>
+#include <qvariant.h>
+#include <sumrice/types.h>
+#include <visimpl/SelectionManagerWidget.h>
 
 namespace visimpl
 {
@@ -109,16 +133,36 @@ namespace visimpl
     _listViewAvailable->setModel( _modelAvailable );
     _listViewSelected->setModel( _modelSelected );
 
-    _buttonAddToSelection = new QPushButton( "-->" );
+    _buttonAddToSelection = new QPushButton(QIcon(":/icons/right.svg"), "");
     _buttonAddToSelection->setToolTip( tr( "Add to selected GIDs" ));
 
-    _buttonRemoveFromSelection = new QPushButton( "<--" );
+    _buttonRemoveFromSelection = new QPushButton(QIcon(":/icons/left.svg"), "");
     _buttonRemoveFromSelection->setToolTip( tr( "Remove from selected GIDs" ));
 
     layoutSelection->addWidget( _listViewAvailable, 1, 0, 5, 1 );
     layoutSelection->addWidget( _buttonAddToSelection, 2, 1, 1, 1 );
     layoutSelection->addWidget( _buttonRemoveFromSelection, 4, 1, 1, 1 );
     layoutSelection->addWidget( _listViewSelected, 1, 2, 5, 1 );
+    layoutSelection->addWidget( new QLabel("Selected:"), 6,0,1,1);
+
+    QRegExp rx("[0-9 \\-\\,]+");
+    auto validator = new QRegExpValidator(rx, this);
+
+    _rangeEdit = new QLineEdit();
+    _rangeEdit->setPlaceholderText("Nothing selected");
+    _rangeEdit->setValidator(validator);
+
+    auto rangeLayout = new QHBoxLayout();
+    rangeLayout->addWidget(new QLabel("Selected:"), 0);
+    rangeLayout->addWidget(_rangeEdit, 1);
+
+    layoutSelection->addLayout(rangeLayout, 6, 0, 1, 4);
+
+    connect(_rangeEdit, SIGNAL(editingFinished()),
+            this,       SLOT(_updateRangeEdit()));
+
+    connect(_listViewAvailable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection&)),
+            this,                                 SLOT(_updateRangeEdit()));
 
     connect( _buttonAddToSelection, SIGNAL( clicked( void )),
              this, SLOT( _addToSelected( void )));
@@ -244,8 +288,10 @@ namespace visimpl
     for( auto gid : gids )
     {
       const auto text = QString::number(gid);
+      auto idx = new QStandardItem(text);
+      idx->setData(gid);
 
-      available << new QStandardItem(text);
+      available << idx;
       selected << new QStandardItem(text);
 
       _gidIndex.insert( std::make_pair( gid, index ));
@@ -279,11 +325,13 @@ namespace visimpl
   {
     _labelAvailable->setText( QString( "Available GIDs: ") + QString::number( _gidsAvailable.size( )));
     _labelSelection->setText( QString( "Selected GIDs: ") + QString::number( _gidsSelected.size( )));
+
+    _buttonRemoveFromSelection->setEnabled(!_gidsSelected.empty());
   }
 
   void SelectionManagerWidget::_addToSelected( void )
   {
-    auto selectedIndices =
+    const auto selectedIndices =
         _listViewAvailable->selectionModel( )->selectedIndexes( );
 
     if( selectedIndices.size( ) <= 0 )
@@ -294,7 +342,7 @@ namespace visimpl
       if( index.row( ) < 0 )
         continue;
 
-      auto item = _modelAvailable->itemFromIndex( index );
+      const auto item = _modelAvailable->itemFromIndex( index );
 
       bool ok;
       unsigned int gid = item->data( Qt::DisplayRole ).toUInt( &ok );
@@ -302,7 +350,7 @@ namespace visimpl
       _gidsAvailable.erase( gid );
       _gidsSelected.insert( gid );
 
-      auto gidIndex = _gidIndex.find( gid );
+      const auto gidIndex = _gidIndex.find( gid );
       assert( gidIndex != _gidIndex.end( ));
 
       _listViewAvailable->setRowHidden( gidIndex->second, true );
@@ -310,6 +358,7 @@ namespace visimpl
     }
 
     _listViewAvailable->selectionModel( )->clearSelection( );
+    _rangeEdit->clear();
 
     _updateListsLabelNumbers( );
   }
@@ -342,6 +391,120 @@ namespace visimpl
     _updateListsLabelNumbers( );
   }
 
+  void SelectionManagerWidget::_updateRangeEdit()
+  {
+    auto lEdit = qobject_cast<QLineEdit*>(sender());
+    if(lEdit)
+    {
+      const auto parts = _rangeEdit->text().split(',');
+      const auto model = _listViewAvailable->model();
+      QItemSelection selection;
+
+      auto processPart = [&model, &selection, this](const QString &s)
+      {
+        if(s.isEmpty()) return true;
+        const auto trim = s.trimmed();
+        bool ok = false;
+
+        if(trim.contains("-"))
+        {
+          const auto values = trim.split("-");
+          if(values.size() > 2) return false;
+          const auto min = values.first().trimmed().toULongLong(&ok);
+          if(!ok) return false;
+          const auto max = values.last().trimmed().toULongLong(&ok);
+          if(!ok || max < min) return false;
+          const auto minIt = _gidIndex.find(min);
+          const auto maxIt = _gidIndex.find(max);
+          if(minIt == _gidIndex.end() || maxIt == _gidIndex.end()) return false;
+
+          const auto range = QItemSelectionRange(model->index((*minIt).second, 0), model->index((*maxIt).second, 0));
+          selection.append(range);
+          return true;
+        }
+
+        // not a range
+        const auto value = trim.toULongLong(&ok);
+        if(!ok) return false;
+        const auto it = _gidIndex.find(value);
+        if(it == _gidIndex.end()) return false;
+        const auto item = model->index((*it).second, 0);
+        selection.append(QItemSelectionRange(item, item));
+        return true;
+      };
+
+      auto it = std::find_if_not(parts.cbegin(), parts.cend(), processPart);
+      if(it != parts.cend())
+      {
+        lEdit->setStyleSheet("QLineEdit { background: rgb(255, 160, 160); selection-background-color: rgb(0, 200, 200); }");
+      }
+      else
+      {
+        lEdit->setStyleSheet("");
+      }
+
+      if(!selection.isEmpty())
+      {
+        auto sModel = _listViewAvailable->selectionModel();
+        sModel->blockSignals(true);
+        sModel->select(selection, QItemSelectionModel::ClearAndSelect);
+        sModel->blockSignals(false);
+        _listViewAvailable->scrollTo(selection.last().bottomRight(), QAbstractItemView::EnsureVisible);
+        _listViewAvailable->repaint();
+      }
+    }
+    else
+    {
+      auto sModel = qobject_cast<QItemSelectionModel*>(sender());
+      if(sModel)
+      {
+        const auto selection = sModel->selection();
+        std::vector<Range> ranges;
+
+        auto processRange = [&ranges](const QItemSelectionRange &r)
+        {
+          bool ok = false;
+          const auto min = r.topLeft();
+          if(!min.isValid()) return false;
+          const auto minData = min.data(Qt::UserRole + 1);
+          if(!minData.isValid()) return false;
+          const auto minValue = minData.toULongLong(&ok);
+          if(!ok) return false;
+
+          const auto max = r.bottomRight();
+          if(!max.isValid()) return false;
+          if(min != max)
+          {
+            const auto maxData = max.data(Qt::UserRole + 1);
+            if(!maxData.isValid()) return false;
+            const auto maxValue = maxData.toULongLong(&ok);
+            if(!ok) return false;
+
+            ranges.emplace_back(minValue, maxValue);
+            return true;
+          }
+
+          ranges.emplace_back(minValue, minValue);
+          return true;
+        };
+        auto it = std::find_if_not(selection.cbegin(), selection.cend(), processRange);
+        if(it != selection.cend() || ranges.empty()) return;
+
+        ranges = mergeRanges(ranges);
+
+        _rangeEdit->setStyleSheet("");
+        _rangeEdit->blockSignals(true);
+        _rangeEdit->setText(printRanges(ranges));
+        _rangeEdit->blockSignals(false);
+        _rangeEdit->repaint();
+      }
+      else
+      {
+        std::cerr << "Unable to indentify sender! " << __FILE__ << "," << __LINE__ << std::endl;
+      }
+    }
+  }
+
   void SelectionManagerWidget::_saveToFile( const QString& filePath,
                                             const QString& separator,
                                             const QString& prefix,
@@ -353,6 +516,7 @@ namespace visimpl
       msgBox.setWindowTitle("Selection save");
       msgBox.setText( "The prefix and the suffix cannot contain the separator character." );
       msgBox.setStandardButtons( QMessageBox::Ok );
+      msgBox.setWindowIcon(QIcon(":/visimpl.png"));
       msgBox.exec( );
 
       return;
@@ -364,6 +528,7 @@ namespace visimpl
       QMessageBox msgBox( this );
       msgBox.setWindowTitle("Selection save");
       msgBox.setText( "The selected file already exists." );
+      msgBox.setWindowIcon(QIcon(":/visimpl.png"));
       msgBox.setInformativeText( "Do you want to overwrite?" );
       msgBox.setStandardButtons( QMessageBox::Save | QMessageBox::Cancel );
       msgBox.setDefaultButton( QMessageBox::Save );
@@ -429,4 +594,48 @@ namespace visimpl
     _saveToFile( _lineEditFilePath->text( ), separator,
                  _lineEditPrefix->text( ), _lineEditSuffix->text( ));
   }
+
+  SelectionManagerWidget::Ranges SelectionManagerWidget::mergeRanges(
+      SelectionManagerWidget::Ranges &r)
+  {
+    Ranges result;
+
+    auto sortRanges = [](const Range &lhs, const Range &rhs)
+    {
+      // ranges dont overlap
+      return lhs.min < rhs.min;
+    };
+    std::sort(r.begin(), r.end(), sortRanges);
+
+    // join sorted ranges
+    for(auto it = r.cbegin(); it != r.cend(); ++it)
+    {
+      if(result.empty())
+      {
+        result.emplace_back(*it);
+        continue;
+      }
+
+      if(result.back().canMerge(*it))
+      {
+        result.back() = result.back() + (*it);
+      }
+      else
+      {
+        result.emplace_back(*it);
+      }
+    }
+
+    return result;
+  }
+
+  QString SelectionManagerWidget::printRanges(const SelectionManagerWidget::Ranges &r)
+  {
+    QStringList texts;
+    auto printRange = [&texts](const Range &item){ texts << item.print(); };
+    std::for_each(r.cbegin(), r.cend(), printRange);
+
+    return texts.join(',');
+  }
+
 }
diff --git a/visimpl/SelectionManagerWidget.h b/visimpl/SelectionManagerWidget.h
index 9741647e7552d4d5ce85b371b2cb126e5f79905f..115e9c73814e0ceb16538ca654abb19cf93efe66 100644
--- a/visimpl/SelectionManagerWidget.h
+++ b/visimpl/SelectionManagerWidget.h
@@ -78,6 +78,8 @@ namespace visimpl
     void _buttonCancelClicked( void );
     void _buttonAcceptClicked( void );
 
+    void _updateRangeEdit();
+
   protected:
     void _initTabSelection( void );
     void _initTabExport( void );
@@ -110,6 +112,7 @@ namespace visimpl
 
     QLabel* _labelAvailable;
     QLabel* _labelSelection;
+    QLineEdit *_rangeEdit;
 
     TUIntUintMap _gidIndex;
 
@@ -128,6 +131,70 @@ namespace visimpl
     QPushButton* _buttonSave;
 
     QString _pathExportDefault;
+
+  private:
+    /** \struct Range
+     * \brief Minimal class to represent a range of uint64_t and its basic operations.
+     *
+     */
+    struct Range
+    {
+        unsigned long long min;
+        unsigned long long max;
+
+        /** \brief Range class constructor.
+         * \param[in] a Range minimum
+         * \param[in] b Range maximim
+         */
+        Range(unsigned long a, unsigned long b)
+        : min { a }, max { b }
+        {};
+
+        /** \brief Returns true if the given Range can be merged.
+         * \param[in] r Range reference.
+         */
+        bool canMerge(const Range &r)
+        {
+          // dont overcomplicate it, Qt returns QItemSelections without overlaps.
+          return (max + 1 == r.min) || (min - 1 == r.max);
+        };
+
+        /** \brief Modifies the range struct adding with the given one.
+         * \param[in] r Range reference.
+         */
+        Range& operator+(const Range &r)
+        {
+          if (max + 1 == r.min)
+            max = r.max;
+          else
+            min = r.min;
+
+          return *this;
+        };
+
+        /** \brief Returns a QString with the range.
+         *
+         */
+        QString print() const
+        {
+          if(min != max) return QString("%1-%2").arg(min).arg(max);
+          return QString("%1").arg(min);
+        }
+    };
+
+    using Ranges = std::vector<Range>;
+
+    /** \brief Returns the minimal vector of ranges representing the given one.
+     * \param[inout] r Vector of ranges. Returned sorted.
+     *
+     */
+    Ranges mergeRanges(Ranges &r);
+
+    /** \brief Returns a QString with the given ranges separated by commas.
+     *
+     */
+    QString printRanges(const Ranges &r);
+
   };
 }
 
diff --git a/visimpl/icons/left.svg b/visimpl/icons/left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..98f73b025281e546ce7745032e3630105cf6b8b0
--- /dev/null
+++ b/visimpl/icons/left.svg
@@ -0,0 +1,3 @@
+<svg width="48px" height="48px" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24 5L6 24L24 43L24 31L42 31V17H24V5Z" fill="#2F88FF" stroke="black" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/visimpl/icons/right.svg b/visimpl/icons/right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..035cffb1c17314a6afc425902410d1aeb3e7194b
--- /dev/null
+++ b/visimpl/icons/right.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   viewBox="0 0 48 48"
+   fill="none"
+   version="1.1"
+   id="svg4"
+   sodipodi:docname="right.svg"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="736"
+     inkscape:window-height="480"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="4.9166667"
+     inkscape:cx="24"
+     inkscape:cy="24"
+     inkscape:window-x="561"
+     inkscape:window-y="148"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg4" />
+  <path
+     d="m 24.000075,5 18,19 -18,19 V 31 H 6.0000755 V 17 H 24.000075 Z"
+     id="path2"
+     inkscape:connector-curvature="0"
+     style="fill:#2f88ff;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round" />
+</svg>
diff --git a/visimpl/resources.qrc b/visimpl/resources.qrc
index efa370bf25914c07a975b40cd6a8b841a4830ea8..950eb7a705119479dd75028f4258d9b925713415 100644
--- a/visimpl/resources.qrc
+++ b/visimpl/resources.qrc
@@ -28,6 +28,8 @@
     <file>icons/stackviz.svg</file>
     <file>icons/recorder.svg</file>
     <file>icons/toolconfig.svg</file>
+    <file>icons/left.svg</file>
+    <file>icons/right.svg</file>
     <file>visimpl.png</file>
   </qresource>
 </RCC>