diff --git a/recorder/obj/moc_mainwindow.cpp b/recorder/obj/moc_mainwindow.cpp
index 299f62b9624cd40b02f06e72a4ed44d78c8c7dfd..d61dda207042797b02c480b38cad425b83eb5de4 100644
--- a/recorder/obj/moc_mainwindow.cpp
+++ b/recorder/obj/moc_mainwindow.cpp
@@ -22,8 +22,8 @@ QT_BEGIN_MOC_NAMESPACE
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_DEPRECATED
 struct qt_meta_stringdata_MainWindow_t {
-    const uint offsetsAndSize[8];
-    char stringdata0[26];
+    const uint offsetsAndSize[14];
+    char stringdata0[55];
 };
 #define QT_MOC_LITERAL(ofs, len) \
     uint(offsetof(qt_meta_stringdata_MainWindow_t, stringdata0) + ofs), len 
@@ -32,10 +32,14 @@ static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
 QT_MOC_LITERAL(0, 10), // "MainWindow"
 QT_MOC_LITERAL(11, 3), // "log"
 QT_MOC_LITERAL(15, 0), // ""
-QT_MOC_LITERAL(16, 9) // "checkCams"
+QT_MOC_LITERAL(16, 10), // "VmbError_t"
+QT_MOC_LITERAL(27, 3), // "err"
+QT_MOC_LITERAL(31, 10), // "updateCams"
+QT_MOC_LITERAL(42, 12) // "opencloseCam"
 
     },
-    "MainWindow\0log\0\0checkCams"
+    "MainWindow\0log\0\0VmbError_t\0err\0"
+    "updateCams\0opencloseCam"
 };
 #undef QT_MOC_LITERAL
 
@@ -45,7 +49,7 @@ static const uint qt_meta_data_MainWindow[] = {
       10,       // revision
        0,       // classname
        0,    0, // classinfo
-       2,   14, // methods
+       4,   14, // methods
        0,    0, // properties
        0,    0, // enums/sets
        0,    0, // constructors
@@ -53,12 +57,16 @@ static const uint qt_meta_data_MainWindow[] = {
        0,       // signalCount
 
  // slots: name, argc, parameters, tag, flags, initial metatype offsets
-       1,    1,   26,    2, 0x0a,    1 /* Public */,
-       3,    0,   29,    2, 0x0a,    3 /* Public */,
+       1,    2,   38,    2, 0x0a,    1 /* Public */,
+       1,    1,   43,    2, 0x2a,    4 /* Public | MethodCloned */,
+       5,    0,   46,    2, 0x08,    6 /* Private */,
+       6,    2,   47,    2, 0x08,    7 /* Private */,
 
  // slots: parameters
+    QMetaType::Void, QMetaType::QString, 0x80000000 | 3,    2,    4,
     QMetaType::Void, QMetaType::QString,    2,
     QMetaType::Void,
+    QMetaType::Void, QMetaType::Int, QMetaType::Int,    2,    2,
 
        0        // eod
 };
@@ -69,8 +77,10 @@ void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
         auto *_t = static_cast<MainWindow *>(_o);
         (void)_t;
         switch (_id) {
-        case 0: _t->log((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1]))); break;
-        case 1: _t->checkCams(); break;
+        case 0: _t->log((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1])),(*reinterpret_cast< std::add_pointer_t<VmbError_t>>(_a[2]))); break;
+        case 1: _t->log((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1]))); break;
+        case 2: _t->updateCams(); break;
+        case 3: _t->opencloseCam((*reinterpret_cast< std::add_pointer_t<int>>(_a[1])),(*reinterpret_cast< std::add_pointer_t<int>>(_a[2]))); break;
         default: ;
         }
     }
@@ -84,7 +94,7 @@ const QMetaObject MainWindow::staticMetaObject = { {
     nullptr,
 qt_incomplete_metaTypeArray<qt_meta_stringdata_MainWindow_t
 , QtPrivate::TypeAndForceComplete<MainWindow, std::true_type>
-, QtPrivate::TypeAndForceComplete<void, std::false_type>, QtPrivate::TypeAndForceComplete<const QString &, std::false_type>, QtPrivate::TypeAndForceComplete<void, std::false_type>
+, QtPrivate::TypeAndForceComplete<void, std::false_type>, QtPrivate::TypeAndForceComplete<QString, std::false_type>, QtPrivate::TypeAndForceComplete<VmbError_t, std::false_type>, QtPrivate::TypeAndForceComplete<void, std::false_type>, QtPrivate::TypeAndForceComplete<QString, std::false_type>, QtPrivate::TypeAndForceComplete<void, std::false_type>, QtPrivate::TypeAndForceComplete<void, std::false_type>, QtPrivate::TypeAndForceComplete<int, std::false_type>, QtPrivate::TypeAndForceComplete<int, std::false_type>
 
 
 >,
@@ -111,13 +121,13 @@ int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
     if (_id < 0)
         return _id;
     if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 2)
+        if (_id < 4)
             qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
+        _id -= 4;
     } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 2)
