conference : UI implementation

- add a button on to add people
- add a button to join call with a parent
(launched with add people button)
- reuse transferdialog to present the information for add people
- rename transferdialog to callutilsdialog
- add a method to set the current distant renderer instead of being
dependant of LRC signals
- various code clean-up

Tuleap: #29
Change-Id: I7f8875011702b586f2155e87c60f43f806494e65
diff --git a/RingWinClient.pro b/RingWinClient.pro
index 8e36a42..d5ba0af 100644
--- a/RingWinClient.pro
+++ b/RingWinClient.pro
@@ -56,8 +56,8 @@
     contactpicker.cpp \
     contactmethodpicker.cpp \
     globalsystemtray.cpp \
-    transferdialog.cpp \
-    smartlistdelegate.cpp
+    smartlistdelegate.cpp \
+    callutilsdialog.cpp
 
 HEADERS  += mainwindow.h \
     callwidget.h \
@@ -84,8 +84,8 @@
     contactmethodpicker.h \
     settingskey.h \
     globalsystemtray.h \
-    transferdialog.h \
-    smartlistdelegate.h
+    smartlistdelegate.h \
+    callutilsdialog.h
 
 FORMS    += mainwindow.ui \
     callwidget.ui \
@@ -99,7 +99,7 @@
     videooverlay.ui \
     contactpicker.ui \
     contactmethodpicker.ui \
-    transferdialog.ui
+    callutilsdialog.ui
 
 win32: LIBS += -lole32 -luuid -lshlwapi
 
diff --git a/callutilsdialog.cpp b/callutilsdialog.cpp
new file mode 100644
index 0000000..86d566b
--- /dev/null
+++ b/callutilsdialog.cpp
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * Copyright (C) 2015 by Savoir-faire Linux                                *
+ * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
+ *                                                                         *
+ * 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; either version 3 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * 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.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ **************************************************************************/
+
+#include "callutilsdialog.h"
+#include "ui_callutilsdialog.h"
+
+#include "callmodel.h"
+#include "phonedirectorymodel.h"
+#include "recentmodel.h"
+#include "contactmethod.h"
+#include "person.h"
+
+CallUtilsDialog::CallUtilsDialog(QWidget* parent) :
+    QDialog(parent),
+    ui(new Ui::CallUtilsDialog),
+    confMode_(false),
+    smartListDelegate_(nullptr),
+    notCurrentProxyModel_(nullptr)
+{
+    ui->setupUi(this);
+
+    this->setWindowFlags(Qt::CustomizeWindowHint);
+    this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
+}
+
+CallUtilsDialog::~CallUtilsDialog()
+{
+    delete smartListDelegate_;
+    delete notCurrentProxyModel_;
+    delete ui;
+}
+
+void
+CallUtilsDialog::showEvent(QShowEvent* event)
+{
+    Q_UNUSED(event)
+
+    ui->numberBar->clear();
+    if (not notCurrentProxyModel_) {
+        notCurrentProxyModel_ = new NotCurrentProxyModel(&RecentModel::instance());
+    }
+    ui->contactView->setModel(notCurrentProxyModel_);
+    if (not smartListDelegate_) {
+        smartListDelegate_ = new SmartListDelegate();
+    }
+    ui->contactView->setItemDelegate(smartListDelegate_);
+}
+
+void CallUtilsDialog::removeProxyModel()
+{
+    ui->contactView->setModel(nullptr);
+}
+
+void CallUtilsDialog::closeEvent(QCloseEvent* event)
+{
+    //This prevent a crash happening in Qt5.5 in QSortFilterProxyModel
+    Q_UNUSED(event)
+    removeProxyModel();
+}
+
+void
+CallUtilsDialog::on_transferButton_clicked()
+{
+    auto callList = CallModel::instance().getActiveCalls();
+    for (auto c : callList) {
+        if (c->state() == Call::State::CURRENT) {
+            if (not ui->numberBar->text().isEmpty()) {
+                auto number = PhoneDirectoryModel::instance().getNumber(ui->numberBar->text());
+                CallModel::instance().transfer(c, number);
+            }
+            removeProxyModel();
+            this->close();
+            return;
+        }
+    }
+}
+
+void
+CallUtilsDialog::setConfMode(bool active)
+{
+    confMode_ = active;
+    ui->transferButton->setVisible(not active);
+    ui->numberBar->setVisible(not active);
+}
+
+void
+CallUtilsDialog::on_contactView_doubleClicked(const QModelIndex& index)
+{
+    removeProxyModel();
+    if (not index.isValid())
+        return;
+    auto realIdx = notCurrentProxyModel_->mapToSource(index);
+    if (not RecentModel::instance().hasActiveCall(realIdx)) {
+        ContactMethod* m = nullptr;
+        if (auto cm = realIdx.data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>()) {
+            m = cm;
+        } else {
+            if (auto person = realIdx.data(static_cast<int>(Person::Role::Object)).value<Person*>()) {
+                m = person->phoneNumbers().first();
+            }
+        }
+        if (confMode_) {
+            if (m && !RecentModel::instance().index(0, 0, realIdx).isValid()) {
+                Call* c = CallModel::instance().dialingCall(m, CallModel::instance().selectedCall());
+                c->performAction(Call::Action::ACCEPT);
+            }
+        } else {
+            if (m) {
+                auto activeCall = CallModel::instance().selectedCall();
+                CallModel::instance().transfer(activeCall, m);
+            }
+        }
+    } else {
+        auto activeCall = CallModel::instance().selectedCall();
+        auto call = RecentModel::instance().getActiveCall(realIdx);
+        if (not confMode_)
+            CallModel::instance().attendedTransfer(activeCall, call);
+        else
+            CallModel::instance().createJoinOrMergeConferenceFromCall(activeCall, call);
+    }
+    this->close();
+}
diff --git a/transferdialog.h b/callutilsdialog.h
similarity index 70%
rename from transferdialog.h
rename to callutilsdialog.h
index a28fce0..37c9e21 100644
--- a/transferdialog.h
+++ b/callutilsdialog.h
@@ -22,15 +22,18 @@
 #include <QSortFilterProxyModel>
 
 #include "callmodel.h"
