callview: add plugin

Change-Id: If4cae049167d1a1e16dc6624a202722a6316a0ff
diff --git a/src/clientwrapper.h b/src/clientwrapper.h
index d6e321a..681c35e 100644
--- a/src/clientwrapper.h
+++ b/src/clientwrapper.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2019-2020 by Savoir-faire Linux
  * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -25,9 +26,11 @@
 #include "bannedlistmodel.h"
 #include "calladapter.h"
 #include "contactadapter.h"
+#include "mediahandleradapter.h"
 #include "conversationsadapter.h"
 #include "deviceitemlistmodel.h"
 #include "pluginitemlistmodel.h"
+#include "mediahandleritemlistmodel.h"
 #include "preferenceitemlistmodel.h"
 #include "distantrenderer.h"
 #include "globalinstances.h"
diff --git a/src/mainapplication.cpp b/src/mainapplication.cpp
index 938a0eb..f53cc95 100644
--- a/src/mainapplication.cpp
+++ b/src/mainapplication.cpp
@@ -3,6 +3,7 @@
  * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
  * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
  * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -32,9 +33,11 @@
 #include "calladapter.h"
 #include "clientwrapper.h"
 #include "contactadapter.h"
+#include "mediahandleradapter.h"
 #include "conversationsadapter.h"
 #include "deviceitemlistmodel.h"
 #include "pluginitemlistmodel.h"
+#include "mediahandleritemlistmodel.h"
 #include "preferenceitemlistmodel.h"
 #include "distantrenderer.h"
 #include "globalinstances.h"
@@ -296,6 +299,7 @@
     QML_REGISTERTYPE(AccountListModel, 1, 0);
     QML_REGISTERTYPE(DeviceItemListModel, 1, 0);
     QML_REGISTERTYPE(PluginItemListModel, 1, 0);
+    QML_REGISTERTYPE(MediaHandlerItemListModel, 1, 0);
     QML_REGISTERTYPE(PreferenceItemListModel, 1, 0);
     QML_REGISTERTYPE(BannedListModel, 1, 0);
     QML_REGISTERTYPE(VideoCodecListModel, 1, 0);
@@ -330,6 +334,7 @@
     QML_REGISTERSINGLETONTYPE(ConversationsAdapter, 1, 0);
     QML_REGISTERSINGLETONTYPE(AvAdapter, 1, 0);
     QML_REGISTERSINGLETONTYPE(ContactAdapter, 1, 0);
+    QML_REGISTERSINGLETONTYPE(MediaHandlerAdapter, 1, 0);
     QML_REGISTERSINGLETONTYPE(ClientWrapper, 1, 0);
 
     //QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(AccountAdapter, 1, 0);
diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml
index 2f4eac5..75774d3 100644
--- a/src/mainview/components/CallOverlay.qml
+++ b/src/mainview/components/CallOverlay.qml
@@ -3,6 +3,7 @@
  * Copyright (C) 2020 by Savoir-faire Linux
  * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
  * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -25,6 +26,7 @@
 import net.jami.Models 1.0
 
 import "../js/contactpickercreation.js" as ContactPickerCreation
+import "../js/mediahandlerpickercreation.js" as MediaHandlerPickerCreation
 
 import "../../commoncomponents"
 
@@ -67,6 +69,10 @@
         ContactPickerCreation.closeContactPicker()
     }
 
+    function closePotentialMediaHandlerPicker() {
+        MediaHandlerPickerCreation.closeMediaHandlerPicker()
+    }
+    
     function handleParticipantsInfo(infos) {
         videoCallOverlay.updateMaster()
         var isMaster = CallAdapter.isCurrentMaster()
@@ -389,11 +395,15 @@
     onWidthChanged: {
         ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
                                                   callOverlayRect.height / 2)
+        MediaHandlerPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
+                                                  callOverlayRect.height / 2)
     }
 
     onHeightChanged: {
         ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
                                                   callOverlayRect.height / 2)
+        MediaHandlerPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
+                                                  callOverlayRect.height / 2)
     }
 
     CallViewContextMenu {
@@ -410,6 +420,14 @@
                         callOverlayRect.width / 2, callOverlayRect.height / 2)
             ContactPickerCreation.openContactPicker()
         }
