callview: add plugin

Change-Id: If4cae049167d1a1e16dc6624a202722a6316a0ff
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()
+}