+#include "recentmodel.h"
+
+#include "smartlistdelegate.h"
 
 namespace Ui {
-class TransferDialog;
+    class CallUtilsDialog;
 }
 
-class ActiveCallsProxyModel : public QSortFilterProxyModel
+class NotCurrentProxyModel : public QSortFilterProxyModel
 {
 public:
-    ActiveCallsProxyModel(QAbstractItemModel* parent) : QSortFilterProxyModel(parent)
+    NotCurrentProxyModel(QAbstractItemModel* parent) : QSortFilterProxyModel(parent)
     {
         setSourceModel(parent);
     }
@@ -41,32 +44,34 @@
         auto idx = sourceModel()->index(source_row,0,source_parent);
         if (not idx.isValid())
             return false;
-        return idx.data(static_cast<int>(Call::Role::State))
-                .value<Call::State>() != Call::State::CURRENT;
+        auto call = RecentModel::instance().getActiveCall(idx);
+        return not call || not (call->state() == Call::State::CURRENT);
     }
 };
 
-
-class TransferDialog : public QDialog
+class CallUtilsDialog : public QDialog
 {
     Q_OBJECT
 
 public:
-    explicit TransferDialog(QWidget *parent = 0);
-    ~TransferDialog();
+    explicit CallUtilsDialog(QWidget* parent = 0);
+    ~CallUtilsDialog();
+
+    void setConfMode(bool active);
 
 //UI SLOTS
 protected slots:
-    void showEvent(QShowEvent *event);
+    void showEvent(QShowEvent* event);
+    void closeEvent(QCloseEvent* event);
 private slots:
     void on_transferButton_clicked();
-    void on_activeCallsView_doubleClicked(const QModelIndex &index);
-    void on_activeCallsView_clicked(const QModelIndex &index);
+    void on_contactView_doubleClicked(const QModelIndex& index);
 
 private:
-    Ui::TransferDialog *ui;
-    Call *selectedCall_;
-    ActiveCallsProxyModel *activeProxy_;
+    Ui::CallUtilsDialog* ui;
+    bool confMode_;
+    SmartListDelegate* smartListDelegate_;
+    NotCurrentProxyModel* notCurrentProxyModel_;
 
     void removeProxyModel();
 };