+
+        onPluginItemClicked: {
+            // Create media handler picker - PLUGINS
+            MediaHandlerPickerCreation.createMediaHandlerPickerObjects(callOverlayRect)
+            MediaHandlerPickerCreation.calculateCurrentGeo(
+                        callOverlayRect.width / 2, callOverlayRect.height / 2)
+            MediaHandlerPickerCreation.openMediaHandlerPicker()
+        }
     }
 
     ParticipantContextMenu {
diff --git a/src/mainview/components/CallViewContextMenu.qml b/src/mainview/components/CallViewContextMenu.qml
index 93b008f..23da3fd 100644
--- a/src/mainview/components/CallViewContextMenu.qml
+++ b/src/mainview/components/CallViewContextMenu.qml
@@ -1,7 +1,8 @@
-/*
+/**
  * Copyright (C) 2020 by Savoir-faire Linux
  * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
  * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ * Author: Aline Gondim Santos <aline.gondimsantos@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
@@ -31,6 +32,9 @@
 
     property int generalMenuSeparatorCount: 0
     property int commonBorderWidth: 1
+
+    signal pluginItemClicked
+
     font.pointSize: JamiTheme.textFontSize+3
 
     property bool isSIP: false
@@ -267,7 +271,7 @@
         onClicked: {
             root.close()
         }
-    }
+    }*/
 
     GeneralMenuItem {
         id: pluginItem
@@ -278,9 +282,10 @@
         rightBorderWidth: commonBorderWidth
 
         onClicked: {
+            root.pluginItemClicked()
             root.close()
         }
-    }*/
+    }
 
     background: Rectangle {
         implicitWidth: startRecordingItem.preferredWidth
diff --git a/src/mainview/components/MediaHandlerItemDelegate.qml b/src/mainview/components/MediaHandlerItemDelegate.qml
new file mode 100644
index 0000000..650f024
--- /dev/null
+++ b/src/mainview/components/MediaHandlerItemDelegate.qml
@@ -0,0 +1,144 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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/>.
+ */
+
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Controls.Universal 2.12
+import QtQuick.Layouts 1.3
+import QtGraphicalEffects 1.14
+import QtQuick.Controls.Styles 1.4
+import net.jami.Models 1.0
+
+import "../../commoncomponents"
+
+ItemDelegate {
+    id: root
+
+    property string mediaHandlerName : ""
+    property string mediaHandlerId: ""
+    property string mediaHandlerIcon: ""
+    property bool isLoaded: false
+
+    signal btnLoadMediaHandlerToggled
+
+    highlighted: ListView.isCurrentItem
+
+    RowLayout{
+        anchors.fill: parent
+
+        Label{
+            Layout.leftMargin: 8
+            Layout.bottomMargin: 8
+
+            Layout.minimumWidth: 30
+            Layout.preferredWidth: 30
+            Layout.maximumWidth: 30
+
+            Layout.minimumHeight: 30
+            Layout.preferredHeight: 30
+            Layout.maximumHeight: 30
+
+            background: Rectangle{
+                anchors.fill: parent
+                Image {
+                    anchors.fill: parent
+                    source: "file:" + mediaHandlerIcon
+                }
+            }
+        }
+
+        ColumnLayout{
+            Layout.fillWidth: true
+            Layout.fillHeight: true
+
+            Layout.leftMargin: 8
+            Layout.topMargin: 8
+            Layout.bottomMargin: 8
+
+            RowLayout{
+
+                Layout.minimumHeight: 30
+
+                Label{
+                    id: labelDeviceId
+
+                    Layout.minimumHeight: 20
+
+                    font.pointSize: 10
+                    font.kerning: true
+                    text: mediaHandlerName === "" ? mediaHandlerId : mediaHandlerName
+                }
+
+                Item{
+                    Layout.fillWidth: true
+
+                    Layout.minimumWidth: 0
+                    Layout.minimumHeight: 20
+                }
+            }
+        }
+
+        Switch {
+            id: loadSwitch
+            property bool isHovering: false
+
+            Layout.bottomMargin: 8
+            Layout.rightMargin: 22
+            Layout.alignment: Qt.AlignRight
+
+            Layout.maximumWidth: 30
+            Layout.preferredWidth: 30
+            Layout.minimumWidth: 30
+
+            Layout.minimumHeight: 30
+            Layout.preferredHeight: 30
+            Layout.maximumHeight: 30
+
+            ToolTip.visible: isHovering
+            ToolTip.text: {
+                return qsTr("On/Off")
+            }
+
+            checked: isLoaded
+            onClicked: {
+                btnLoadMediaHandlerToggled()
+            }
+
+            background: Rectangle {
+                id: switchBackground
+                MouseArea {
+                    id: btnMouseArea
+                    anchors.fill: parent
+                    hoverEnabled: true
+                    onPressed: {
+                    }
+                    onReleased: {
+                        loadSwitch.clicked()
+                    }
+                    onEntered: {
+                        loadSwitch.isHovering = true
+                    }
+                    onExited: {
+                        loadSwitch.isHovering = false
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/mainview/components/MediaHandlerPicker.qml b/src/mainview/components/MediaHandlerPicker.qml
new file mode 100644
index 0000000..f6a1cc8
--- /dev/null
+++ b/src/mainview/components/MediaHandlerPicker.qml
@@ -0,0 +1,131 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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 <https://www.gnu.org/licenses/>.
+ */
+import QtQuick 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+import QtQuick.Controls.Universal 2.12
+import net.jami.Models 1.0
+
+import "../../commoncomponents"
+
+Popup {
+    id: mediahandlerPickerPopup
+
+    function toggleMediaHandlerSlot(mediaHandlerId, isLoaded) {
+        ClientWrapper.pluginModel.toggleCallMediaHandler(mediaHandlerId, !isLoaded)
+        mediahandlerPickerListView.model = MediaHandlerAdapter.getMediaHandlerSelectableModel()
+    }
+
+    contentWidth: 350
+    contentHeight: mediahandlerPickerPopupRectColumnLayout.height + 50
+
+    padding: 0
+
+    modal: true
+
+    contentItem: Rectangle {
+        id: mediahandlerPickerPopupRect
+
+        width: 250
+
+        HoverableButton {
+            id: closeButton
+
+            anchors.top: mediahandlerPickerPopupRect.top
+            anchors.topMargin: 5
+            anchors.right: mediahandlerPickerPopupRect.right
+            anchors.rightMargin: 5
+
+            width: 30
+            height: 30
+
+            radius: 30
+            source: "qrc:/images/icons/round-close-24px.svg"
+
+            onClicked: {
+                mediahandlerPickerPopup.close()
+            }
+        }
+
+        ColumnLayout {
+            id: mediahandlerPickerPopupRectColumnLayout
+
+            anchors.top: mediahandlerPickerPopupRect.top
+            anchors.topMargin: 15
+
+            Text {
+                id: mediahandlerPickerTitle
+
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: mediahandlerPickerPopupRect.width
+                Layout.preferredHeight: 30
+
+                font.pointSize: JamiTheme.textFontSize
+                font.bold: true
+
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+
+                text: qsTr("Choose plugin")
+            }
+
+            ListView {
+                id: mediahandlerPickerListView
+
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: mediahandlerPickerPopupRect.width
+                Layout.preferredHeight: 200
+
+                model: MediaHandlerAdapter.getMediaHandlerSelectableModel()
+
+                clip: true
+
+                delegate: MediaHandlerItemDelegate {
+                    id: mediaHandlerItemDelegate
+                    visible: ClientWrapper.pluginModel.getPluginsEnabled()
+                    width: mediahandlerPickerListView.width
+                    height: 50
+
+                    mediaHandlerName : MediaHandlerName
+                    mediaHandlerId: MediaHandlerId
+                    mediaHandlerIcon: MediaHandlerIcon
+                    isLoaded: IsLoaded
+
+                    onBtnLoadMediaHandlerToggled: {
+                        toggleMediaHandlerSlot(mediaHandlerId, isLoaded)
+                    }
+
+                }
+
+                ScrollIndicator.vertical: ScrollIndicator {}
+            }
+        }
+
+        radius: 10
+        color: "white"
+    }
+
+    onAboutToShow: {
+        // Reset the model on each show.
+        mediahandlerPickerListView.model = MediaHandlerAdapter.getMediaHandlerSelectableModel()
+    }
+
+    background: Rectangle {
+        color: "transparent"
+    }
+}
diff --git a/src/mainview/js/mediahandlerpickercreation.js b/src/mainview/js/mediahandlerpickercreation.js
new file mode 100644
index 0000000..1a14eca
--- /dev/null
+++ b/src/mainview/js/mediahandlerpickercreation.js
@@ -0,0 +1,72 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos <aline.gondimsantos@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 <https://www.gnu.org/licenses/>.
+ */
+
+
+/*
+ * Global mediahandler picker component, object variable for creation.
+ */
+var mediahandlerPickerComponent
+var mediahandlerPickerObject
+
+function createMediaHandlerPickerObjects(parent) {
+    if (mediahandlerPickerObject) {
+        /*
+         * If already created, reset parameters, since object cannot be destroyed.
+         */
+        mediahandlerPickerObject.parent = parent
+        return
+    }
+    mediahandlerPickerComponent = Qt.createComponent(
+                "../components/MediaHandlerPicker.qml")
+    if (mediahandlerPickerComponent.status === Component.Ready)
+        finishCreation(parent)
+    else if (mediahandlerPickerComponent.status === Component.Error)
+        console.log("Error loading component:",
+                    mediahandlerPickerComponent.errorString())
+}
+
+function finishCreation(parent) {
+    mediahandlerPickerObject = mediahandlerPickerComponent.createObject(parent)
+    if (mediahandlerPickerObject === null) {
+        /*
+         * Error Handling.
+         */
+        console.log("Error creating object for mediahandler picker")
+    }
+}
+
+
+/*
+ * Put mediahandler picker in the middle of container.
+ */
+function calculateCurrentGeo(containerX, containerY) {
+    if (mediahandlerPickerObject) {
+        mediahandlerPickerObject.x = containerX - mediahandlerPickerObject.width / 2
+        mediahandlerPickerObject.y = containerY - mediahandlerPickerObject.height / 2
+    }
+}
+
+function openMediaHandlerPicker() {
+    if (mediahandlerPickerObject)
+        mediahandlerPickerObject.open()
+}
+
+function closeMediaHandlerPicker() {
+    if (mediahandlerPickerObject)
+        mediahandlerPickerObject.close()
+}
diff --git a/src/mediahandleradapter.cpp b/src/mediahandleradapter.cpp
new file mode 100644
index 0000000..f8cb0dd
--- /dev/null
+++ b/src/mediahandleradapter.cpp
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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 "mediahandleradapter.h"
+
+#include "lrcinstance.h"
+
+MediaHandlerAdapter::MediaHandlerAdapter(QObject *parent)
+    : QmlAdapterBase(parent)
+{ }
+
+MediaHandlerAdapter::~MediaHandlerAdapter() {}
+
+QVariant
+MediaHandlerAdapter::getMediaHandlerSelectableModel()
+{
+    /*
+     * Called from qml every time contact picker refreshes.
+     */
+    mediaHandlerListModel_.reset(new MediaHandlerItemListModel(this));
+
+    return QVariant::fromValue(mediaHandlerListModel_.get());
+}
+
+
+void
+MediaHandlerAdapter::initQmlObject()
+{}
diff --git a/src/mediahandleradapter.h b/src/mediahandleradapter.h
new file mode 100644
index 0000000..6af2d13
--- /dev/null
+++ b/src/mediahandleradapter.h
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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/>.
+ */
+
+#pragma once
+
+#include "qmladapterbase.h"
+//#include "smartlistmodel.h"
+#include "mediahandleritemlistmodel.h"
+
+#include <QObject>
+#include <QSortFilterProxyModel>
+#include <QString>
+
+class MediaHandlerAdapter : public QmlAdapterBase
+{
+    Q_OBJECT
+
+public:
+    explicit MediaHandlerAdapter(QObject *parent = nullptr);
+    ~MediaHandlerAdapter();
+
+    Q_INVOKABLE QVariant getMediaHandlerSelectableModel();
+
+private:
+    void initQmlObject();
+
+    std::unique_ptr<MediaHandlerItemListModel> mediaHandlerListModel_;
+
+};
diff --git a/src/mediahandleritemlistmodel.cpp b/src/mediahandleritemlistmodel.cpp
new file mode 100644
index 0000000..648cfef
--- /dev/null
+++ b/src/mediahandleritemlistmodel.cpp
@@ -0,0 +1,128 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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 "mediahandleritemlistmodel.h"
+
+MediaHandlerItemListModel::MediaHandlerItemListModel(QObject *parent)
+    : QAbstractListModel(parent)
+{}
+
+MediaHandlerItemListModel::~MediaHandlerItemListModel() {}
+
+int
+MediaHandlerItemListModel::rowCount(const QModelIndex &parent) const
+{
+    if (!parent.isValid()) {
+        /*
+         * Count.
+         */
+        return LRCInstance::pluginModel().listCallMediaHandlers().size();
+    }
+    /*
+     * A valid QModelIndex returns 0 as no entry has sub-elements.
+     */
+    return 0;
+}
+
+int
+MediaHandlerItemListModel::columnCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    /*
+     * Only need one column.
+     */
+    return 1;
+}
+
+QVariant
+MediaHandlerItemListModel::data(const QModelIndex &index, int role) const
+{
+    auto mediahandlerList = LRCInstance::pluginModel().listCallMediaHandlers();
+    if (!index.isValid() || mediahandlerList.size() <= index.row()) {
+        return QVariant();
+    }
+
+    auto details = LRCInstance::pluginModel().getCallMediaHandlerDetails(
+        mediahandlerList.at(index.row()));
+    auto status = LRCInstance::pluginModel().getCallMediaHandlerStatus();
+    bool loaded = false;
+    if (status["name"] == details.id)
+        loaded = true;
+
+    switch (role) {
+        case Role::MediaHandlerName:
+            return QVariant(details.name);
+        case Role::MediaHandlerId:
+            return QVariant(mediahandlerList.at(index.row()));
+        case Role::MediaHandlerIcon:
+            return QVariant(details.iconPath);
+        case Role::IsLoaded:
+            return QVariant(loaded);
+    }
+    return QVariant();
+}
+
+QHash<int, QByteArray>
+MediaHandlerItemListModel::roleNames() const
+{
+    QHash<int, QByteArray> roles;
+    roles[MediaHandlerName] = "MediaHandlerName";
+    roles[MediaHandlerId] = "MediaHandlerId";
+    roles[MediaHandlerIcon] = "MediaHandlerIcon";
+    roles[IsLoaded] = "IsLoaded";
+
+    return roles;
+}
+
+QModelIndex
+MediaHandlerItemListModel::index(int row, int column, const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    if (column != 0) {
+        return QModelIndex();
+    }
+
+    if (row >= 0 && row < rowCount()) {
+        return createIndex(row, column);
+    }
+    return QModelIndex();
+}
+
+QModelIndex
+MediaHandlerItemListModel::parent(const QModelIndex &child) const
+{
+    Q_UNUSED(child);
+    return QModelIndex();
+}
+
+Qt::ItemFlags
+MediaHandlerItemListModel::flags(const QModelIndex &index) const
+{
+    auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+    if (!index.isValid()) {
+        return QAbstractItemModel::flags(index);
+    }
+    return flags;
+}
+
+void
+MediaHandlerItemListModel::reset()
+{
+    beginResetModel();
+    endResetModel();
+}
diff --git a/src/mediahandleritemlistmodel.h b/src/mediahandleritemlistmodel.h
new file mode 100644
index 0000000..ad3e43c
--- /dev/null
+++ b/src/mediahandleritemlistmodel.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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/>.
+ */
+
+#pragma once
+
+#include <QAbstractItemModel>
+
+#include "api/pluginmodel.h"
+
+#include "lrcinstance.h"
+
+class MediaHandlerItemListModel : public QAbstractListModel
+{
+    Q_OBJECT
+
+public:
+    enum Role { MediaHandlerName = Qt::UserRole + 1, MediaHandlerId, MediaHandlerIcon, IsLoaded };
+    Q_ENUM(Role)
+
+    explicit MediaHandlerItemListModel(QObject *parent = 0);
+    ~MediaHandlerItemListModel();
+
+    /*
+     * QAbstractListModel override.
+     */
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    int columnCount(const QModelIndex &parent) const override;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    /*
+     * Override role name as access point in qml.
+     */
+    QHash<int, QByteArray> roleNames() const override;
+    QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+    QModelIndex parent(const QModelIndex &child) const;
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    /*
+     * This function is to reset the model when there's new account added.
+     */
+    Q_INVOKABLE void reset();
+};
diff --git a/src/preferenceitemlistmodel.cpp b/src/preferenceitemlistmodel.cpp
index 8e90426..245ee77 100644
--- a/src/preferenceitemlistmodel.cpp
+++ b/src/preferenceitemlistmodel.cpp
@@ -1,6 +1,6 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
diff --git a/src/preferenceitemlistmodel.h b/src/preferenceitemlistmodel.h
index c51a070..4c53d74 100644
--- a/src/preferenceitemlistmodel.h
+++ b/src/preferenceitemlistmodel.h
@@ -1,6 +1,6 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -27,16 +27,16 @@
 class PreferenceItemListModel : public QAbstractListModel
 {
     Q_OBJECT
-    
+
     Q_PROPERTY(QString pluginId READ pluginId WRITE setPluginId)
 public:
     enum Role { PreferenceKey = Qt::UserRole + 1, PreferenceName, PreferenceSummary, PreferenceType, PreferenceDefaultValue, PreferenceEntries, PreferenceEntryValues};
-    
+
     typedef enum {
     LIST,
     DEFAULT,
     } Type;
-    
+
     Q_ENUM(Role)
 
     explicit PreferenceItemListModel(QObject *parent = 0);
@@ -57,7 +57,7 @@
     Qt::ItemFlags flags(const QModelIndex &index) const;
 
     /*
-     * This function is to reset the model when there's new account added.
+     * This function is to reset the model when there's new plugin added or modified.
      */
     Q_INVOKABLE void reset();
 
diff --git a/src/settingsview/components/PluginListPreferencesView.qml b/src/settingsview/components/PluginListPreferencesView.qml
index 9b8c03a..2bce002 100644
--- a/src/settingsview/components/PluginListPreferencesView.qml
+++ b/src/settingsview/components/PluginListPreferencesView.qml
@@ -1,6 +1,6 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
+/**
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -72,7 +72,7 @@
     function getSize(pluginId, show){
         size = 50 * ClientWrapper.pluginModel.getPluginPreferences(pluginId).length
         if (show) {
-            height = 200 + size            
+            height = 200 + size
             pluginPreferenceView.height = size
         } else {
             height = 25
diff --git a/src/settingsview/components/PluginSettingsPage.qml b/src/settingsview/components/PluginSettingsPage.qml
index a9d59d0..636b810 100644
--- a/src/settingsview/components/PluginSettingsPage.qml
+++ b/src/settingsview/components/PluginSettingsPage.qml
@@ -128,6 +128,7 @@
                         pluginListSettingsView.visible = checked
                         if (!checked) {
                             pluginListPreferencesView.visible = checked
+                            ClientWrapper.pluginModel.toggleCallMediaHandler("",true);
                         }
                         if (pluginListSettingsView.visible) {
                             pluginListSettingsView.updatePluginListDisplayed()
diff --git a/src/utils.cpp b/src/utils.cpp
index a397cab..1556f9d 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -4,6 +4,7 @@
  * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
  * Author: Isa Nanic <isa.nanic@savoirfairelinux.com
  * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -1080,3 +1081,10 @@
 {
     return QDir::currentPath();
 }
+
+bool
+UtilsAdapter::checkShowPluginsButton()
+{
+    return LRCInstance::pluginModel().getPluginsEnabled()
+           && (LRCInstance::pluginModel().listLoadedPlugins().size() > 0);
+}
\ No newline at end of file
diff --git a/src/utils.h b/src/utils.h
index 64db451..28f3ef0 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -4,6 +4,7 @@
  * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
  * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
  * Author: Mingrui Zhang   <mingrui.zhang@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@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
@@ -554,6 +555,8 @@
         return QString::fromLatin1(Utils::QImageToByteArray(croppedImage).toBase64().data());
     }
 
+    Q_INVOKABLE bool checkShowPluginsButton();
+
 private:
     QClipboard *clipboard_;
 };