mainview: make all context menus generated at run time with the same style
By giving a base context menu, all context menus are generated at run time
and kept the same style. Some issues are fixed along with the patch.
Gitlab: #8
Gitlab: #35
Change-Id: Ieb812420fcb44c33d161a62c8574f6705dc5e1a9
diff --git a/src/commoncomponents/BaseContextMenu.qml b/src/commoncomponents/BaseContextMenu.qml
new file mode 100644
index 0000000..05227a5
--- /dev/null
+++ b/src/commoncomponents/BaseContextMenu.qml
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Mingrui Zhang <mingrui.zhang@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 QtGraphicalEffects 1.12
+import net.jami.Models 1.0
+
+Menu {
+ id: root
+
+ property int menuItemsPreferredWidth: 220
+ property int menuItemsPreferredHeight: 48
+ property int generalMenuSeparatorCount: 0
+ property int commonBorderWidth: 1
+ font.pointSize: JamiTheme.menuFontSize
+
+ function openMenu(){
+ visible = true
+ visible = false
+ visible = true
+ }
+
+ background: Rectangle {
+ implicitWidth: menuItemsPreferredWidth
+ implicitHeight: menuItemsPreferredHeight
+ * (root.count - generalMenuSeparatorCount)
+
+ border.width: commonBorderWidth
+ border.color: JamiTheme.tabbarBorderColor
+ }
+}
diff --git a/src/commoncomponents/GeneralMenuItem.qml b/src/commoncomponents/GeneralMenuItem.qml
index a457f8d..199f59d 100644
--- a/src/commoncomponents/GeneralMenuItem.qml
+++ b/src/commoncomponents/GeneralMenuItem.qml
@@ -35,8 +35,7 @@
property string iconSource: ""
property int preferredWidth: 220
property int preferredHeight: 48
- property int topBorderWidth: 0
- property int bottomBorderWidth: 0
+
property int leftBorderWidth: 0
property int rightBorderWidth: 0
@@ -99,8 +98,6 @@
id: contextMenuBackgroundRect
anchors.fill: parent
- anchors.topMargin: topBorderWidth
- anchors.bottomMargin: bottomBorderWidth
anchors.leftMargin: leftBorderWidth
anchors.rightMargin: rightBorderWidth
@@ -132,8 +129,8 @@
commonBorder: false
lBorderwidth: leftBorderWidth
rBorderwidth: rightBorderWidth
- tBorderwidth: topBorderWidth
- bBorderwidth: bottomBorderWidth
+ tBorderwidth: 0
+ bBorderwidth: 0
borderColor: JamiTheme.tabbarBorderColor
}
}
diff --git a/src/commoncomponents/js/contextmenugenerator.js b/src/commoncomponents/js/contextmenugenerator.js
new file mode 100644
index 0000000..7c55365
--- /dev/null
+++ b/src/commoncomponents/js/contextmenugenerator.js
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * Author: Mingrui Zhang <mingrui.zhang@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 base context menu, object variable for creation.
+var baseContextMenuComponent
+var baseContextMenuObject
+var menuItemList = []
+
+function createBaseContextMenuObjects(parent) {
+ // If already created, return, since object cannot be destroyed.
+ if (baseContextMenuObject)
+ return
+
+ baseContextMenuComponent = Qt.createComponent(
+ "../BaseContextMenu.qml")
+ if (baseContextMenuComponent.status === Component.Ready)
+ finishCreation(parent)
+ else if (baseContextMenuComponent.status === Component.Error)
+ console.log("Error loading component:",
+ baseContextMenuComponent.errorString())
+}
+
+function finishCreation(parent) {
+ baseContextMenuObject = baseContextMenuComponent.createObject(parent)
+ if (baseContextMenuObject === null) {
+ // Error Handling.
+ console.log("Error creating object for base context menu")
+ }
+
+ baseContextMenuObject.closed.connect(function (){
+ // Remove the menu items when hidden.
+ for (var i = 0; i < menuItemList.length; i++) {
+ baseContextMenuObject.removeItem(menuItemList[i])
+ }
+ })
+
+ baseContextMenuObject.aboutToShow.connect(function (){
+ // Add default separator at the bottom.
+ addMenuSeparator(8, "transparent")
+ })
+}
+
+function addMenuSeparator(separatorHeight, separatorColor) {
+ var menuSeparatorObject
+ var menuSeparatorComponent = Qt.createComponent("../GeneralMenuSeparator.qml");
+ if (menuSeparatorComponent.status === Component.Ready) {
+ baseContextMenuObject.generalMenuSeparatorCount ++
+ menuSeparatorObject = menuSeparatorComponent.createObject(null,
+ {preferredWidth: baseContextMenuObject.menuItemsPreferredWidth,
+ preferredHeight: separatorHeight ? separatorHeight : 1})
+ if (separatorColor)
+ menuSeparatorObject.separatorColor = separatorColor
+ } else if (menuSeparatorComponent.status === Component.Error)
+ console.log("Error loading component:",
+ menuSeparatorComponent.errorString())
+ if (menuSeparatorObject !== null) {
+ baseContextMenuObject.addItem(menuSeparatorObject)
+
+ menuItemList.push(menuSeparatorObject)
+ } else {
+ // Error handling.
+ console.log("Error creating object")
+ }
+}
+
+function addMenuItem(itemName,
+ iconSource,
+ onClickedCallback) {
+ if (!baseContextMenuObject.count){
+ // Add default separator at the top.
+ addMenuSeparator(8, "transparent")
+ }
+
+ var menuItemObject
+ var menuItemComponent = Qt.createComponent("../GeneralMenuItem.qml");
+ if (menuItemComponent.status === Component.Ready) {
+ menuItemObject = menuItemComponent.createObject(null,
+ {itemName: itemName,
+ iconSource: iconSource,
+ leftBorderWidth: baseContextMenuObject.commonBorderWidth,
+ rightBorderWidth: baseContextMenuObject.commonBorderWidth})
+ } else if (menuItemComponent.status === Component.Error)
+ console.log("Error loading component:",
+ menuItemComponent.errorString())
+ if (menuItemObject !== null) {
+ menuItemObject.clicked.connect(function () {baseContextMenuObject.close()})
+ menuItemObject.clicked.connect(onClickedCallback)
+ menuItemObject.icon.color = "black"
+
+ baseContextMenuObject.addItem(menuItemObject)
+
+ menuItemList.push(menuItemObject)
+ } else {
+ // Error handling.
+ console.log("Error creating object")
+ }
+}
+
+function getMenu() {
+ return baseContextMenuObject
+}
diff --git a/src/mainview/components/CallOverlayButtonGroup.qml b/src/mainview/components/CallOverlayButtonGroup.qml
index 107ab9e..88a097f 100644
--- a/src/mainview/components/CallOverlayButtonGroup.qml
+++ b/src/mainview/components/CallOverlayButtonGroup.qml
@@ -230,7 +230,7 @@
onClicked: {
var rectPos = mapToItem(callStackViewWindow, optionsButton.x, optionsButton.y)
- callViewContextMenu.activate()
+ callViewContextMenu.openMenu()
callViewContextMenu.x = rectPos.x + optionsButton.width/2 - callViewContextMenu.width/2
callViewContextMenu.y = rectPos.y - 12 - callViewContextMenu.height
}
diff --git a/src/mainview/components/CallViewContextMenu.qml b/src/mainview/components/CallViewContextMenu.qml
index 2deeeaa..5b2272a 100644
--- a/src/mainview/components/CallViewContextMenu.qml
+++ b/src/mainview/components/CallViewContextMenu.qml
@@ -17,6 +17,7 @@
* 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 QtGraphicalEffects 1.12
@@ -24,61 +25,125 @@
import "../../commoncomponents"
+import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
+import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
-Menu {
+Item {
id: root
- property int generalMenuSeparatorCount: 0
- property int commonBorderWidth: 1
-
- signal pluginItemClicked
-
- font.pointSize: JamiTheme.textFontSize+3
-
property bool isSIP: false
property bool isPaused: false
property bool isAudioOnly: false
property bool isRecording: false
+ signal pluginItemClicked
signal transferCallButtonClicked
- function activate() {
+ function openMenu(){
+ if (isSIP){
+ ContextMenuGenerator.addMenuItem(isPaused ? qsTr("Resume call") : qsTr("Hold call"),
+ isPaused ?
+ "qrc:/images/icons/play_circle_outline-24px.svg" :
+ "qrc:/images/icons/pause_circle_outline-24px.svg",
+ function (){
+ CallAdapter.holdThisCallToggle()
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Sip Input Panel"),
+ "qrc:/images/icons/ic_keypad.svg",
+ function (){
+ sipInputPanel.open()
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Transfer call"),
+ "qrc:/images/icons/phone_forwarded-24px.svg",
+ function (){
+ root.transferCallButtonClicked()
+ })
+
+ ContextMenuGenerator.addMenuSeparator()
+ }
+
+ if (!isAudioOnly) {
+ ContextMenuGenerator.addMenuItem(isRecording ? qsTr("Stop recording") :
+ qsTr("Start recording"),
+ "qrc:/images/icons/ic_video_call_24px.svg",
+ function (){
+ CallAdapter.recordThisCallToggle()
+ })
+ ContextMenuGenerator.addMenuItem(videoCallPage.isFullscreen ? qsTr("Exit full screen") :
+ qsTr("Full screen mode"),
+ videoCallPage.isFullscreen ?
+ "qrc:/images/icons/close_fullscreen-24px.svg" :
+ "qrc:/images/icons/open_in_full-24px.svg",
+ function (){
+ videoCallPageRect.needToShowInFullScreen()
+ })
+
+ ContextMenuGenerator.addMenuSeparator()
+
+ generateDeviceMenuItem()
+
+ ContextMenuGenerator.addMenuSeparator()
+
+ ContextMenuGenerator.addMenuItem(qsTr("Share entire screen"),
+ "qrc:/images/icons/screen_share-24px.svg",
+ function (){
+ if (Qt.application.screens.length === 1) {
+ AvAdapter.shareEntireScreen(0)
+ } else {
+ SelectScreenWindowCreation.createSelectScreenWindowObject()
+ SelectScreenWindowCreation.showSelectScreenWindow()
+ }
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Share screen area"),
+ "qrc:/images/icons/screen_share-24px.svg",
+ function (){
+ if (Qt.application.screens.length === 1) {
+ ScreenRubberBandCreation.createScreenRubberBandWindowObject(
+ null, 0)
+ ScreenRubberBandCreation.showScreenRubberBandWindow()
+ } else {
+ SelectScreenWindowCreation.createSelectScreenWindowObject(true)
+ SelectScreenWindowCreation.showSelectScreenWindow()
+ }
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Share file"),
+ "qrc:/images/icons/insert_photo-24px.svg",
+ function (){
+ jamiFileDialog.open()
+ })
+ }
+
+ ContextMenuGenerator.addMenuItem(qsTr("Toggle plugin"),
+ "qrc:/images/icons/extension_24dp.svg",
+ function (){
+ root.pluginItemClicked()
+ })
+
+ root.height = ContextMenuGenerator.getMenu().height
+ root.width = ContextMenuGenerator.getMenu().width
+ ContextMenuGenerator.getMenu().open()
+ }
+
+ function generateDeviceMenuItem() {
var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem()
+
/*
* Somehow, the map size is undefined, so use this instead.
*/
var mapSize = deviceContextMenuInfoMap["size"]
- var count = 2
+ if (mapSize === 0)
+ VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
+ qsTr("No video device"), false)
+
for (var deviceName in deviceContextMenuInfoMap) {
- if (deviceName === "size" || root.isAudioOnly)
+ if (deviceName === "size")
continue
- if (videoDeviceItem.itemName === "No video device") {
- videoDeviceItem.checkable = true
- videoDeviceItem.itemName = deviceName
- videoDeviceItem.checked = deviceContextMenuInfoMap[deviceName]
- if (count === mapSize)
- root.open()
- } else {
- VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
- deviceName, deviceContextMenuInfoMap[deviceName],
- count === mapSize)
- }
- count++
+ VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
+ deviceName, deviceContextMenuInfoMap[deviceName])
}
- root.open()
- }
-
- Component.onCompleted: {
- VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(root)
- }
-
-
- onClosed: {
- videoDeviceItem.itemName = "No video device"
- VideoDeviceContextMenuItemCreation.removeCreatedItems()
}
JamiFileDialog {
@@ -92,187 +157,13 @@
}
}
- /*
- * All GeneralMenuItems should remain the same width / height.
- */
- GeneralMenuItem {
- id: holdCallButton
+ Component.onCompleted: {
+ ContextMenuGenerator.createBaseContextMenuObjects(root)
+ VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(ContextMenuGenerator.getMenu())
- visible: isSIP
- height: isSIP? undefined : 0
-
- itemName: isPaused? qsTr("Resume call") : qsTr("Hold call")
- iconSource: isPaused? "qrc:/images/icons/play_circle_outline-24px.svg" : "qrc:/images/icons/pause_circle_outline-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- CallAdapter.holdThisCallToggle()
- root.close()
- }
- }
-
- GeneralMenuItem {
- id: showSipInputPanelButton
-
- visible: isSIP
- height: isSIP? undefined : 0
-
- itemName: qsTr("Sip Input Panel")
- iconSource: "qrc:/images/icons/ic_keypad.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- root.close()
- sipInputPanel.open()
- }
- }
-
- GeneralMenuItem {
- id: transferCallButton
-
- visible: isSIP
- height: isSIP? undefined : 0
-
- itemName: qsTr("Transfer call")
- iconSource: "qrc:/images/icons/phone_forwarded-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- root.transferCallButtonClicked()
- root.close()
- }
- }
-
- GeneralMenuSeparator {
- preferredWidth: startRecordingItem.preferredWidth
- preferredHeight: commonBorderWidth
-
- visible: isSIP
- height: isSIP? undefined : 0
-
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- GeneralMenuItem {
- id: startRecordingItem
-
- itemName: isRecording? qsTr("Stop recording") : qsTr("Start recording")
- iconSource: "qrc:/images/icons/ic_video_call_24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- root.close()
- CallAdapter.recordThisCallToggle()
- }
- }
-
- GeneralMenuItem {
- id: fullScreenItem
-
- itemName: videoCallPage.isFullscreen ? qsTr("Exit full screen") : qsTr(
- "Full screen mode")
- iconSource: videoCallPage.isFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" : "qrc:/images/icons/open_in_full-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- root.close()
- videoCallPageRect.needToShowInFullScreen()
- }
- }
-
- GeneralMenuSeparator {
- preferredWidth: startRecordingItem.preferredWidth
- preferredHeight: commonBorderWidth
-
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- VideoCallPageContextMenuDeviceItem {
- id: videoDeviceItem
- visible: !isAudioOnly
- height: !isAudioOnly? undefined : 0
-
- contextMenuPreferredWidth: root.implicitWidth
- }
-
- GeneralMenuSeparator {
- preferredWidth: startRecordingItem.preferredWidth
- preferredHeight: commonBorderWidth
- visible: !isAudioOnly
- height: !isAudioOnly? undefined : 0
-
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- GeneralMenuItem {
- id: shareEntireScreenItem
-
- itemName: qsTr("Share entire screen")
- iconSource: "qrc:/images/icons/screen_share-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
- visible: !isAudioOnly
- height: !isAudioOnly? undefined : 0
-
- onClicked: {
- root.close()
- if (Qt.application.screens.length === 1) {
- AvAdapter.shareEntireScreen(0)
- } else {
- SelectScreenWindowCreation.createSelectScreenWindowObject()
- SelectScreenWindowCreation.showSelectScreenWindow()
- }
- }
- }
-
- GeneralMenuItem {
- id: shareScreenAreaItem
-
- itemName: qsTr("Share screen area")
- iconSource: "qrc:/images/icons/screen_share-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
- visible: !isAudioOnly
- height: !isAudioOnly? undefined : 0
-
- onClicked: {
- root.close()
- if (Qt.application.screens.length === 1) {
- ScreenRubberBandCreation.createScreenRubberBandWindowObject(
- null, 0)
- ScreenRubberBandCreation.showScreenRubberBandWindow()
- } else {
- SelectScreenWindowCreation.createSelectScreenWindowObject(true)
- SelectScreenWindowCreation.showSelectScreenWindow()
- }
- }
- }
-
- GeneralMenuItem {
- id: shareFileItem
-
- itemName: qsTr("Share file")
- iconSource: "qrc:/images/icons/insert_photo-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
- visible: !isAudioOnly
- height: !isAudioOnly? undefined : 0
-
- onClicked: {
- root.close()
- jamiFileDialog.open()
- }
+ ContextMenuGenerator.getMenu().closed.connect(function (){
+ VideoDeviceContextMenuItemCreation.removeCreatedItems()
+ })
}
/* TODO: In the future we want to implement this
@@ -289,31 +180,5 @@
root.close()
}
}*/
-
- GeneralMenuItem {
- id: pluginItem
-
- itemName: qsTr("Toggle plugin")
- iconSource: "qrc:/images/icons/extension_24dp.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- root.pluginItemClicked()
- root.close()
- }
- }
-
- background: Rectangle {
- implicitWidth: startRecordingItem.preferredWidth
- implicitHeight: startRecordingItem.preferredHeight
- * (root.count
- - (isSIP? 0 : 2)
- - (isAudioOnly? 6 : 0)
- - generalMenuSeparatorCount)
-
- border.width: commonBorderWidth
- border.color: JamiTheme.tabbarBorderColor
- }
}
diff --git a/src/mainview/components/ConversationSmartListContextMenu.qml b/src/mainview/components/ConversationSmartListContextMenu.qml
index 26c5406..c5aa471 100644
--- a/src/mainview/components/ConversationSmartListContextMenu.qml
+++ b/src/mainview/components/ConversationSmartListContextMenu.qml
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
@@ -16,6 +15,7 @@
* 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 QtGraphicalEffects 1.12
@@ -23,157 +23,88 @@
import "../../commoncomponents"
-Menu {
- id: contextMenu
+import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
+
+Item {
+ id: root
+
property string responsibleAccountId: ""
property string responsibleConvUid: ""
-
- property int generalMenuSeparatorCount: 0
- property int commonBorderWidth: 1
- font.pointSize: JamiTheme.menuFontSize
+ property int contactType: Profile.Type.INVALID
function openMenu(){
- visible = true
- visible = false
- visible = true
- }
+ ContextMenuGenerator.addMenuItem(qsTr("Start video call"),
+ "qrc:/images/icons/ic_video_call_24px.svg",
+ function (){
+ ConversationsAdapter.selectConversation(
+ responsibleAccountId,
+ responsibleConvUid, false)
+ CallAdapter.placeCall()
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Start audio call"),
+ "qrc:/images/icons/ic_phone_24px.svg",
+ function (){
+ ConversationsAdapter.selectConversation(
+ responsibleAccountId,
+ responsibleConvUid, false)
+ CallAdapter.placeAudioOnlyCall()
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Clear conversation"),
+ "qrc:/images/icons/ic_clear_24px.svg",
+ function (){
+ ClientWrapper.utilsAdaptor.clearConversationHistory(
+ responsibleAccountId,
+ responsibleConvUid)
+ })
- GeneralMenuSeparator {
- preferredWidth: startVideoCallItem.preferredWidth
- preferredHeight: 8
- separatorColor: "transparent"
- Component.onCompleted: {
- generalMenuSeparatorCount++
+ if (contactType === Profile.Type.RING || contactType === Profile.Type.SIP) {
+ ContextMenuGenerator.addMenuItem(qsTr("Remove contact"),
+ "qrc:/images/icons/round-remove_circle-24px.svg",
+ function (){
+ ClientWrapper.utilsAdaptor.removeConversation(
+ responsibleAccountId,
+ responsibleConvUid)
+ })
}
- }
- /*
- * All GeneralMenuItems should remain the same width / height.
- */
- GeneralMenuItem {
- id: startVideoCallItem
+ if (contactType === Profile.Type.RING || contactType === Profile.Type.PENDING) {
+ ContextMenuGenerator.addMenuSeparator()
- itemName: qsTr("Start video call")
- iconSource: "qrc:/images/icons/ic_video_call_24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
+ if (contactType === Profile.Type.PENDING) {
+ ContextMenuGenerator.addMenuItem(qsTr("Accept request"),
+ "qrc:/images/icons/person_add-24px.svg",
+ function (){
+ MessagesAdapter.acceptInvitation(
+ responsibleConvUid)
+ })
+ ContextMenuGenerator.addMenuItem(qsTr("Decline request"),
+ "qrc:/images/icons/round-close-24px.svg",
+ function (){
+ MessagesAdapter.refuseInvitation(
+ responsibleConvUid)
+ })
+ }
+ ContextMenuGenerator.addMenuItem(qsTr("Block contact"),
+ "qrc:/images/icons/ic_block_24px.svg",
+ function (){
+ MessagesAdapter.blockConversation(
+ responsibleConvUid)
+ })
- onClicked: {
- contextMenu.close()
- ConversationsAdapter.selectConversation(responsibleAccountId,
- responsibleConvUid, false)
- CallAdapter.placeCall()
+ ContextMenuGenerator.addMenuSeparator()
+ ContextMenuGenerator.addMenuItem(qsTr("Profile"),
+ "qrc:/images/icons/person-24px.svg",
+ function (){
+ userProfile.open()
+ })
}
+
+ root.height = ContextMenuGenerator.getMenu().height
+ root.width = ContextMenuGenerator.getMenu().width
+ ContextMenuGenerator.getMenu().open()
}
- GeneralMenuItem {
- id: startAudioCallItem
-
- itemName: qsTr("Start audio call")
- iconSource: "qrc:/images/icons/ic_phone_24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- contextMenu.close()
- ConversationsAdapter.selectConversation(responsibleAccountId,
- responsibleConvUid, false)
- CallAdapter.placeAudioOnlyCall()
- }
- }
-
- GeneralMenuItem {
- id: clearConversationItem
-
- itemName: qsTr("Clear conversation")
- iconSource: "qrc:/images/icons/ic_clear_24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- contextMenu.close()
- ClientWrapper.utilsAdaptor.clearConversationHistory(responsibleAccountId,
- responsibleConvUid)
- }
- }
-
- GeneralMenuItem {
- id: removeContactItem
-
- itemName: qsTr("Remove contact")
- iconSource: "qrc:/images/icons/round-remove_circle-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- contextMenu.close()
- ClientWrapper.utilsAdaptor.removeConversation(responsibleAccountId,
- responsibleConvUid)
- }
- }
-
- GeneralMenuSeparator {
- preferredWidth: startVideoCallItem.preferredWidth
- preferredHeight: commonBorderWidth
-
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- GeneralMenuItem {
- id: blockContactItem
-
- itemName: qsTr("Block contact")
- iconSource: "qrc:/images/icons/ic_block_24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- contextMenu.close()
- ClientWrapper.utilsAdaptor.removeConversation(responsibleAccountId,
- responsibleConvUid, true)
- }
- }
-
- GeneralMenuSeparator {
- preferredWidth: startVideoCallItem.preferredWidth
- preferredHeight: commonBorderWidth
-
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- GeneralMenuItem {
- id: profileItem
-
- itemName: qsTr("Profile")
- iconSource: "qrc:/images/icons/person-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- contextMenu.close()
- userProfile.open()
- }
- }
-
- GeneralMenuSeparator {
- preferredWidth: startVideoCallItem.preferredWidth
- preferredHeight: 8
- separatorColor: "transparent"
- Component.onCompleted: {
- generalMenuSeparatorCount++
- }
- }
-
- background: Rectangle {
- implicitWidth: startVideoCallItem.preferredWidth
- implicitHeight: startVideoCallItem.preferredHeight
- * (contextMenu.count - generalMenuSeparatorCount)
-
- border.width: commonBorderWidth
- border.color: JamiTheme.tabbarBorderColor
+ Component.onCompleted: {
+ ContextMenuGenerator.createBaseContextMenuObjects(root)
}
}
diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml
index ee787f7..d16b96d 100644
--- a/src/mainview/components/ConversationSmartListView.qml
+++ b/src/mainview/components/ConversationSmartListView.qml
@@ -82,6 +82,10 @@
conversationSmartListView.model.setAccount(accountId)
}
+ ConversationSmartListContextMenu {
+ id: smartListContextMenu
+ }
+
Connections {
target: CallAdapter
diff --git a/src/mainview/components/ConversationSmartListViewItemDelegate.qml b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
index 7b564a8..74d07db 100644
--- a/src/mainview/components/ConversationSmartListViewItemDelegate.qml
+++ b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
@@ -180,7 +180,7 @@
itemSmartListBackground.color = JamiTheme.releaseColor
}
if (mouse.button === Qt.RightButton) {
-
+ smartListContextMenu.parent = mouseAreaSmartListItemDelegate
/*
* Make menu pos at mouse.
@@ -191,6 +191,7 @@
smartListContextMenu.y = relativeMousePos.y
smartListContextMenu.responsibleAccountId = ClientWrapper.utilsAdaptor.getCurrAccId()
smartListContextMenu.responsibleConvUid = UID
+ smartListContextMenu.contactType = ContactType
userProfile.responsibleConvUid = UID
userProfile.aliasText = DisplayName
userProfile.registeredNameText = DisplayID
@@ -225,8 +226,4 @@
}
}
}
-
- ConversationSmartListContextMenu {
- id: smartListContextMenu
- }
}
diff --git a/src/mainview/components/ParticipantContextMenu.qml b/src/mainview/components/ParticipantContextMenu.qml
index 9397701..87d883a 100644
--- a/src/mainview/components/ParticipantContextMenu.qml
+++ b/src/mainview/components/ParticipantContextMenu.qml
@@ -1,7 +1,7 @@
-
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ * Author: Mingrui Zhang <mingrui.zhang@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
@@ -16,6 +16,7 @@
* 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 QtGraphicalEffects 1.12
@@ -23,105 +24,46 @@
import "../../commoncomponents"
-import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
-import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
+import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
-Menu {
+Item {
id: root
- property int generalMenuSeparatorCount: 0
- property int commonBorderWidth: 1
- font.pointSize: JamiTheme.textFontSize + 3
property var uri: ""
property var maximized: true
property var active: true
+ property var showHangup: false
+ property var showMaximize: false
+ property var showMinimize: false
- function showHangup(show) {
- if (show) {
- hangupItem.visible = true
- hangupItem.height = hangupItem.preferredHeight
- } else {
- hangupItem.visible = false
- hangupItem.height = 0
- }
+ function openMenu(){
+ if (showHangup)
+ ContextMenuGenerator.addMenuItem(qsTr("Hang up"),
+ "qrc:/images/icons/ic_call_end_white_24px.svg",
+ function (){
+ CallAdapter.hangupCall(uri)
+ })
+
+ if (showMaximize)
+ ContextMenuGenerator.addMenuItem(qsTr("Maximize participant"),
+ "qrc:/images/icons/open_in_full-24px.svg",
+ function (){
+ CallAdapter.maximizeParticipant(uri, active)
+ })
+ if (showMinimize)
+ ContextMenuGenerator.addMenuItem(qsTr("Minimize participant"),
+ "qrc:/images/icons/close_fullscreen-24px.svg",
+ function (){
+ CallAdapter.minimizeParticipant()
+ })
+
+ root.height = ContextMenuGenerator.getMenu().height
+ root.width = ContextMenuGenerator.getMenu().width
+ ContextMenuGenerator.getMenu().open()
}
- function showMaximize(show) {
- if (show) {
- maximizeItem.visible = true
- maximizeItem.height = hangupItem.preferredHeight
- } else {
- maximizeItem.visible = false
- maximizeItem.height = 0
- }
- }
-
- function showMinimize(show) {
- if (show) {
- minimizeItem.visible = true
- minimizeItem.height = hangupItem.preferredHeight
- } else {
- minimizeItem.visible = false
- minimizeItem.height = 0
- }
- }
-
- function setHeight(visibleItems) {
- root.height = hangupItem.preferredHeight * visibleItems;
- }
-
- /*
- * All GeneralMenuItems should remain the same width / height.
- */
- GeneralMenuItem {
- id: hangupItem
-
- itemName: qsTr("Hangup")
- iconSource: "qrc:/images/icons/ic_call_end_white_24px.svg"
- icon.color: "black"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
- onClicked: {
- CallAdapter.hangupCall(uri)
- root.close()
- }
- }
- GeneralMenuItem {
- id: maximizeItem
-
- itemName: qsTr("Maximize participant")
- iconSource: "qrc:/images/icons/open_in_full-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
- visible: !maximized
-
- onClicked: {
- CallAdapter.maximizeParticipant(uri, active)
- root.close()
- }
- }
- GeneralMenuItem {
- id: minimizeItem
-
- itemName: qsTr("Minimize participant")
- iconSource: "qrc:/images/icons/close_fullscreen-24px.svg"
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
- visible: maximized
-
- onClicked: {
- CallAdapter.minimizeParticipant()
- root.close()
- }
- }
-
- background: Rectangle {
- implicitWidth: hangupItem.preferredWidth
- implicitHeight: hangupItem.preferredHeight * 3
-
- border.width: commonBorderWidth
- border.color: JamiTheme.tabbarBorderColor
+ Component.onCompleted: {
+ ContextMenuGenerator.createBaseContextMenuObjects(root)
}
}
diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml
index fb49a46..2f17b08 100644
--- a/src/mainview/components/ParticipantOverlay.qml
+++ b/src/mainview/components/ParticipantOverlay.qml
@@ -112,18 +112,14 @@
var layout = CallAdapter.getCurrentLayoutType()
var showMaximized = layout !== 2
var showMinimized = !(layout === 0 || (layout === 1 && !active))
- injectedContextMenu.showHangup(!root.isLocal)
- injectedContextMenu.showMaximize(showMaximized)
- injectedContextMenu.showMinimize(showMinimized)
- injectedContextMenu.setHeight(
- (root.isLocal ? 0 : 1)
- + (showMaximized ? 1 : 0)
- + (showMinimized ? 1 : 0))
+ injectedContextMenu.showHangup = !root.isLocal
+ injectedContextMenu.showMaximize = showMaximized
+ injectedContextMenu.showMinimize = showMinimized
injectedContextMenu.uri = uri
injectedContextMenu.active = active
injectedContextMenu.x = mousePos.x
injectedContextMenu.y = mousePos.y - injectedContextMenu.height
- injectedContextMenu.open()
+ injectedContextMenu.openMenu()
}
}
}
@@ -166,4 +162,4 @@
duration: 500
}
}
-}
\ No newline at end of file
+}
diff --git a/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml
index 73e692b..a6a4f80 100644
--- a/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml
+++ b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
@@ -16,24 +15,21 @@
* 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 net.jami.Models 1.0
import "../../commoncomponents"
-
/*
- * Take advantage of child can access parent's item (ex: contextMenu, commonBorderWidth).
+ * Menu item wrapper for video device checkable item.
*/
GeneralMenuItem {
id: videoCallPageContextMenuDeviceItem
property int contextMenuPreferredWidth: 250
- leftBorderWidth: commonBorderWidth
- rightBorderWidth: commonBorderWidth
-
TextMetrics {
id: textMetrics
elide: Text.ElideMiddle
@@ -54,7 +50,6 @@
onClicked: {
var deviceName = videoCallPageContextMenuDeviceItem.itemName
- contextMenu.close()
AvAdapter.onVideoContextMenuDeviceItemClicked(deviceName)
}
}
diff --git a/src/mainview/js/videodevicecontextmenuitemcreation.js b/src/mainview/js/videodevicecontextmenuitemcreation.js
index 02aa292..ca17fc7 100644
--- a/src/mainview/js/videodevicecontextmenuitemcreation.js
+++ b/src/mainview/js/videodevicecontextmenuitemcreation.js
@@ -40,24 +40,28 @@
videoContextMenuObject = obj
}
-function createVideoDeviceContextMenuItemObjects(deviceName, setChecked, last) {
+function createVideoDeviceContextMenuItemObjects(deviceName, setChecked) {
videoDeviceContextMenuItemComponent = Qt.createComponent(
"../components/VideoCallPageContextMenuDeviceItem.qml")
if (videoDeviceContextMenuItemComponent.status === Component.Ready)
- finishCreation(deviceName, setChecked, last)
+ finishCreation(deviceName, setChecked)
else if (videoDeviceContextMenuItemComponent.status === Component.Error)
console.log("Error loading component:",
videoDeviceContextMenuItemComponent.errorString())
}
-function finishCreation(deviceName, setChecked, last) {
+function finishCreation(deviceName, setChecked) {
videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject()
if (videoDeviceContextMenuItemObject === null) {
// Error Handling.
console.log("Error creating video context menu object")
}
+ videoDeviceContextMenuItemObject.leftBorderWidth =
+ videoContextMenuObject.commonBorderWidth
+ videoDeviceContextMenuItemObject.rightBorderWidth =
+ videoContextMenuObject.commonBorderWidth
videoDeviceContextMenuItemObject.itemName = deviceName
videoDeviceContextMenuItemObject.checkable = true
videoDeviceContextMenuItemObject.checked = setChecked
@@ -68,14 +72,11 @@
* Push into the storage array, and insert it into context menu.
*/
itemArray.push(videoDeviceContextMenuItemObject)
- videoContextMenuObject.insertItem(3 /* The button is at pos 3 in the menu */, videoDeviceContextMenuItemObject)
+ videoContextMenuObject.addItem(videoDeviceContextMenuItemObject)
-
- /*
- * If it is the last device context menu item, open the context menu.
- */
- if (last)
- videoContextMenuObject.open()
+ videoDeviceContextMenuItemObject.clicked.connect(function () {
+ videoContextMenuObject.close()
+ })
}
function removeCreatedItems() {
diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp
index 5214d0b..37b477f 100644
--- a/src/messagesadapter.cpp
+++ b/src/messagesadapter.cpp
@@ -633,24 +633,24 @@
}
void
-MessagesAdapter::acceptInvitation()
+MessagesAdapter::acceptInvitation(const QString &convUid)
{
- const auto convUid = LRCInstance::getCurrentConvUid();
- LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
+ const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
+ LRCInstance::getCurrentConversationModel()->makePermanent(currentConvUid);
}
void
-MessagesAdapter::refuseInvitation()
+MessagesAdapter::refuseInvitation(const QString &convUid)
{
- auto convUid = LRCInstance::getCurrentConvUid();
- LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
+ const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
+ LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, false);
setInvitation(false);
}
void
-MessagesAdapter::blockConversation()
+MessagesAdapter::blockConversation(const QString &convUid)
{
- auto convUid = LRCInstance::getCurrentConvUid();
- LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
+ const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
+ LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, true);
setInvitation(false);
}
diff --git a/src/messagesadapter.h b/src/messagesadapter.h
index 6b520d2..aaf11da 100644
--- a/src/messagesadapter.h
+++ b/src/messagesadapter.h
@@ -41,9 +41,9 @@
/*
* JS Q_INVOKABLE.
*/
- Q_INVOKABLE void acceptInvitation();
- Q_INVOKABLE void refuseInvitation();
- Q_INVOKABLE void blockConversation();
+ Q_INVOKABLE void acceptInvitation(const QString &convUid = "");
+ Q_INVOKABLE void refuseInvitation(const QString &convUid = "");
+ Q_INVOKABLE void blockConversation(const QString &convUid = "");
Q_INVOKABLE void setNewMessagesContent(const QString &path);
Q_INVOKABLE void sendMessage(const QString &message);
Q_INVOKABLE void sendImage(const QString &message);
diff --git a/src/settingsview/components/BannedItemDelegate.qml b/src/settingsview/components/BannedItemDelegate.qml
index 0322bb0..999b494 100644
--- a/src/settingsview/components/BannedItemDelegate.qml
+++ b/src/settingsview/components/BannedItemDelegate.qml
@@ -173,7 +173,7 @@
buttonImageHeight: height - 8
buttonImageWidth: width - 8
- source: "qrc:/images/icons/ic_person_add_black_24dp_2x.png"
+ source: "qrc:/images/icons/person_add-24px.svg"
radius: height / 2
width: 25