diff --git a/transferdialog.ui b/callutilsdialog.ui
similarity index 60%
rename from transferdialog.ui
rename to callutilsdialog.ui
index 7316590..f2cb59a 100644
--- a/transferdialog.ui
+++ b/callutilsdialog.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>TransferDialog</class>
- <widget class="QDialog" name="TransferDialog">
+ <class>CallUtilsDialog</class>
+ <widget class="QDialog" name="CallUtilsDialog">
   <property name="geometry">
    <rect>
     <x>0</x>
@@ -13,18 +13,23 @@
   <property name="windowTitle">
    <string>Dialog</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0" columnstretch="0,0">
-   <item row="1" column="0">
-    <widget class="QListView" name="activeCallsView"/>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>4</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>1</number>
+   </property>
+   <item>
+    <widget class="QListView" name="contactView"/>
    </item>
-   <item row="3" column="0" colspan="2">
-    <widget class="QPushButton" name="transferButton">
-     <property name="text">
-      <string>Transfer</string>
-     </property>
-    </widget>
-   </item>
-   <item row="2" column="0">
+   <item>
     <widget class="QLineEdit" name="numberBar">
      <property name="placeholderText">
       <string>or type number...</string>
@@ -34,10 +39,10 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="0">
-    <widget class="QLabel" name="label">
+   <item>
+    <widget class="QPushButton" name="transferButton">
      <property name="text">
-      <string>Current Calls</string>
+      <string>Transfer</string>
      </property>
     </widget>
    </item>
diff --git a/callwidget.cpp b/callwidget.cpp
index 1e3b5f9..d018bd7 100644
--- a/callwidget.cpp
+++ b/callwidget.cpp
@@ -150,8 +150,8 @@
 
         findRingAccount();
 
-    } catch (...) {
-        qDebug() << "INIT ERROR";
+    } catch (const std::exception& e) {
+        qDebug() << "INIT ERROR" << e.what();
     }
 }
 
@@ -270,9 +270,6 @@
     if (call == nullptr)
         return;
 