+        if (_id < 4)
             *reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
-        _id -= 2;
+        _id -= 4;
     }
     return _id;
 }
diff --git a/recorder/recorder.sublime-project b/recorder/recorder.sublime-project
index 799a6bde348d082b366dd0ed20a7fe0f6ea2233e..c650914c5ee74bf2b67380e54037c8608e01aa03 100644
--- a/recorder/recorder.sublime-project
+++ b/recorder/recorder.sublime-project
@@ -46,6 +46,10 @@
 					"name": "rebuild",
 					"shell_cmd": "make -j8 clean && qmake6 && make -j8 -B",
 				},
+				{
+					"name": "build",
+					"shell_cmd": "qmake6 && make -j8 ",
+				},
 				{
 					"name": "run",
 					"shell_cmd": "cd ../bin && recorder",
diff --git a/recorder/src/main.cpp b/recorder/src/main.cpp
index c8807d81c3886906afae1a743ba858ee0d758c80..d28994eed404d9c62e3b4f99c68506833250499c 100644
--- a/recorder/src/main.cpp
+++ b/recorder/src/main.cpp
@@ -1,10 +1,29 @@
 #include "mainwindow.h"
+
 #include <QApplication>
+#include <QFile>
+#include <QDir>
+
+
+void loadStyleSheets(const QString& name, MainWindow& mw)
+{
+    QFile file(name);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+    {
+        mw.log( "didn't find '" + name + "' in " + QDir::currentPath() );
+    }
+    else
+    {
+        mw.log("init styles");
+        qApp->setStyleSheet( file.readAll() );
+    }
+}
 
 int main(int argc, char *argv[])
 {
     QApplication a(argc, argv);
     MainWindow w;
+    loadStyleSheets("style.qss", w);
 
     w.show();
     return a.exec();
diff --git a/recorder/src/mainwindow.cpp b/recorder/src/mainwindow.cpp
index 72d4ebe26e23712f1d625c7579287e9f79d7cbe7..dc9b11898da3840f45602b54dec61ca19b3b6604 100644
--- a/recorder/src/mainwindow.cpp
+++ b/recorder/src/mainwindow.cpp
@@ -3,7 +3,7 @@
 
 #include "../obj/ui_mainwindow.h"
 #include <QDebug>
-// #include <QPushButton>
+#include <QKeyEvent>
 
 #include <unistd.h>
 #include <iostream>
@@ -18,13 +18,15 @@ MainWindow::MainWindow(QWidget *parent)
 , cameras(CameraPtrVector())
 {
     ui->setupUi(this);
-    QObject::connect(ui->b_update, SIGNAL(clicked()), this, SLOT(checkCams()));
+    QObject::connect(ui->b_update, SIGNAL(clicked()), this, SLOT(updateCams()));
+    QObject::connect(ui->tw_cams, SIGNAL(cellClicked(int,int)), this, SLOT(openCloseCam(int,int)));
+
     log(getVersionString());
 
     if ( VmbErrorSuccess == sys.Startup() )
     {
       log( " Started Vimba C++ Api" );
-      checkCams();
+      updateCams();
   }
   else
   {
@@ -45,39 +47,66 @@ MainWindow::~MainWindow()
   delete ui;
 }
 
-// void MainWindow::open()
-// {
-//     //open 1rst cam in list
-//     if ( VmbErrorSuccess == (* iter)->Open( VmbAccessModeFull ) )
-//     {
-//         std :: cout << " Camera opened " << std :: endl;
-//     }
-// ID can be IP / MAC / ID
-//  sys->OpenCameraByID
-// }
-
-// void MainWindow::on_b_listcams_clicked()
-void MainWindow::checkCams()
+void MainWindow::keyPressEvent(QKeyEvent *e)
+{
+    //will not work on other windows (eg floating dockwidgets)
+    if ( e->key() == Qt::Key_Escape )
+    {
+        qApp->quit();
+    }
+    return QWidget::keyPressEvent(e);
+}
+
+void MainWindow::opencloseCam(int row,int col)
+{
+    log(QString("%1,%2").arg(row).arg(col));
+    auto cam = cameras.at(row);
+    auto item = ui->tw_cams->itemAt(row,col);
+    if( item->text() == "opened" )
+    {
+        //close
+        auto ret = cam->Close();
+        log( QString("Close camera %1").arg(row), ret );
+    }
+    else
+    {
+        //open
+        auto ret = cam->Open(VmbAccessModeFull);
+        log( QString("Open camera %1").arg(row), ret );
+    }
+}
+
+void MainWindow::updateCams()
 {
+
+    ui->tw_cams->clear();
+
     VmbErrorType err = sys.GetCameras( cameras );            // Fetch all cameras known to Vimba
     if( VmbErrorSuccess == err )
     {
-        std::cout << "Cameras found: " << cameras.size() <<"\n\n";
-
         // query and print all _static_ details of all known cams [without opening cams]
-        log( QString("Found %1 Cameras!").arg(cameras.size()));
+        auto ncam = cameras.size();
+        log( QString("Found %1 Camera%2!").arg(ncam).arg(ncam>1?"s":""));
         auto mf = std::bind(&MainWindow::printCamInfo, this, std::placeholders::_1); //weird syntax for calling non-static memberfunction in for_each...
+
+        ui->tw_cams->setRowCount(ncam);
         std::for_each( cameras.begin(), cameras.end(), mf );
+
+        if( cameras.size() )
+        {
+            ui->tw_cams->setCurrentCell(0,0); //XXX select row?
+        }
     }
     else
     {
-        log( QString("Could not list cameras Err: %1\n" ).arg(errorCodeToMessage(err)) );
+        log( QString("Could not list cameras."), err);
     }
 }
 
+/// get static cam info and add to listwidget
 void MainWindow::printCamInfo( const CameraPtr &camera )
 {
-    std::string strID, strName, strModelName, strSerialNumber, strInterfaceID, caminfo;
+    std::string strID, strName, strModelName, strSerialNumber, strInterfaceID, strCaminfo;
 
     VmbErrorType err = camera->GetID( strID );
     if( VmbErrorSuccess != err )
@@ -99,21 +128,27 @@ void MainWindow::printCamInfo( const CameraPtr &camera )
     if( VmbErrorSuccess != err )
         strInterfaceID =  errorCodeToMessage(err).toStdString();
 
-    caminfo = "/// Camera Name    : " + strName +
-    "\n/// Model Name     : " + strModelName +
-    "\n/// Camera ID      : " + strID +
-    "\n/// Serial Number  : " + strSerialNumber +
-    "\n/// @ Interface ID : " + strInterfaceID + "\n\n";
+    strCaminfo = \
+      "Name    : " + strName +
+    "\nModel   : " + strModelName +
+    "\nID      : " + strID +
+    "\nSerial  : " + strSerialNumber +
+    "\n@Interface : " + strInterfaceID + "\n\n";
+    QString caminfo = QString::fromStdString(strCaminfo);
 
-    log( QString::fromStdString(caminfo));
+    auto row = ui->tw_cams->rowCount()-1;
 
-    // ui->lw_cams->
+    ui->tw_cams->setItem( row, 0, new QTableWidgetItem( caminfo ) );
+    ui->tw_cams->setItem( row, 1, new QTableWidgetItem("closed") ); //XXX setIcon ??
 }
 
 
-void MainWindow::log(const QString& msg)
+void MainWindow::log(QString msg, VmbError_t err )
 {
+    msg.append(QString("%1" ).arg(errorCodeToMessage(err)));
+
     //for std::string, use: log(QString::fromStdString(msg))
-    ui->lw_log->insertItem( 0, msg );
+    auto idx = ui->lw_log->count()-1;
+    ui->lw_log->insertItem( idx , msg );
     qDebug() << msg;
 }
diff --git a/recorder/src/mainwindow.h b/recorder/src/mainwindow.h
index 0a8ed61b0bc83f3674a5fca3ed2d1a7e4cd46711..f1edef926562ab47dfd69a35abea491e555fec5c 100644
--- a/recorder/src/mainwindow.h
+++ b/recorder/src/mainwindow.h
@@ -2,16 +2,12 @@
 #define MAINWINDOW_H
 
 #include <QMainWindow>
-#include <VimbaCPP/Include/VimbaCPP.h>
-#include <VimbaCPP/Include/SharedPointerDefines.h>
-// #include <VimbaCPP/Include/Camera.h>
+#include <VimbaCPP/Include/VimbaCPP.h> //cameratptrvector (cant fwddcl typedef), vimbasys (could fwd decl)
 
 QT_BEGIN_NAMESPACE
 namespace Ui { class MainWindow; }
 QT_END_NAMESPACE
 
-namespace AVT { namespace VmbAPI { class VimbaSystem; } }
-
 
 class MainWindow : public QMainWindow
 {
@@ -22,10 +18,14 @@ public:
     ~MainWindow();
 
 public slots:
-    void log(const QString&);
+    void log(QString,VmbError_t err = VmbErrorSuccess);
+
+private slots:
+    void updateCams();
+    void opencloseCam(int,int);
 
-// private slots:
-    void checkCams();
+protected:
+    void keyPressEvent(QKeyEvent *);
 
 private:
     void printCamInfo( const AVT::VmbAPI::CameraPtr &camera );
diff --git a/recorder/src/mainwindow.ui b/recorder/src/mainwindow.ui
index 8b0ce1fe27e61ea910d73b0766a483366aa31383..150c8ec79ebc597afd1aeb27928d43598ce21ae8 100644
--- a/recorder/src/mainwindow.ui
+++ b/recorder/src/mainwindow.ui
@@ -13,7 +13,44 @@
   <property name="windowTitle">
    <string>MainWindow</string>
   </property>
-  <widget class="QWidget" name="centralwidget"/>
+  <widget class="QWidget" name="centralwidget">
+   <widget class="QTableWidget" name="tw_cams_2">
+    <property name="geometry">
+     <rect>
+      <x>50</x>
+      <y>30</y>
+      <width>311</width>
+      <height>241</height>
+     </rect>
+    </property>
+    <property name="sizeAdjustPolicy">
+     <enum>QAbstractScrollArea::AdjustToContents</enum>
+    </property>
+    <property name="rowCount">
+     <number>3</number>
+    </property>
+    <property name="columnCount">
+     <number>2</number>
+    </property>
+    <attribute name="horizontalHeaderVisible">
+     <bool>false</bool>
+    </attribute>
+    <attribute name="horizontalHeaderCascadingSectionResizes">
+     <bool>true</bool>
+    </attribute>
+    <attribute name="horizontalHeaderStretchLastSection">
+     <bool>false</bool>
+    </attribute>
+    <attribute name="verticalHeaderCascadingSectionResizes">
+     <bool>true</bool>
+    </attribute>
+    <row/>
+    <row/>
+    <row/>
+    <column/>
+    <column/>
+   </widget>
+  </widget>
   <widget class="QMenuBar" name="menubar">
    <property name="geometry">
     <rect>
@@ -51,7 +88,16 @@
       </widget>
      </item>
      <item>
-      <widget class="QListWidget" name="lw_cams"/>
+      <widget class="QTableWidget" name="tw_cams">
+       <property name="columnCount">
+        <number>2</number>
+       </property>
+       <attribute name="horizontalHeaderVisible">
+        <bool>false</bool>
+       </attribute>
+       <column/>
+       <column/>
+      </widget>
      </item>
     </layout>
    </widget>
diff --git a/recorder/src/utils.cpp b/recorder/src/utils.cpp
index 0b3bb98df62da5222ff2efb2fbebe3b5e6a83b7d..62aec564a525fb9fbcbe82522561e85f323c86ac 100644
--- a/recorder/src/utils.cpp
+++ b/recorder/src/utils.cpp
@@ -4,9 +4,10 @@
 #include "VimbaCPP/Include/VimbaCPP.h"
 #include <QString>
 
+
 const int APP_VERSION_MAJOR = 0;
 const int APP_VERSION_MINOR = 0;
-const int APP_VERSION_PATCH = 2;
+const int APP_VERSION_PATCH = 3;
 
 using namespace AVT::VmbAPI;
 
@@ -31,7 +32,7 @@ const QString errorCodeToMessage( VmbError_t err )
     switch( err )
     {
         default:                        msg += "Unknown"; break;
-        case VmbErrorSuccess:           msg += "Success."; break;
+        case VmbErrorSuccess:           msg = ""; break;
         case VmbErrorInternalFault:     msg += "Unexpected fault in VmbApi or driver."; break;
         case VmbErrorApiNotStarted:     msg += "API not started."; break;
         case VmbErrorNotFound:          msg += "Not found."; break;
@@ -53,3 +54,4 @@ const QString errorCodeToMessage( VmbError_t err )
     }
     return msg;
 }
+