1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-30 11:43:36 +02:00

plugins: add ChatHandler API

Change-Id: I415fc953b9111ca7e3d899c1531a42bd43716ab2
This commit is contained in:
agsantos 2021-01-22 11:53:08 -05:00
parent 4a06565e57
commit a5ec0c8e65
26 changed files with 717 additions and 522 deletions

View file

@ -66,7 +66,7 @@ set(COMMON_SOURCES
${SRC_DIR}/settingsadapter.cpp
${SRC_DIR}/deviceitemlistmodel.cpp
${SRC_DIR}/pluginitemlistmodel.cpp
${SRC_DIR}/mediahandleritemlistmodel.cpp
${SRC_DIR}/pluginhandleritemlistmodel.cpp
${SRC_DIR}/preferenceitemlistmodel.cpp
${SRC_DIR}/mediacodeclistmodel.cpp
${SRC_DIR}/accountstomigratelistmodel.cpp
@ -115,7 +115,7 @@ set(COMMON_HEADERS
${SRC_DIR}/settingsadapter.h
${SRC_DIR}/deviceitemlistmodel.h
${SRC_DIR}/pluginitemlistmodel.h
${SRC_DIR}/mediahandleritemlistmodel.h
${SRC_DIR}/pluginhandleritemlistmodel.h
${SRC_DIR}/preferenceitemlistmodel.h
${SRC_DIR}/mediacodeclistmodel.h
${SRC_DIR}/accountstomigratelistmodel.h

View file

@ -170,7 +170,7 @@ HEADERS += \
src/settingsadapter.h \
src/deviceitemlistmodel.h \
src/pluginitemlistmodel.h \
src/mediahandleritemlistmodel.h \
src/pluginhandleritemlistmodel.h \
src/preferenceitemlistmodel.h \
src/mediacodeclistmodel.h \
src/accountstomigratelistmodel.h \
@ -211,7 +211,7 @@ SOURCES += \
src/settingsadapter.cpp \
src/deviceitemlistmodel.cpp \
src/pluginitemlistmodel.cpp \
src/mediahandleritemlistmodel.cpp \
src/pluginhandleritemlistmodel.cpp \
src/preferenceitemlistmodel.cpp \
src/mediacodeclistmodel.cpp \
src/accountstomigratelistmodel.cpp \

View file

@ -45,7 +45,7 @@
<file>src/commoncomponents/SettingParaCombobox.qml</file>
<file>src/settingsview/components/DeviceItemDelegate.qml</file>
<file>src/settingsview/components/PluginItemDelegate.qml</file>
<file>src/mainview/components/MediaHandlerItemDelegate.qml</file>
<file>src/mainview/components/PluginHandlerItemDelegate.qml</file>
<file>src/commoncomponents/PreferenceItemDelegate.qml</file>
<file>src/settingsview/components/ContactItemDelegate.qml</file>
<file>src/settingsview/components/MediaCodecDelegate.qml</file>
@ -112,9 +112,9 @@
<file>src/mainview/js/callfullscreenwindowcontainercreation.js</file>
<file>src/mainview/components/VideoCallFullScreenWindowContainer.qml</file>
<file>src/mainview/components/ContactPicker.qml</file>
<file>src/mainview/components/MediaHandlerPicker.qml</file>
<file>src/mainview/components/PluginHandlerPicker.qml</file>
<file>src/mainview/js/contactpickercreation.js</file>
<file>src/mainview/js/mediahandlerpickercreation.js</file>
<file>src/mainview/js/pluginhandlerpickercreation.js</file>
<file>src/mainview/components/ContactPickerItemDelegate.qml</file>
<file>src/commoncomponents/AccountMigrationDialog.qml</file>
<file>src/commoncomponents/MaterialButton.qml</file>

View file

@ -170,6 +170,8 @@ Item {
property int preferredDialogWidth: 400
property int preferredDialogHeight: 300
property int minimumPreviewWidth: 120
property int pluginHandlersPopupViewHeight: 200
property int pluginHandlersPopupViewDelegateHeight: 50
// main application spec
property int mainViewMinWidth: 460

View file

@ -28,7 +28,7 @@ import net.jami.Adapters 1.0
import net.jami.Constants 1.0
import "../js/contactpickercreation.js" as ContactPickerCreation
import "../js/mediahandlerpickercreation.js" as MediaHandlerPickerCreation
import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation
import "../../commoncomponents"
@ -73,8 +73,8 @@ Rectangle {
ContactPickerCreation.closeContactPicker()
}
function closePotentialMediaHandlerPicker() {
MediaHandlerPickerCreation.closeMediaHandlerPicker()
function closePotentialPluginHandlerPicker() {
PluginHandlerPickerCreation.closePluginHandlerPicker()
}
// returns true if participant is not fully maximized
@ -561,9 +561,9 @@ Rectangle {
}
onPluginItemClicked: {
// Create media handler picker - PLUGINS
MediaHandlerPickerCreation.createMediaHandlerPickerObjects(callOverlayRect)
MediaHandlerPickerCreation.openMediaHandlerPicker()
// Create plugin handler picker - PLUGINS
PluginHandlerPickerCreation.createPluginHandlerPickerObjects(callOverlayRect, true)
PluginHandlerPickerCreation.openPluginHandlerPicker()
}
}
}

View file

@ -131,7 +131,7 @@ Item {
})
}
if (UtilsAdapter.checkShowPluginsButton()) {
if (UtilsAdapter.checkShowPluginsButton(true)) {
ContextMenuGenerator.addMenuItem(JamiStrings.viewPlugin,
"qrc:/images/icons/extension_24dp.svg",
function (){

View file

@ -1,259 +0,0 @@
/*
* 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.14
import net.jami.Models 1.0
import net.jami.Adapters 1.0
import net.jami.Constants 1.0
import "../../commoncomponents"
Popup {
id: root
function toggleMediaHandlerSlot(mediaHandlerId, isLoaded) {
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
PluginModel.toggleCallMediaHandler(mediaHandlerId, callId, !isLoaded)
mediahandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(callId)
}
width: 350
height: contentItem.height
modal: true
contentItem: StackLayout {
id: stack
currentIndex: 0
height: childrenRect.height
Rectangle {
id: mediahandlerPickerPopupRect
width: root.width
height: childrenRect.height + 50
color: JamiTheme.backgroundColor
radius: 10
PushButton {
id: closeButton
anchors.top: mediahandlerPickerPopupRect.top
anchors.topMargin: 5
anchors.right: mediahandlerPickerPopupRect.right
anchors.rightMargin: 5
source: "qrc:/images/icons/round-close-24px.svg"
imageColor: JamiTheme.textColor
onClicked: {
root.close()
}
}
ColumnLayout {
id: mediahandlerPickerPopupRectColumnLayout
anchors.top: mediahandlerPickerPopupRect.top
anchors.topMargin: 15
height: 230
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
color: JamiTheme.textColor
text: qsTr("Choose plugin")
}
ListView {
id: mediahandlerPickerListView
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: mediahandlerPickerPopupRect.width
Layout.preferredHeight: 200
model: {
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
return PluginAdapter.getMediaHandlerSelectableModel(callId)
}
clip: true
delegate: MediaHandlerItemDelegate {
id: mediaHandlerItemDelegate
visible: PluginModel.getPluginsEnabled()
width: mediahandlerPickerListView.width
height: 50
mediaHandlerName : MediaHandlerName
mediaHandlerId: MediaHandlerId
mediaHandlerIcon: MediaHandlerIcon
isLoaded: IsLoaded
pluginId: PluginId
onBtnLoadMediaHandlerToggled: {
toggleMediaHandlerSlot(mediaHandlerId, isLoaded)
}
onOpenPreferences: {
mediahandlerPreferencePickerListView.pluginId = pluginId
mediahandlerPreferencePickerListView.mediaHandlerName = mediaHandlerName
mediahandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(pluginId, mediaHandlerName)
stack.currentIndex = 1
}
}
ScrollIndicator.vertical: ScrollIndicator {}
}
}
}
Rectangle {
id: mediahandlerPreferencePopupRect2
width: root.width
height: childrenRect.height + 50
color: JamiTheme.backgroundColor
radius: 10
PushButton {
id: backButton
anchors.top: mediahandlerPreferencePopupRect2.top
anchors.topMargin: 5
anchors.left: mediahandlerPreferencePopupRect2.left
anchors.leftMargin: 5
imageColor: JamiTheme.textColor
source: "qrc:/images/icons/ic_arrow_back_24px.svg"
toolTipText: qsTr("Go back to plugins list")
hoverEnabled: true
onClicked: {
stack.currentIndex = 0
}
}
PushButton {
id: closeButton2
anchors.top: mediahandlerPreferencePopupRect2.top
anchors.topMargin: 5
anchors.right: mediahandlerPreferencePopupRect2.right
anchors.rightMargin: 5
source: "qrc:/images/icons/round-close-24px.svg"
imageColor: JamiTheme.textColor
onClicked: {
stack.currentIndex = 0
root.close()
}
}
ColumnLayout {
anchors.top: mediahandlerPreferencePopupRect2.top
anchors.topMargin: 15
height: 230
Text {
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: mediahandlerPreferencePopupRect2.width
Layout.preferredHeight: 30
font.pointSize: JamiTheme.textFontSize
font.bold: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: JamiTheme.textColor
text: qsTr("Preferences")
}
ListView {
id: mediahandlerPreferencePickerListView
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: mediahandlerPickerPopupRect.width
Layout.preferredHeight: 200
property string pluginId: ""
property string mediaHandlerName: ""
model: PluginAdapter.getPluginPreferencesModel(pluginId, mediaHandlerName)
clip: true
delegate: PreferenceItemDelegate {
id: mediaHandlerPreferenceDelegate
width: mediahandlerPreferencePickerListView.width
height: childrenRect.height
preferenceName: PreferenceName
preferenceSummary: PreferenceSummary
preferenceType: PreferenceType
preferenceCurrentValue: PreferenceCurrentValue
pluginId: PluginId
currentPath: CurrentPath
preferenceKey : PreferenceKey
fileFilters: FileFilters
isImage: IsImage
pluginListPreferenceModel: PluginListPreferenceModel{
id: pluginListPreferenceModel
preferenceKey : PreferenceKey
pluginId: PluginId
}
onClicked: mediahandlerPreferencePickerListView.currentIndex = index
onBtnPreferenceClicked: {
PluginModel.setPluginPreference(pluginId, preferenceKey, preferenceNewValue)
mediahandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(pluginId, mediahandlerPreferencePickerListView.mediaHandlerName)
}
}
ScrollIndicator.vertical: ScrollIndicator {}
}
}
}
}
onAboutToHide: stack.currentIndex = 0
onAboutToShow: {
// Reset the model on each show.
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
mediahandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(callId)
}
background: Rectangle {
color: "transparent"
}
}

View file

@ -26,6 +26,7 @@ import net.jami.Adapters 1.0
import net.jami.Constants 1.0
import "../../commoncomponents"
import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation
Rectangle {
id: messageWebViewRect
@ -136,6 +137,14 @@ Rectangle {
onNeedToHideConversationInCall: {
messageWebViewRect.needToHideConversationInCall()
}
onPluginSelector : {
// Create plugin handler picker - PLUGINS
PluginHandlerPickerCreation.createPluginHandlerPickerObjects(messageWebViewRect, false)
PluginHandlerPickerCreation.calculateCurrentGeo(
messageWebViewRect.width / 2, messageWebViewRect.height / 2)
PluginHandlerPickerCreation.openPluginHandlerPicker()
}
}
QtObject {

View file

@ -21,6 +21,7 @@ import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import net.jami.Models 1.0
import net.jami.Constants 1.0
import net.jami.Adapters 1.0
import "../../commoncomponents"
@ -34,6 +35,7 @@ Rectangle {
signal backClicked
signal needToHideConversationInCall
signal pluginSelector
function resetBackToWelcomeViewButtonSource(reset) {
backToWelcomeViewButtonSource = reset ? "qrc:/images/icons/ic_arrow_back_24px.svg" : "qrc:/images/icons/round-close-24px.svg"
@ -42,6 +44,7 @@ Rectangle {
function toggleMessagingHeaderButtonsVisible(visible) {
startAAudioCallButton.visible = visible
startAVideoCallButton.visible = visible
selectPluginButton.visible = visible
}
color: JamiTheme.secondaryBackgroundColor
@ -155,7 +158,8 @@ Rectangle {
PushButton {
id: startAVideoCallButton
anchors.right: sendContactRequestButton.visible ?
anchors.right: selectPluginButton.visible ? selectPluginButton.left :
sendContactRequestButton.visible ?
sendContactRequestButton.left :
buttonGroup.right
anchors.rightMargin: 16
@ -173,6 +177,32 @@ Rectangle {
}
}
PushButton {
id: selectPluginButton
visible: UtilsAdapter.checkShowPluginsButton(false)
Connections {
target: PluginAdapter
function onPluginHandlersUpdateStatus() {
selectPluginButton.visible = UtilsAdapter.checkShowPluginsButton(false)
}
}
anchors.right: sendContactRequestButton.visible ?
sendContactRequestButton.left :
buttonGroup.right
anchors.rightMargin: 16
anchors.verticalCenter: buttonGroup.verticalCenter
source: "qrc:/images/icons/extension_24dp.svg"
normalColor: JamiTheme.secondaryBackgroundColor
imageColor: JamiTheme.chatviewButtonColor
onClicked: pluginSelector()
}
PushButton {
id: sendContactRequestButton

View file

@ -30,13 +30,13 @@ import "../../commoncomponents"
ItemDelegate {
id: root
property string mediaHandlerName : ""
property string mediaHandlerId: ""
property string mediaHandlerIcon: ""
property string handlerName : ""
property string handlerId: ""
property string handlerIcon: ""
property bool isLoaded: false
property string pluginId: ""
signal btnLoadMediaHandlerToggled
signal btnLoadHandlerToggled
signal openPreferences
RowLayout{
@ -52,7 +52,7 @@ ItemDelegate {
color: "transparent"
Image {
anchors.centerIn: parent
source: "file:" + mediaHandlerIcon
source: "file:" + handlerIcon
width: 30
height: 30
mipmap: true
@ -69,7 +69,7 @@ ItemDelegate {
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
text: mediaHandlerName === "" ? mediaHandlerId : mediaHandlerName
text: handlerName === "" ? handlerId : handlerName
}
Switch {
@ -89,7 +89,7 @@ ItemDelegate {
checked: isLoaded
onClicked: {
btnLoadMediaHandlerToggled()
btnLoadHandlerToggled()
}
background: Rectangle {
@ -116,7 +116,7 @@ ItemDelegate {
}
PushButton {
id: btnPreferencesMediaHandler
id: btnPreferencesPluginHandler
Layout.alignment: Qt.AlingVCenter | Qt.AlignRight
Layout.rightMargin: 8

View file

@ -0,0 +1,297 @@
/*
* Copyright (C) 2021 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.14
import net.jami.Models 1.0
import net.jami.Adapters 1.0
import net.jami.Constants 1.0
import "../../commoncomponents"
Popup {
id: root
property bool isCall
property string pluginId: ""
property string handlerName: ""
signal updateProperties
width: JamiTheme.preferredDialogWidth
height: JamiTheme.pluginHandlersPopupViewHeight + JamiTheme.pluginHandlersPopupViewDelegateHeight
modal: true
contentItem: StackView {
id: stack
initialItem: pluginhandlerPreferenceStack
anchors.fill: parent
}
Component {
id: pluginhandlerPreferenceStack
Rectangle {
color: JamiTheme.backgroundColor
radius: 10
anchors.fill: parent
Connections {
target: root
function onAboutToShow(visible) {
if (isCall) {
// Reset the model on each show.
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(callId)
} else {
// Reset the model on each show.
var accountId = AccountAdapter.currentAccountId
var peerId = UtilsAdapter.getPeerUri(accountId, UtilsAdapter.getCurrConvId())
pluginhandlerPickerListView.model = PluginAdapter.getChatHandlerSelectableModel(accountId, peerId)
}
}
}
function toggleHandlerSlot(handlerId, isLoaded) {
if (isCall) {
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
PluginModel.toggleCallMediaHandler(handlerId, callId, !isLoaded)
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(callId)
} else {
var accountId = AccountAdapter.currentAccountId
var peerId = UtilsAdapter.getPeerUri(accountId, UtilsAdapter.getCurrConvId())
PluginModel.toggleChatHandler(handlerId, accountId, peerId, !isLoaded)
pluginhandlerPickerListView.model = PluginAdapter.getChatHandlerSelectableModel(accountId, peerId)
}
}
ColumnLayout {
anchors.fill: parent
anchors.bottomMargin: 5
RowLayout {
height: JamiTheme.preferredFieldHeight
PushButton {
id: closeButton
Layout.leftMargin: 5
Layout.topMargin: 5
source: "qrc:/images/icons/round-close-24px.svg"
imageColor: JamiTheme.textColor
onClicked: {
root.close()
}
}
Text {
Layout.topMargin: 10
Layout.rightMargin: 5 + closeButton.width
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
font.pointSize: JamiTheme.textFontSize
font.bold: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: JamiTheme.textColor
text: qsTr("Choose plugin")
}
}
ListView {
id: pluginhandlerPickerListView
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true
model: {
if (isCall) {
var callId = UtilsAdapter.getCallId(callStackViewWindow.responsibleAccountId,
callStackViewWindow.responsibleConvUid)
return PluginAdapter.getMediaHandlerSelectableModel(callId)
} else {
var accountId = AccountAdapter.currentAccountId
var peerId = UtilsAdapter.getPeerUri(accountId, UtilsAdapter.getCurrConvId())
return PluginAdapter.getChatHandlerSelectableModel(accountId, peerId)
}
}
clip: true
delegate: PluginHandlerItemDelegate {
id: pluginHandlerItemDelegate
visible: PluginModel.getPluginsEnabled()
width: pluginhandlerPickerListView.width
height: JamiTheme.pluginHandlersPopupViewDelegateHeight
handlerName : HandlerName
handlerId: HandlerId
handlerIcon: HandlerIcon
isLoaded: IsLoaded
pluginId: PluginId
onBtnLoadHandlerToggled: {
toggleHandlerSlot(HandlerId, isLoaded)
}
onOpenPreferences: {
root.pluginId = pluginId
root.handlerName = handlerName
stack.push(pluginhandlerPreferenceStack2, StackView.Immediate)
updateProperties()
}
}
ScrollIndicator.vertical: ScrollIndicator {}
}
}
}
}
Component {
id: pluginhandlerPreferenceStack2
Rectangle {
color: JamiTheme.backgroundColor
radius: 10
anchors.fill: parent
Connections {
target: root
function onUpdateProperties() {
pluginhandlerPreferencePickerListView.pluginId = root.pluginId
pluginhandlerPreferencePickerListView.handlerName = root.handlerName
pluginhandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(root.pluginId, root.handlerName)
}
}
ColumnLayout {
anchors.fill: parent
anchors.bottomMargin: 5
RowLayout {
height: JamiTheme.preferredFieldHeight
PushButton {
id: backButton
Layout.leftMargin: 5
Layout.topMargin: 5
imageColor: JamiTheme.textColor
source: "qrc:/images/icons/ic_arrow_back_24px.svg"
toolTipText: qsTr("Go back to plugins list")
hoverEnabled: true
onClicked: {
stack.pop(null, StackView.Immediate)
}
}
Text {
Layout.topMargin: 10
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
font.pointSize: JamiTheme.textFontSize
font.bold: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: JamiTheme.textColor
text: qsTr("Preferences")
}
PushButton {
id: closeButton2
Layout.rightMargin: 5
Layout.topMargin: 5
source: "qrc:/images/icons/round-close-24px.svg"
imageColor: JamiTheme.textColor
onClicked: {
root.close()
}
}
}
ListView {
id: pluginhandlerPreferencePickerListView
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true
property string pluginId: ""
property string handlerName: ""
model: PluginAdapter.getPluginPreferencesModel(pluginId, handlerName)
clip: true
delegate: PreferenceItemDelegate {
id: pluginHandlerPreferenceDelegate
width: pluginhandlerPreferencePickerListView.width
height: JamiTheme.pluginHandlersPopupViewDelegateHeight
preferenceName: PreferenceName
preferenceSummary: PreferenceSummary
preferenceType: PreferenceType
preferenceCurrentValue: PreferenceCurrentValue
pluginId: PluginId
currentPath: CurrentPath
preferenceKey : PreferenceKey
fileFilters: FileFilters
isImage: IsImage
pluginListPreferenceModel: PluginListPreferenceModel {
id: handlerPickerPreferenceModel
preferenceKey : PreferenceKey
pluginId: PluginId
}
onClicked: pluginhandlerPreferencePickerListView.currentIndex = index
onBtnPreferenceClicked: {
PluginModel.setPluginPreference(pluginId, preferenceKey, preferenceNewValue)
PluginAdapter.pluginHandlersUpdateStatus()
pluginhandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(pluginId, pluginhandlerPreferencePickerListView.handlerName)
}
}
ScrollIndicator.vertical: ScrollIndicator {}
}
}
}
}
onAboutToHide: stack.pop(null, StackView.Immediate)
background: Rectangle {
color: "transparent"
}
}

View file

@ -346,4 +346,3 @@ Rectangle {
}
}
}

View file

@ -1,66 +0,0 @@
/**
* 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")
} else {
mediahandlerPickerObject.x = Qt.binding(function(){
return parent.width/2 - mediahandlerPickerObject.width / 2})
mediahandlerPickerObject.y = Qt.binding(function(){
return parent.height/2 - mediahandlerPickerObject.height / 2})
}
}
function openMediaHandlerPicker() {
if (mediahandlerPickerObject)
mediahandlerPickerObject.open()
}
function closeMediaHandlerPicker() {
if (mediahandlerPickerObject)
mediahandlerPickerObject.close()
}

View file

@ -0,0 +1,78 @@
/**
* Copyright (C) 2021 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 pluginhandler picker component, object variable for creation.
*/
var pluginhandlerPickerComponent
var pluginhandlerPickerObject
function createPluginHandlerPickerObjects(parent, isCall) {
if (pluginhandlerPickerObject) {
/*
* If already created, reset parameters, since object cannot be destroyed.
*/
pluginhandlerPickerObject.parent = parent
return
}
pluginhandlerPickerComponent = Qt.createComponent(
"../components/PluginHandlerPicker.qml")
if (pluginhandlerPickerComponent.status === Component.Ready)
finishCreation(parent, isCall)
else if (pluginhandlerPickerComponent.status === Component.Error)
console.log("Error loading component:",
pluginhandlerPickerComponent.errorString())
}
function finishCreation(parent, isCall) {
pluginhandlerPickerObject = pluginhandlerPickerComponent.createObject(parent)
if (pluginhandlerPickerObject === null) {
/*
* Error Handling.
*/
console.log("Error creating object for pluginhandler picker")
} else {
pluginhandlerPickerObject.x = Qt.binding(function(){
return parent.width/2 - pluginhandlerPickerObject.width / 2})
pluginhandlerPickerObject.y = Qt.binding(function(){
return parent.height/2 - pluginhandlerPickerObject.height / 2})
}
pluginhandlerPickerObject.isCall = isCall
}
/*
* Put pluginhandler picker in the middle of container.
*/
function calculateCurrentGeo(containerX, containerY) {
if (pluginhandlerPickerObject) {
pluginhandlerPickerObject.x = containerX - pluginhandlerPickerObject.width / 2
pluginhandlerPickerObject.y = containerY - pluginhandlerPickerObject.height / 2
}
}
function openPluginHandlerPicker() {
if (pluginhandlerPickerObject)
pluginhandlerPickerObject.open()
}
function closePluginHandlerPicker() {
if (pluginhandlerPickerObject)
pluginhandlerPickerObject.close()
}

View file

@ -1,149 +0,0 @@
/**
* 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, const QString& callId)
: QAbstractListModel(parent)
{
callId_ = callId;
}
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(callId_);
bool loaded = false;
for (const auto& mediaHandler : status[callId_])
if (mediaHandler == details.id)
loaded = true;
if (!details.pluginId.isEmpty()) {
details.pluginId.remove(details.pluginId.size() - 5, 5);
}
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);
case Role::PluginId:
return QVariant(details.pluginId);
}
return QVariant();
}
QHash<int, QByteArray>
MediaHandlerItemListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[MediaHandlerName] = "MediaHandlerName";
roles[MediaHandlerId] = "MediaHandlerId";
roles[MediaHandlerIcon] = "MediaHandlerIcon";
roles[IsLoaded] = "IsLoaded";
roles[PluginId] = "PluginId";
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();
}
QString
MediaHandlerItemListModel::callId()
{
return callId_;
}
void
MediaHandlerItemListModel::setCallId(QString callId)
{
callId_ = callId;
}

View file

@ -27,8 +27,15 @@ PluginAdapter::PluginAdapter(QObject* parent)
QVariant
PluginAdapter::getMediaHandlerSelectableModel(const QString& callId)
{
mediaHandlerListModel_.reset(new MediaHandlerItemListModel(this, callId));
return QVariant::fromValue(mediaHandlerListModel_.get());
pluginHandlerListModel_.reset(new PluginHandlerItemListModel(this, callId, QString("")));
return QVariant::fromValue(pluginHandlerListModel_.get());
}
QVariant
PluginAdapter::getChatHandlerSelectableModel(const QString& accountId, const QString& peerId)
{
pluginHandlerListModel_.reset(new PluginHandlerItemListModel(this, accountId, peerId));
return QVariant::fromValue(pluginHandlerListModel_.get());
}
QVariant

View file

@ -20,7 +20,7 @@
#include "qmladapterbase.h"
#include "pluginitemlistmodel.h"
#include "mediahandleritemlistmodel.h"
#include "pluginhandleritemlistmodel.h"
#include "pluginlistpreferencemodel.h"
#include "preferenceitemlistmodel.h"
@ -38,13 +38,18 @@ public:
protected:
void safeInit() override {};
Q_INVOKABLE QVariant getMediaHandlerSelectableModel(const QString& callId = QString(""));
Q_INVOKABLE QVariant getMediaHandlerSelectableModel(const QString& callId);
Q_INVOKABLE QVariant getChatHandlerSelectableModel(const QString& accountId,
const QString& peerId);
Q_INVOKABLE QVariant getPluginSelectableModel();
Q_INVOKABLE QVariant getPluginPreferencesModel(const QString& pluginId,
const QString& mediaHandlerName = "");
signals:
void pluginHandlersUpdateStatus();
private:
std::unique_ptr<MediaHandlerItemListModel> mediaHandlerListModel_;
std::unique_ptr<PluginHandlerItemListModel> pluginHandlerListModel_;
std::unique_ptr<PreferenceItemListModel> preferenceItemListModel_;
std::unique_ptr<PluginItemListModel> pluginItemListModel_;
};

View file

@ -0,0 +1,218 @@
/**
* 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 "pluginhandleritemlistmodel.h"
PluginHandlerItemListModel::PluginHandlerItemListModel(QObject* parent,
const QString& accountId,
const QString& peerId)
: QAbstractListModel(parent)
{
if (!peerId.isEmpty()) {
accountId_ = accountId;
peerId_ = peerId;
isMediaHandler_ = false;
} else {
callId_ = accountId;
isMediaHandler_ = true;
}
}
PluginHandlerItemListModel::~PluginHandlerItemListModel() {}
int
PluginHandlerItemListModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid()) {
/*
* Count.
*/
if (isMediaHandler_)
return LRCInstance::pluginModel().getCallMediaHandlers().size();
else
return LRCInstance::pluginModel().getChatHandlers().size();
}
/*
* A valid QModelIndex returns 0 as no entry has sub-elements.
*/
return 0;
}
int
PluginHandlerItemListModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
/*
* Only need one column.
*/
return 1;
}
QVariant
PluginHandlerItemListModel::data(const QModelIndex& index, int role) const
{
QString name {""};
QString id {""};
QString iconPath {""};
QString pluginId {""};
bool loaded = false;
if (isMediaHandler_) {
auto mediahandlerList = LRCInstance::pluginModel().getCallMediaHandlers();
if (!index.isValid() || mediahandlerList.size() <= index.row()) {
return QVariant();
}
auto details = LRCInstance::pluginModel().getCallMediaHandlerDetails(
mediahandlerList.at(index.row()));
for (const auto& mediaHandler :
LRCInstance::pluginModel().getCallMediaHandlerStatus(callId_))
if (mediaHandler == details.id)
loaded = true;
if (!details.pluginId.isEmpty()) {
details.pluginId.remove(details.pluginId.size() - 5, 5);
}
name = details.name;
id = mediahandlerList.at(index.row());
iconPath = details.iconPath;
pluginId = details.pluginId;
} else {
auto chathandlerList = LRCInstance::pluginModel().getChatHandlers();
if (!index.isValid() || chathandlerList.size() <= index.row()) {
return QVariant();
}
auto details = LRCInstance::pluginModel().getChatHandlerDetails(
chathandlerList.at(index.row()));
for (const auto& chatHandler :
LRCInstance::pluginModel().getChatHandlerStatus(accountId_, peerId_))
if (chatHandler == details.id)
loaded = true;
if (!details.pluginId.isEmpty()) {
details.pluginId.remove(details.pluginId.size() - 5, 5);
}
name = details.name;
id = chathandlerList.at(index.row());
iconPath = details.iconPath;
pluginId = details.pluginId;
}
switch (role) {
case Role::HandlerName:
return QVariant(name);
case Role::HandlerId:
return QVariant(id);
case Role::HandlerIcon:
return QVariant(iconPath);
case Role::IsLoaded:
return QVariant(loaded);
case Role::PluginId:
return QVariant(pluginId);
}
return QVariant();
}
QHash<int, QByteArray>
PluginHandlerItemListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[HandlerName] = "HandlerName";
roles[HandlerId] = "HandlerId";
roles[HandlerIcon] = "HandlerIcon";
roles[IsLoaded] = "IsLoaded";
roles[PluginId] = "PluginId";
return roles;
}
QModelIndex
PluginHandlerItemListModel::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
PluginHandlerItemListModel::parent(const QModelIndex& child) const
{
Q_UNUSED(child);
return QModelIndex();
}
Qt::ItemFlags
PluginHandlerItemListModel::flags(const QModelIndex& index) const
{
auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
if (!index.isValid()) {
return QAbstractItemModel::flags(index);
}
return flags;
}
void
PluginHandlerItemListModel::reset()
{
beginResetModel();
endResetModel();
}
QString
PluginHandlerItemListModel::callId()
{
return callId_;
}
void
PluginHandlerItemListModel::setCallId(QString callId)
{
callId_ = callId;
}
QString
PluginHandlerItemListModel::accountId()
{
return accountId_;
}
void
PluginHandlerItemListModel::setAccountId(QString accountId)
{
accountId_ = accountId;
}
QString
PluginHandlerItemListModel::peerId()
{
return peerId_;
}
void
PluginHandlerItemListModel::setPeerId(QString peerId)
{
peerId_ = peerId;
}