-    //Force update of smartList
-    ui->smartList->setFocus();
-
     if (call->state() == Call::State::OVER
             || call->state() == Call::State::ERROR
             || call->state() == Call::State::FAILURE
@@ -349,8 +346,8 @@
 CallWidget::setActualCall(Call* value)
 {
     actualCall_ = value;
-    if (value)
-        CallModel::instance().selectCall(value);
+    CallModel::instance().selectCall(value);
+    ui->videoWidget->pushRenderer(value);
 }
 
 void
@@ -395,18 +392,14 @@
     Q_UNUSED(oldSel)
 
     auto newIdx = newSel.indexes().first();
-    if (newIdx.parent().isValid())
+    if (not newIdx.isValid())
         return;
 
     auto newIdxCall = RecentModel::instance().getActiveCall(RecentModel::instance().peopleProxy()->mapToSource(newIdx));
 
     if (newIdxCall == actualCall_)
         return;
-    if (actualCall_ != nullptr) {
-        actualCall_->performAction(Call::Action::HOLD);
-    }
     if (newIdxCall) {
-        newIdxCall->performAction(Call::Action::HOLD);
         setActualCall(newIdxCall);
         ui->stackedWidget->setCurrentWidget(ui->videoPage);
     } else {
diff --git a/transferdialog.cpp b/transferdialog.cpp
deleted file mode 100644
index 90e204c..0000000
--- a/transferdialog.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Savoir-faire Linux                                *
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
- *                                                                         *
- * 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; either version 3 of the License, or       *
- * (at your option) any later version.                                     *
- *                                                                         *
- * 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.                            *
- *                                                                         *
- * You should have received a copy of the GNU General Public License       *
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- **************************************************************************/
-
-#include "transferdialog.h"
-#include "ui_transferdialog.h"
-
-#include "callmodel.h"
-#include "phonedirectorymodel.h"
-
-TransferDialog::TransferDialog(QWidget *parent) :
-    QDialog(parent),
-    ui(new Ui::TransferDialog),
-    activeProxy_(nullptr)
-{
-    ui->setupUi(this);
-
-    this->setWindowFlags(Qt::CustomizeWindowHint);
-    this->setWindowFlags(Qt::FramelessWindowHint);
-}
-
-TransferDialog::~TransferDialog()
-{
-    delete ui;
-}
-
-void
-TransferDialog::showEvent(QShowEvent *event)
-{
-    Q_UNUSED(event)
-
-    ui->numberBar->clear();
-    selectedCall_ = nullptr;
-    if (not activeProxy_) {
-        activeProxy_ = new ActiveCallsProxyModel(&CallModel::instance());
-        activeProxy_->setDynamicSortFilter(false);
-    }
-    ui->activeCallsView->setModel(activeProxy_);
-    ui->activeCallsView->clearSelection();
-}
-
-void
-TransferDialog::on_transferButton_clicked()
-{
-    removeProxyModel();
-
-    auto callList = CallModel::instance().getActiveCalls();
-    for (auto c : callList) {
-        if (c->state() == Call::State::CURRENT) {
-            if (not ui->numberBar->text().isEmpty()) {
-                auto number = PhoneDirectoryModel::instance().getNumber(ui->numberBar->text());
-                CallModel::instance().transfer(c, number);
-            } else if (selectedCall_) {
-                CallModel::instance().attendedTransfer(c, selectedCall_);
-            }
-            this->close();
-            return;
-        }
-    }
-}
-
-void
-TransferDialog::removeProxyModel()
-{
-    //This prevent a crash happening in Qt5.5 in QSortFilterProxyModel
-    ui->activeCallsView->setModel(nullptr);
-}
-
-void
-TransferDialog::on_activeCallsView_doubleClicked(const QModelIndex &index)
-{
-    Q_UNUSED(index)
-
-    removeProxyModel();
-
-    auto callList = CallModel::instance().getActiveCalls();
-    for (auto c : callList) {
-        if (c->state() == Call::State::CURRENT) {
-            if (c != selectedCall_) {
-                CallModel::instance().attendedTransfer(c, selectedCall_);
-                this->close();
-                return;
-            }
-        }
-    }
-}
-
-void
-TransferDialog::on_activeCallsView_clicked(const QModelIndex &index)
-{
-    selectedCall_ = CallModel::instance().getCall(index);
-}
diff --git a/videooverlay.cpp b/videooverlay.cpp
index cbe728c..0028307 100644
--- a/videooverlay.cpp
+++ b/videooverlay.cpp
@@ -21,15 +21,14 @@
 
 #include "callmodel.h"
 
-VideoOverlay::VideoOverlay(QWidget *parent) :
+VideoOverlay::VideoOverlay(QWidget* parent) :
     QWidget(parent),
     ui(new Ui::VideoOverlay),
-    transferDialog_(new TransferDialog())
+    transferDialog_(new CallUtilsDialog())
 {
     ui->setupUi(this);
 
     ui->chatButton->setCheckable(true);
-    ui->transferButton->setCheckable(true);
 
     actionModel_ = CallModel::instance().userActionModel();
     setAttribute(Qt::WA_NoSystemBackground);
@@ -62,6 +61,10 @@
                 muteVideo->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
                 muteVideo->setEnabled(idx.flags() & Qt::ItemIsEnabled);
                 break;
+            case UserActionModel::Action::HOLD:
+                ui->holdButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>());
+                ui->holdButton->setEnabled(idx.flags() & Qt::ItemIsEnabled);
+                break;
             default:
                 break;
             }
@@ -69,6 +72,30 @@
     });
 
     ui->moreButton->setMenu(menu_);
+
+    connect(CallModel::instance().selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex &current, const QModelIndex &previous) {
+        Q_UNUSED(previous)
+        Call* c = current.data(static_cast<int>(Call::Role::Object)).value<Call*>();
+        if (c) {
+            if (c->hasParentCall()) {
+                ui->holdButton->hide();
+                ui->moreButton->hide();
+                ui->transferButton->hide();
+                ui->addPersonButton->hide();
+                ui->chatButton->hide();
+
+                ui->joinButton->show();
+            } else {
+                ui->holdButton->show();
+                ui->moreButton->show();
+                ui->transferButton->show();
+                ui->addPersonButton->show();
+                ui->chatButton->show();
+
+                ui->joinButton->hide();
+            }
+        }
+    });
 }
 
 VideoOverlay::~VideoOverlay()
@@ -91,13 +118,6 @@
 }
 
 void
-VideoOverlay::on_holdButton_toggled(bool checked)
-{
-    Q_UNUSED(checked)
-    actionModel_->execute(UserActionModel::Action::HOLD);
-}
-
-void
 VideoOverlay::on_hangupButton_clicked()
 {
     actionModel_->execute(UserActionModel::Action::HANGUP);
@@ -111,9 +131,36 @@
 }
 
 void
-VideoOverlay::on_transferButton_toggled(bool checked)
+VideoOverlay::on_transferButton_clicked()
 {
+    transferDialog_->setConfMode(false);
     auto pos = this->mapToGlobal(ui->transferButton->pos());
-    transferDialog_->move(pos.x() + ui->transferButton->width(), pos.y() - (transferDialog_->height()/2));
-    checked ? transferDialog_->show() : transferDialog_->hide();
+    transferDialog_->move(pos.x()
+                          - transferDialog_->size().width()/2
+                          + ui->transferButton->size().width()/2,
+                          pos.y() - (transferDialog_->height()));
+    transferDialog_->show();
+}
+
+void
+VideoOverlay::on_addPersonButton_clicked()
+{
+    transferDialog_->setConfMode(true);
+    auto pos = this->mapToGlobal(ui->addPersonButton->pos());
+    transferDialog_->move(pos.x()
+                          - transferDialog_->size().width()/2
+                          + ui->addPersonButton->size().width()/2,
+                          pos.y() - (transferDialog_->height()));
+    transferDialog_->show();
+}
+
+void
+VideoOverlay::on_holdButton_clicked()
+{
+    actionModel_->execute(UserActionModel::Action::HOLD);
+}
+
+void VideoOverlay::on_joinButton_clicked()
+{
+    CallModel::instance().selectedCall()->joinToParent();
 }
diff --git a/videooverlay.h b/videooverlay.h
index 2037876..7d821bc 100644
--- a/videooverlay.h
+++ b/videooverlay.h
@@ -23,7 +23,7 @@
 
 #include "useractionmodel.h"
 