View file

@ -24,22 +24,20 @@
#include "lrcinstance.h"
class MediaHandlerItemListModel : public QAbstractListModel
class PluginHandlerItemListModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Role {
MediaHandlerName = Qt::UserRole + 1,
MediaHandlerId,
MediaHandlerIcon,
IsLoaded,
PluginId
};
enum Role { HandlerName = Qt::UserRole + 1, HandlerId, HandlerIcon, IsLoaded, PluginId };
Q_ENUM(Role)
explicit MediaHandlerItemListModel(QObject* parent = 0, const QString& callId = QString(""));
~MediaHandlerItemListModel();
explicit PluginHandlerItemListModel(
QObject* parent = 0,
const QString& accountId = QString(""),
const QString& peerId = QString(
"")); // for calls, accountId is the callId and peerId is null
~PluginHandlerItemListModel();
/*
* QAbstractListModel override.
@ -62,7 +60,14 @@ public:
QString callId();
void setCallId(QString callId);
QString accountId();
void setAccountId(QString accountId);
QString peerId();
void setPeerId(QString peerId);
private:
QString callId_ = QString("");
QString accountId_ = QString("");
QString peerId_ = QString("");
bool isMediaHandler_;
};

View file

@ -29,7 +29,7 @@ PluginItemListModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid()) {
/// Count
return LRCInstance::pluginModel().listAvailablePlugins().size();
return LRCInstance::pluginModel().getInstalledPlugins().size();
}
/// A valid QModelIndex returns 0 as no entry has sub-elements.
return 0;
@ -46,7 +46,7 @@ PluginItemListModel::columnCount(const QModelIndex& parent) const
QVariant
PluginItemListModel::data(const QModelIndex& index, int role) const
{
auto pluginList = LRCInstance::pluginModel().listAvailablePlugins();
auto pluginList = LRCInstance::pluginModel().getInstalledPlugins();
if (!index.isValid() || pluginList.size() <= index.row()) {
return QVariant();
}
@ -119,5 +119,5 @@ PluginItemListModel::reset()
int
PluginItemListModel::pluginsCount()
{
return LRCInstance::pluginModel().listAvailablePlugins().size();
return LRCInstance::pluginModel().getInstalledPlugins().size();
}

View file

@ -33,7 +33,7 @@
#include "deviceitemlistmodel.h"
#include "distantrenderer.h"
#include "pluginadapter.h"
#include "mediahandleritemlistmodel.h"
#include "pluginhandleritemlistmodel.h"
#include "messagesadapter.h"
#include "namedirectory.h"
#include "updatemanager.h"
@ -101,7 +101,7 @@ registerTypes()
QML_REGISTERTYPE("net.jami.Models", AccountListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", DeviceItemListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", PluginItemListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", MediaHandlerItemListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", PluginHandlerItemListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", PreferenceItemListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", BannedListModel, 1, 0);
QML_REGISTERTYPE("net.jami.Models", ModeratorListModel, 1, 0);

View file

@ -63,6 +63,7 @@ Rectangle {
PluginModel.resetPluginPreferencesValues(pluginId)
}
pluginPreferenceView.model = PluginAdapter.getPluginPreferencesModel(pluginId)
PluginAdapter.pluginHandlersUpdateStatus()
}
function uninstallPluginSlot() {
@ -72,11 +73,13 @@ Rectangle {
}]
msgDialog.openWithParameters(qsTr("Uninstall plugin"),
qsTr("Are you sure you wish to uninstall " + pluginName + " ?"))
PluginAdapter.pluginHandlersUpdateStatus()
}
function uninstallPlugin() {
PluginModel.uninstallPlugin(pluginId)
uninstalled()
PluginAdapter.pluginHandlersUpdateStatus()
}
function setPreference(pluginId, preferenceKey, preferenceNewValue)
@ -87,6 +90,7 @@ Rectangle {
PluginModel.loadPlugin(pluginId)
} else
PluginModel.setPluginPreference(pluginId, preferenceKey, preferenceNewValue)
PluginAdapter.pluginHandlersUpdateStatus()
}
SimpleMessageDialog {

View file

@ -56,6 +56,7 @@ Rectangle {
loaded = PluginModel.loadPlugin(pluginId)
if (pluginListPreferencesView.pluginId === pluginId)
pluginListPreferencesView.isLoaded = loaded
PluginAdapter.pluginHandlersUpdateStatus()
}
function openPreferencesPluginSlot(pluginName, pluginIcon, pluginId, isLoaded) {

View file

@ -40,6 +40,7 @@ Rectangle {
function slotSetPluginEnabled(state) {
PluginModel.setPluginsEnabled(state)
PluginAdapter.pluginHandlersUpdateStatus()
}
color: JamiTheme.secondaryBackgroundColor

View file

@ -110,6 +110,14 @@ UtilsAdapter::getBestName(const QString& accountId, const QString& uid)
return QString();
}
const QString
UtilsAdapter::getPeerUri(const QString& accountId, const QString& uid)
{
auto* convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get();
const auto& convInfo = convModel->getConversationForUid(uid).value();
return convInfo.get().participants.front();
}
QString
UtilsAdapter::getBestId(const QString& accountId)
{
@ -316,10 +324,14 @@ UtilsAdapter::getAbsPath(QString path)
}
bool
UtilsAdapter::checkShowPluginsButton()
UtilsAdapter::checkShowPluginsButton(bool isCall)
{
return LRCInstance::pluginModel().getPluginsEnabled()
&& (LRCInstance::pluginModel().listLoadedPlugins().size() > 0);
if (isCall)
return LRCInstance::pluginModel().getPluginsEnabled()
&& (LRCInstance::pluginModel().getCallMediaHandlers().size() > 0);
else
return LRCInstance::pluginModel().getPluginsEnabled()
&& (LRCInstance::pluginModel().getChatHandlers().size() > 0);
}
QString

View file

@ -47,6 +47,7 @@ public:
Q_INVOKABLE int getTotalUnreadMessages();
Q_INVOKABLE int getTotalPendingRequest();
Q_INVOKABLE const QString getBestName(const QString& accountId, const QString& uid);
Q_INVOKABLE const QString getPeerUri(const QString& accountId, const QString& uid);
Q_INVOKABLE QString getBestId(const QString& accountId);
Q_INVOKABLE const QString getBestId(const QString& accountId, const QString& uid);
Q_INVOKABLE const QString getCurrConvId();
@ -68,7 +69,7 @@ public:
Q_INVOKABLE QString toFileInfoName(QString inputFileName);
Q_INVOKABLE QString toFileAbsolutepath(QString inputFileName);
Q_INVOKABLE QString getAbsPath(QString path);
Q_INVOKABLE bool checkShowPluginsButton();
Q_INVOKABLE bool checkShowPluginsButton(bool isCall);
Q_INVOKABLE QString fileName(const QString& path);
Q_INVOKABLE QString getExt(const QString& path);
Q_INVOKABLE bool isImage(const QString& fileExt);