-#include "transferdialog.h"
+#include "callutilsdialog.h"
 
 namespace Ui {
 class VideoOverlay;
@@ -34,25 +34,27 @@
     Q_OBJECT
 
 public:
-    explicit VideoOverlay(QWidget *parent = 0);
+    explicit VideoOverlay(QWidget* parent = 0);
     ~VideoOverlay();
 
 public:
-    void setName(const QString &name);
-    void setTime(const QString &time);
+    void setName(const QString& name);
+    void setTime(const QString& time);
 
 //UI SLOTS
 private slots:
-    void on_holdButton_toggled(bool checked);
     void on_hangupButton_clicked();
     void on_chatButton_toggled(bool checked);
-    void on_transferButton_toggled(bool checked);
+    void on_transferButton_clicked();
+    void on_addPersonButton_clicked();
+    void on_holdButton_clicked();
+    void on_joinButton_clicked();
 
 private:
-    Ui::VideoOverlay *ui;
+    Ui::VideoOverlay* ui;
     UserActionModel* actionModel_;
     QMenu* menu_;
-    TransferDialog *transferDialog_;
+    CallUtilsDialog* transferDialog_;
 
 signals:
     void setChatVisibility(bool visible);
diff --git a/videooverlay.ui b/videooverlay.ui
index 7d38ac9..27674f5 100644
--- a/videooverlay.ui
+++ b/videooverlay.ui
@@ -23,34 +23,7 @@
    <string/>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="1" column="2">
-    <widget class="QPushButton" name="hangupButton">
-     <property name="text">
-      <string>Hangup</string>
-     </property>
-    </widget>
-   </item>
-   <item row="1" column="5">
-    <widget class="QPushButton" name="moreButton">
-     <property name="text">
-      <string>...</string>
-     </property>
-    </widget>
-   </item>
-   <item row="1" column="0">
-    <spacer name="horizontalSpacer">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>40</width>
-       <height>20</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
-   <item row="1" column="6">
+   <item row="1" column="8">
     <spacer name="horizontalSpacer_2">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
@@ -63,6 +36,71 @@
      </property>
     </spacer>
    </item>
+   <item row="1" column="2">
+    <widget class="QPushButton" name="hangupButton">
+     <property name="text">
+      <string>Hangup</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="8" alignment="Qt::AlignRight|Qt::AlignTop">
+    <widget class="QLabel" name="timerLabel">
+     <property name="palette">
+      <palette>
+       <active>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </active>
+       <inactive>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>255</red>
+           <green>255</green>
+           <blue>255</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </inactive>
+       <disabled>
+        <colorrole role="WindowText">
+         <brush brushstyle="SolidPattern">
+          <color alpha="255">
+           <red>143</red>
+           <green>146</green>
+           <blue>147</blue>
+          </color>
+         </brush>
+        </colorrole>
+       </disabled>
+      </palette>
+     </property>
+     <property name="text">
+      <string>00:00</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="4">
+    <widget class="QPushButton" name="addPersonButton">
+     <property name="text">
+      <string>Add People</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="7">
+    <widget class="QPushButton" name="moreButton">
+     <property name="text">
+      <string>...</string>
+     </property>
+    </widget>
+   </item>
    <item row="0" column="0" alignment="Qt::AlignTop">
     <widget class="QLabel" name="nameLabel">
      <property name="palette">
@@ -107,50 +145,26 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="6" alignment="Qt::AlignRight|Qt::AlignTop">
-    <widget class="QLabel" name="timerLabel">
-     <property name="palette">
-      <palette>
-       <active>
-        <colorrole role="WindowText">
-         <brush brushstyle="SolidPattern">
-          <color alpha="255">
-           <red>255</red>
-           <green>255</green>
-           <blue>255</blue>
-          </color>
-         </brush>
-        </colorrole>
-       </active>
-       <inactive>
-        <colorrole role="WindowText">
-         <brush brushstyle="SolidPattern">
-          <color alpha="255">
-           <red>255</red>
-           <green>255</green>
-           <blue>255</blue>
-          </color>
-         </brush>
-        </colorrole>
-       </inactive>
-       <disabled>
-        <colorrole role="WindowText">
-         <brush brushstyle="SolidPattern">
-          <color alpha="255">
-           <red>143</red>
-           <green>146</green>
-           <blue>147</blue>
-          </color>
-         </brush>
-        </colorrole>
-       </disabled>
-      </palette>
-     </property>
+   <item row="1" column="3">
+    <widget class="QPushButton" name="chatButton">
      <property name="text">
-      <string>00:00</string>
+      <string>Chat</string>
      </property>
     </widget>
    </item>
+   <item row="1" column="0">
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
    <item row="1" column="1">
     <widget class="QPushButton" name="holdButton">
      <property name="text">
@@ -161,20 +175,20 @@
      </property>
     </widget>
    </item>
-   <item row="1" column="3">
-    <widget class="QPushButton" name="chatButton">
-     <property name="text">
-      <string>Chat</string>
-     </property>
-    </widget>
-   </item>
-   <item row="1" column="4">
+   <item row="1" column="6">
     <widget class="QPushButton" name="transferButton">
      <property name="text">
       <string>Transfer</string>
      </property>
     </widget>
    </item>
+   <item row="1" column="5">
+    <widget class="QPushButton" name="joinButton">
+     <property name="text">
+      <string>Join</string>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
  <resources/>
diff --git a/videoview.cpp b/videoview.cpp
index 4157d7a..c0e1816 100644
--- a/videoview.cpp
+++ b/videoview.cpp
@@ -35,7 +35,7 @@
 #include "videooverlay.h"
 #include "selectareadialog.h"
 
-VideoView::VideoView(QWidget *parent) :
+VideoView::VideoView(QWidget* parent) :
     QWidget(parent),
     ui(new Ui::VideoView)
 {
@@ -72,7 +72,7 @@
 }
 
 void
-VideoView::resizeEvent(QResizeEvent *event)
+VideoView::resizeEvent(QResizeEvent* event)
 {
     Q_UNUSED(event)
     overlay_->resize(this->size());
@@ -99,24 +99,26 @@
 VideoView::callStateChanged(Call* call, Call::State previousState)
 {
    Q_UNUSED(previousState)
+
     if (call->state() == Call::State::CURRENT) {
         ui->videoWidget->show();
         timerConnection_ = connect(call, SIGNAL(changed()), this, SLOT(updateCall()));
     }
     else {
+        QObject::disconnect(timerConnection_);
         emit setChatVisibility(false);
         if (isFullScreen())
             toggleFullScreen();
-        QObject::disconnect(timerConnection_);
     }
 }
 
 void
 VideoView::updateCall()
 {
-    auto call = CallModel::instance().selectedCall();
-    overlay_->setName(call->formattedName());
-    overlay_->setTime(call->length());
+    if (auto call = CallModel::instance().selectedCall()) {
+        overlay_->setName(call->formattedName());
+        overlay_->setTime(call->length());
+    }
 }
 
 void
@@ -125,13 +127,15 @@
     toggleFullScreen();
 }
 
-void VideoView::dragEnterEvent(QDragEnterEvent *event)
+void
+VideoView::dragEnterEvent(QDragEnterEvent* event)
 {
     if (event->mimeData()->hasUrls())
         event->acceptProposedAction();
 }
 
-void VideoView::dropEvent(QDropEvent *event)
+void
+VideoView::dropEvent(QDropEvent* event)
 {
     auto urls = event->mimeData()->urls();
     Video::SourceModel::instance().setFile(urls.at(0));
@@ -204,3 +208,27 @@
     menu.exec(globalPos);
 }
 
+void
+VideoView::pushRenderer(Call* call) {
+    if (not call) {
+        disconnect(videoStartedConnection_);
+        return;
+    }
+    if (auto renderer = call->videoRenderer()) {
+        slotVideoStarted(renderer);
+    } else {
+        disconnect(videoStartedConnection_);
+        videoStartedConnection_ = connect(call,
+                SIGNAL(videoStarted(Video::Renderer*)),
+                this,
+                SLOT(slotVideoStarted(Video::Renderer*)));
+    }
+    ui->videoWidget->setPreviewDisplay(call->type() != Call::Type::CONFERENCE);
+}
+
+void
+VideoView::slotVideoStarted(Video::Renderer* renderer) {
+    ui->videoWidget->show();
+    ui->videoWidget->setDistantRenderer(renderer);
+}
+
diff --git a/videoview.h b/videoview.h
index 4e535ef..bcf95c1 100644
--- a/videoview.h
+++ b/videoview.h
@@ -34,30 +34,33 @@
     Q_OBJECT
 
 public:
-    explicit VideoView(QWidget *parent = 0);
+    explicit VideoView(QWidget* parent = 0);
     ~VideoView();
+    void pushRenderer(Call* call);
 
 protected:
     void resizeEvent(QResizeEvent* event);
     void enterEvent(QEvent* event);
     void leaveEvent(QEvent* event);
-    void mouseDoubleClickEvent(QMouseEvent *e);
-    void dragEnterEvent(QDragEnterEvent *event);
-    void dropEvent(QDropEvent *event);
+    void mouseDoubleClickEvent(QMouseEvent* e);
+    void dragEnterEvent(QDragEnterEvent* event);
+    void dropEvent(QDropEvent* event);
 
 private slots:
-    void callStateChanged(Call *call, Call::State previousState);
+    void callStateChanged(Call* call, Call::State previousState);
     void updateCall();
-    void showContextMenu(const QPoint &pos);
+    void showContextMenu(const QPoint& pos);
+    void slotVideoStarted(Video::Renderer* renderer);
 
 private:
-    Ui::VideoView *ui;
+    Ui::VideoView* ui;
     VideoOverlay* overlay_;
     constexpr static int fadeOverlayTime_ = 2000; //msec
     QPropertyAnimation* fadeAnim_;
-    QWidget *oldParent_;
+    QWidget* oldParent_;
     QSize oldSize_;
     QMetaObject::Connection timerConnection_;
+    QMetaObject::Connection videoStartedConnection_;
 private:
     void toggleFullScreen();
 signals:
diff --git a/videowidget.cpp b/videowidget.cpp
index c12c100..5bc7023 100644
--- a/videowidget.cpp
+++ b/videowidget.cpp
@@ -18,18 +18,15 @@
 
 #include "videowidget.h"
 
-VideoWidget::VideoWidget(QWidget *parent) :
+VideoWidget::VideoWidget(QWidget* parent) :
     QWidget(parent)
   , previewRenderer_(nullptr)
   , renderer_(nullptr)
+  , isPreviewDisplayed_(true)
 {
     connect(&Video::PreviewManager::instance(),
             SIGNAL(previewStarted(Video::Renderer*)),
             this, SLOT(previewStarted(Video::Renderer*)));
-    connect(&CallModel::instance(),
-            SIGNAL(rendererAdded(Call*,Video::Renderer*)),
-            this, SLOT(callInitiated(Call*, Video::Renderer*)),
-            Qt::ConnectionType::DirectConnection);
 
     QPalette pal(palette());
     pal.setColor(QPalette::Background, Qt::black);
@@ -41,10 +38,12 @@
 {}
 
 void
-VideoWidget::previewStarted(Video::Renderer *renderer) {
+VideoWidget::previewStarted(Video::Renderer* renderer) {
     //Enforce that only one videowidget we'll be used at the same time
     if (not isVisible())
         return;
+    if (previewRenderer_ == renderer)
+        return;
     previewRenderer_ = renderer;
     connect(previewRenderer_, SIGNAL(frameUpdated()),
             this, SLOT(frameFromPreview()));
@@ -57,7 +56,7 @@
     disconnect(previewRenderer_, SIGNAL(frameUpdated()),
                this, SLOT(frameFromPreview()));
     disconnect(previewRenderer_, SIGNAL(stopped()),
-               this, SLOT(renderingStopped()));
+               this, SLOT(previewStopped()));
     previewRenderer_ = nullptr;
 }
 
@@ -75,7 +74,7 @@
 }
 
 void
-VideoWidget::paintEvent(QPaintEvent *evt) {
+VideoWidget::paintEvent(QPaintEvent* evt) {
     Q_UNUSED(evt)
     QPainter painter(this);
 
@@ -99,7 +98,7 @@
             painter.drawImage(QRect(xDiff,yDiff,scaledDistant.width(),scaledDistant.height()), scaledDistant);
         }
     }
-    if (previewRenderer_) {
+    if (previewRenderer_ && isPreviewDisplayed_) {
         {
             QMutexLocker lock(&mutex_);
             if (currentPreviewFrame_.storage.size() != 0
@@ -129,15 +128,15 @@
 }
 
 void
-VideoWidget::callInitiated(Call* call, Video::Renderer *renderer) {
-    Q_UNUSED(call)
-    //Enforce that only one videowidget we'll be used at the same time
-    if (not isVisible())
+VideoWidget::setDistantRenderer(Video::Renderer* renderer) {
+    if (not renderer)
         return;
-    renderer_ = renderer;
-    connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
-    connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()),
-            Qt::ConnectionType::DirectConnection);
+    if (renderer_ != renderer) {
+        renderingStopped();
+        renderer_ = renderer;
+        connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
+        connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()));
+    }
 }
 
 void
@@ -148,7 +147,6 @@
             auto tmp  = renderer_->currentFrame();
             if (tmp.storage.size())
                 currentDistantFrame_ = tmp;
-
         }
         update();
     }
@@ -156,7 +154,14 @@
 
 void
 VideoWidget::renderingStopped() {
+    if (not renderer_)
+        return;
     disconnect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
     disconnect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()));
     renderer_ = nullptr;
 }
+
+void
+VideoWidget::setPreviewDisplay(bool display) {
+    isPreviewDisplayed_ = display;
+}
diff --git a/videowidget.h b/videowidget.h
index aa39d47..83ac5ac 100644
--- a/videowidget.h
+++ b/videowidget.h
@@ -31,15 +31,16 @@
 {
     Q_OBJECT
 public:
-    explicit VideoWidget(QWidget *parent = 0);
+    explicit VideoWidget(QWidget* parent = 0);
     ~VideoWidget();
     void paintEvent(QPaintEvent* evt);
+    void setPreviewDisplay(bool display);
+    void setDistantRenderer(Video::Renderer* renderer);
 
 public slots:
     void previewStarted(Video::Renderer* renderer);
     void previewStopped();
     void frameFromPreview();
-    void callInitiated(Call *call, Video::Renderer *renderer);
     void frameFromDistant();
     void renderingStopped();
 
@@ -53,6 +54,7 @@
     std::unique_ptr<QImage> previewImage_;
     std::vector<uint8_t> frameDistant_;
     std::vector<uint8_t> framePreview_;
+    bool isPreviewDisplayed_;
 
     constexpr static int previewMargin_ = 15;
 };