mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-30 19:53:33 +02:00
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
This commit is contained in:
parent
6e3aacfc43
commit
968088785d
19 changed files with 418 additions and 525 deletions
Binary file not shown.
Before Width: | Height: | Size: 323 B |
Binary file not shown.
Before Width: | Height: | Size: 329 B |
2
qml.qrc
2
qml.qrc
|
@ -103,5 +103,7 @@
|
||||||
<file>src/mainview/components/RecordBox.qml</file>
|
<file>src/mainview/components/RecordBox.qml</file>
|
||||||
<file>src/commoncomponents/ElidedTextLabel.qml</file>
|
<file>src/commoncomponents/ElidedTextLabel.qml</file>
|
||||||
<file>src/mainview/components/SipInputPanel.qml</file>
|
<file>src/mainview/components/SipInputPanel.qml</file>
|
||||||
|
<file>src/commoncomponents/js/contextmenugenerator.js</file>
|
||||||
|
<file>src/commoncomponents/BaseContextMenu.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
<file>images/icons/ic_add_black_18dp_2x.png</file>
|
<file>images/icons/ic_add_black_18dp_2x.png</file>
|
||||||
<file>images/icons/info-24px.svg</file>
|
<file>images/icons/info-24px.svg</file>
|
||||||
<file>images/icons/backup-24px.svg</file>
|
<file>images/icons/backup-24px.svg</file>
|
||||||
|
<file>images/icons/check_box_outline_blank-24px.svg</file>
|
||||||
|
<file>images/icons/check_box-24px.svg</file>
|
||||||
<file>images/icons/devices-24px.svg</file>
|
<file>images/icons/devices-24px.svg</file>
|
||||||
<file>images/icons/ic_arrow_back_24px.svg</file>
|
<file>images/icons/ic_arrow_back_24px.svg</file>
|
||||||
<file>images/icons/ic_arrow_back_white_24dp.png</file>
|
<file>images/icons/ic_arrow_back_white_24dp.png</file>
|
||||||
|
@ -52,8 +54,6 @@
|
||||||
<file>images/icons/pause_circle_outline-24px.svg</file>
|
<file>images/icons/pause_circle_outline-24px.svg</file>
|
||||||
<file>images/icons/play_circle_outline-24px.svg</file>
|
<file>images/icons/play_circle_outline-24px.svg</file>
|
||||||
<file>images/icons/ic_pause_white_100px.png</file>
|
<file>images/icons/ic_pause_white_100px.png</file>
|
||||||
<file>images/icons/ic_person_add_black_24dp_2x.png</file>
|
|
||||||
<file>images/icons/ic_person_add_white_24dp.png</file>
|
|
||||||
<file>images/icons/ic_phone_24px.svg</file>
|
<file>images/icons/ic_phone_24px.svg</file>
|
||||||
<file>images/icons/ic_photo_camera_white_24dp_2x.png</file>
|
<file>images/icons/ic_photo_camera_white_24dp_2x.png</file>
|
||||||
<file>images/icons/ic_baseline-search-24px.svg</file>
|
<file>images/icons/ic_baseline-search-24px.svg</file>
|
||||||
|
|
47
src/commoncomponents/BaseContextMenu.qml
Normal file
47
src/commoncomponents/BaseContextMenu.qml
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,8 +35,7 @@ MenuItem {
|
||||||
property string iconSource: ""
|
property string iconSource: ""
|
||||||
property int preferredWidth: 220
|
property int preferredWidth: 220
|
||||||
property int preferredHeight: 48
|
property int preferredHeight: 48
|
||||||
property int topBorderWidth: 0
|
|
||||||
property int bottomBorderWidth: 0
|
|
||||||
property int leftBorderWidth: 0
|
property int leftBorderWidth: 0
|
||||||
property int rightBorderWidth: 0
|
property int rightBorderWidth: 0
|
||||||
|
|
||||||
|
@ -99,8 +98,6 @@ MenuItem {
|
||||||
id: contextMenuBackgroundRect
|
id: contextMenuBackgroundRect
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.topMargin: topBorderWidth
|
|
||||||
anchors.bottomMargin: bottomBorderWidth
|
|
||||||
anchors.leftMargin: leftBorderWidth
|
anchors.leftMargin: leftBorderWidth
|
||||||
anchors.rightMargin: rightBorderWidth
|
anchors.rightMargin: rightBorderWidth
|
||||||
|
|
||||||
|
@ -132,8 +129,8 @@ MenuItem {
|
||||||
commonBorder: false
|
commonBorder: false
|
||||||
lBorderwidth: leftBorderWidth
|
lBorderwidth: leftBorderWidth
|
||||||
rBorderwidth: rightBorderWidth
|
rBorderwidth: rightBorderWidth
|
||||||
tBorderwidth: topBorderWidth
|
tBorderwidth: 0
|
||||||
bBorderwidth: bottomBorderWidth
|
bBorderwidth: 0
|
||||||
borderColor: JamiTheme.tabbarBorderColor
|
borderColor: JamiTheme.tabbarBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
116
src/commoncomponents/js/contextmenugenerator.js
Normal file
116
src/commoncomponents/js/contextmenugenerator.js
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -230,7 +230,7 @@ Rectangle {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var rectPos = mapToItem(callStackViewWindow, optionsButton.x, optionsButton.y)
|
var rectPos = mapToItem(callStackViewWindow, optionsButton.x, optionsButton.y)
|
||||||
callViewContextMenu.activate()
|
callViewContextMenu.openMenu()
|
||||||
callViewContextMenu.x = rectPos.x + optionsButton.width/2 - callViewContextMenu.width/2
|
callViewContextMenu.x = rectPos.x + optionsButton.width/2 - callViewContextMenu.width/2
|
||||||
callViewContextMenu.y = rectPos.y - 12 - callViewContextMenu.height
|
callViewContextMenu.y = rectPos.y - 12 - callViewContextMenu.height
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
import QtGraphicalEffects 1.12
|
import QtGraphicalEffects 1.12
|
||||||
|
@ -24,61 +25,125 @@ import net.jami.Models 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
|
||||||
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
||||||
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
||||||
|
import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
|
||||||
|
|
||||||
Menu {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int generalMenuSeparatorCount: 0
|
|
||||||
property int commonBorderWidth: 1
|
|
||||||
|
|
||||||
signal pluginItemClicked
|
|
||||||
|
|
||||||
font.pointSize: JamiTheme.textFontSize+3
|
|
||||||
|
|
||||||
property bool isSIP: false
|
property bool isSIP: false
|
||||||
property bool isPaused: false
|
property bool isPaused: false
|
||||||
property bool isAudioOnly: false
|
property bool isAudioOnly: false
|
||||||
property bool isRecording: false
|
property bool isRecording: false
|
||||||
|
|
||||||
|
signal pluginItemClicked
|
||||||
signal transferCallButtonClicked
|
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()
|
var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Somehow, the map size is undefined, so use this instead.
|
* Somehow, the map size is undefined, so use this instead.
|
||||||
*/
|
*/
|
||||||
var mapSize = deviceContextMenuInfoMap["size"]
|
var mapSize = deviceContextMenuInfoMap["size"]
|
||||||
|
|
||||||
var count = 2
|
if (mapSize === 0)
|
||||||
for (var deviceName in deviceContextMenuInfoMap) {
|
|
||||||
if (deviceName === "size" || root.isAudioOnly)
|
|
||||||
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(
|
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
||||||
deviceName, deviceContextMenuInfoMap[deviceName],
|
qsTr("No video device"), false)
|
||||||
count === mapSize)
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
root.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
for (var deviceName in deviceContextMenuInfoMap) {
|
||||||
VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(root)
|
if (deviceName === "size")
|
||||||
|
continue
|
||||||
|
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
||||||
|
deviceName, deviceContextMenuInfoMap[deviceName])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
videoDeviceItem.itemName = "No video device"
|
|
||||||
VideoDeviceContextMenuItemCreation.removeCreatedItems()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JamiFileDialog {
|
JamiFileDialog {
|
||||||
|
@ -92,187 +157,13 @@ Menu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* All GeneralMenuItems should remain the same width / height.
|
|
||||||
*/
|
|
||||||
GeneralMenuItem {
|
|
||||||
id: holdCallButton
|
|
||||||
|
|
||||||
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: {
|
Component.onCompleted: {
|
||||||
generalMenuSeparatorCount++
|
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
||||||
}
|
VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(ContextMenuGenerator.getMenu())
|
||||||
}
|
|
||||||
|
|
||||||
GeneralMenuItem {
|
ContextMenuGenerator.getMenu().closed.connect(function (){
|
||||||
id: startRecordingItem
|
VideoDeviceContextMenuItemCreation.removeCreatedItems()
|
||||||
|
})
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: In the future we want to implement this
|
/* TODO: In the future we want to implement this
|
||||||
|
@ -289,31 +180,5 @@ Menu {
|
||||||
root.close()
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
import QtGraphicalEffects 1.12
|
import QtGraphicalEffects 1.12
|
||||||
|
@ -23,157 +23,88 @@ import net.jami.Models 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
Menu {
|
import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
|
||||||
id: contextMenu
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
property string responsibleAccountId: ""
|
property string responsibleAccountId: ""
|
||||||
property string responsibleConvUid: ""
|
property string responsibleConvUid: ""
|
||||||
|
property int contactType: Profile.Type.INVALID
|
||||||
property int generalMenuSeparatorCount: 0
|
|
||||||
property int commonBorderWidth: 1
|
|
||||||
font.pointSize: JamiTheme.menuFontSize
|
|
||||||
|
|
||||||
function openMenu(){
|
function openMenu(){
|
||||||
visible = true
|
ContextMenuGenerator.addMenuItem(qsTr("Start video call"),
|
||||||
visible = false
|
"qrc:/images/icons/ic_video_call_24px.svg",
|
||||||
visible = true
|
function (){
|
||||||
}
|
ConversationsAdapter.selectConversation(
|
||||||
|
responsibleAccountId,
|
||||||
GeneralMenuSeparator {
|
|
||||||
preferredWidth: startVideoCallItem.preferredWidth
|
|
||||||
preferredHeight: 8
|
|
||||||
separatorColor: "transparent"
|
|
||||||
Component.onCompleted: {
|
|
||||||
generalMenuSeparatorCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All GeneralMenuItems should remain the same width / height.
|
|
||||||
*/
|
|
||||||
GeneralMenuItem {
|
|
||||||
id: startVideoCallItem
|
|
||||||
|
|
||||||
itemName: qsTr("Start video call")
|
|
||||||
iconSource: "qrc:/images/icons/ic_video_call_24px.svg"
|
|
||||||
leftBorderWidth: commonBorderWidth
|
|
||||||
rightBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
contextMenu.close()
|
|
||||||
ConversationsAdapter.selectConversation(responsibleAccountId,
|
|
||||||
responsibleConvUid, false)
|
responsibleConvUid, false)
|
||||||
CallAdapter.placeCall()
|
CallAdapter.placeCall()
|
||||||
}
|
})
|
||||||
}
|
ContextMenuGenerator.addMenuItem(qsTr("Start audio call"),
|
||||||
|
"qrc:/images/icons/ic_phone_24px.svg",
|
||||||
GeneralMenuItem {
|
function (){
|
||||||
id: startAudioCallItem
|
ConversationsAdapter.selectConversation(
|
||||||
|
responsibleAccountId,
|
||||||
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)
|
responsibleConvUid, false)
|
||||||
CallAdapter.placeAudioOnlyCall()
|
CallAdapter.placeAudioOnlyCall()
|
||||||
}
|
})
|
||||||
}
|
ContextMenuGenerator.addMenuItem(qsTr("Clear conversation"),
|
||||||
|
"qrc:/images/icons/ic_clear_24px.svg",
|
||||||
GeneralMenuItem {
|
function (){
|
||||||
id: clearConversationItem
|
ClientWrapper.utilsAdaptor.clearConversationHistory(
|
||||||
|
responsibleAccountId,
|
||||||
itemName: qsTr("Clear conversation")
|
|
||||||
iconSource: "qrc:/images/icons/ic_clear_24px.svg"
|
|
||||||
leftBorderWidth: commonBorderWidth
|
|
||||||
rightBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
contextMenu.close()
|
|
||||||
ClientWrapper.utilsAdaptor.clearConversationHistory(responsibleAccountId,
|
|
||||||
responsibleConvUid)
|
responsibleConvUid)
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
GeneralMenuItem {
|
if (contactType === Profile.Type.RING || contactType === Profile.Type.SIP) {
|
||||||
id: removeContactItem
|
ContextMenuGenerator.addMenuItem(qsTr("Remove contact"),
|
||||||
|
"qrc:/images/icons/round-remove_circle-24px.svg",
|
||||||
itemName: qsTr("Remove contact")
|
function (){
|
||||||
iconSource: "qrc:/images/icons/round-remove_circle-24px.svg"
|
ClientWrapper.utilsAdaptor.removeConversation(
|
||||||
leftBorderWidth: commonBorderWidth
|
responsibleAccountId,
|
||||||
rightBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
contextMenu.close()
|
|
||||||
ClientWrapper.utilsAdaptor.removeConversation(responsibleAccountId,
|
|
||||||
responsibleConvUid)
|
responsibleConvUid)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralMenuSeparator {
|
if (contactType === Profile.Type.RING || contactType === Profile.Type.PENDING) {
|
||||||
preferredWidth: startVideoCallItem.preferredWidth
|
ContextMenuGenerator.addMenuSeparator()
|
||||||
preferredHeight: commonBorderWidth
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
if (contactType === Profile.Type.PENDING) {
|
||||||
generalMenuSeparatorCount++
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
GeneralMenuItem {
|
ContextMenuGenerator.addMenuSeparator()
|
||||||
id: blockContactItem
|
ContextMenuGenerator.addMenuItem(qsTr("Profile"),
|
||||||
|
"qrc:/images/icons/person-24px.svg",
|
||||||
itemName: qsTr("Block contact")
|
function (){
|
||||||
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()
|
userProfile.open()
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
root.height = ContextMenuGenerator.getMenu().height
|
||||||
|
root.width = ContextMenuGenerator.getMenu().width
|
||||||
|
ContextMenuGenerator.getMenu().open()
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralMenuSeparator {
|
|
||||||
preferredWidth: startVideoCallItem.preferredWidth
|
|
||||||
preferredHeight: 8
|
|
||||||
separatorColor: "transparent"
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
generalMenuSeparatorCount++
|
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
implicitWidth: startVideoCallItem.preferredWidth
|
|
||||||
implicitHeight: startVideoCallItem.preferredHeight
|
|
||||||
* (contextMenu.count - generalMenuSeparatorCount)
|
|
||||||
|
|
||||||
border.width: commonBorderWidth
|
|
||||||
border.color: JamiTheme.tabbarBorderColor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,10 @@ ListView {
|
||||||
conversationSmartListView.model.setAccount(accountId)
|
conversationSmartListView.model.setAccount(accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConversationSmartListContextMenu {
|
||||||
|
id: smartListContextMenu
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CallAdapter
|
target: CallAdapter
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ ItemDelegate {
|
||||||
itemSmartListBackground.color = JamiTheme.releaseColor
|
itemSmartListBackground.color = JamiTheme.releaseColor
|
||||||
}
|
}
|
||||||
if (mouse.button === Qt.RightButton) {
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
smartListContextMenu.parent = mouseAreaSmartListItemDelegate
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make menu pos at mouse.
|
* Make menu pos at mouse.
|
||||||
|
@ -191,6 +191,7 @@ ItemDelegate {
|
||||||
smartListContextMenu.y = relativeMousePos.y
|
smartListContextMenu.y = relativeMousePos.y
|
||||||
smartListContextMenu.responsibleAccountId = ClientWrapper.utilsAdaptor.getCurrAccId()
|
smartListContextMenu.responsibleAccountId = ClientWrapper.utilsAdaptor.getCurrAccId()
|
||||||
smartListContextMenu.responsibleConvUid = UID
|
smartListContextMenu.responsibleConvUid = UID
|
||||||
|
smartListContextMenu.contactType = ContactType
|
||||||
userProfile.responsibleConvUid = UID
|
userProfile.responsibleConvUid = UID
|
||||||
userProfile.aliasText = DisplayName
|
userProfile.aliasText = DisplayName
|
||||||
userProfile.registeredNameText = DisplayID
|
userProfile.registeredNameText = DisplayID
|
||||||
|
@ -225,8 +226,4 @@ ItemDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationSmartListContextMenu {
|
|
||||||
id: smartListContextMenu
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
* 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
|
* 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
|
* 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
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
import QtGraphicalEffects 1.12
|
import QtGraphicalEffects 1.12
|
||||||
|
@ -23,105 +24,46 @@ import net.jami.Models 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
|
||||||
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
|
||||||
|
|
||||||
Menu {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int generalMenuSeparatorCount: 0
|
|
||||||
property int commonBorderWidth: 1
|
|
||||||
font.pointSize: JamiTheme.textFontSize + 3
|
|
||||||
property var uri: ""
|
property var uri: ""
|
||||||
property var maximized: true
|
property var maximized: true
|
||||||
property var active: true
|
property var active: true
|
||||||
|
property var showHangup: false
|
||||||
|
property var showMaximize: false
|
||||||
|
property var showMinimize: false
|
||||||
|
|
||||||
function showHangup(show) {
|
function openMenu(){
|
||||||
if (show) {
|
if (showHangup)
|
||||||
hangupItem.visible = true
|
ContextMenuGenerator.addMenuItem(qsTr("Hang up"),
|
||||||
hangupItem.height = hangupItem.preferredHeight
|
"qrc:/images/icons/ic_call_end_white_24px.svg",
|
||||||
} else {
|
function (){
|
||||||
hangupItem.visible = false
|
|
||||||
hangupItem.height = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
CallAdapter.hangupCall(uri)
|
||||||
root.close()
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
GeneralMenuItem {
|
|
||||||
id: maximizeItem
|
|
||||||
|
|
||||||
itemName: qsTr("Maximize participant")
|
if (showMaximize)
|
||||||
iconSource: "qrc:/images/icons/open_in_full-24px.svg"
|
ContextMenuGenerator.addMenuItem(qsTr("Maximize participant"),
|
||||||
leftBorderWidth: commonBorderWidth
|
"qrc:/images/icons/open_in_full-24px.svg",
|
||||||
rightBorderWidth: commonBorderWidth
|
function (){
|
||||||
visible: !maximized
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
CallAdapter.maximizeParticipant(uri, active)
|
CallAdapter.maximizeParticipant(uri, active)
|
||||||
root.close()
|
})
|
||||||
}
|
if (showMinimize)
|
||||||
}
|
ContextMenuGenerator.addMenuItem(qsTr("Minimize participant"),
|
||||||
GeneralMenuItem {
|
"qrc:/images/icons/close_fullscreen-24px.svg",
|
||||||
id: minimizeItem
|
function (){
|
||||||
|
|
||||||
itemName: qsTr("Minimize participant")
|
|
||||||
iconSource: "qrc:/images/icons/close_fullscreen-24px.svg"
|
|
||||||
leftBorderWidth: commonBorderWidth
|
|
||||||
rightBorderWidth: commonBorderWidth
|
|
||||||
visible: maximized
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
CallAdapter.minimizeParticipant()
|
CallAdapter.minimizeParticipant()
|
||||||
root.close()
|
})
|
||||||
}
|
|
||||||
}
|
root.height = ContextMenuGenerator.getMenu().height
|
||||||
|
root.width = ContextMenuGenerator.getMenu().width
|
||||||
background: Rectangle {
|
ContextMenuGenerator.getMenu().open()
|
||||||
implicitWidth: hangupItem.preferredWidth
|
}
|
||||||
implicitHeight: hangupItem.preferredHeight * 3
|
|
||||||
|
Component.onCompleted: {
|
||||||
border.width: commonBorderWidth
|
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
||||||
border.color: JamiTheme.tabbarBorderColor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,18 +112,14 @@ Rectangle {
|
||||||
var layout = CallAdapter.getCurrentLayoutType()
|
var layout = CallAdapter.getCurrentLayoutType()
|
||||||
var showMaximized = layout !== 2
|
var showMaximized = layout !== 2
|
||||||
var showMinimized = !(layout === 0 || (layout === 1 && !active))
|
var showMinimized = !(layout === 0 || (layout === 1 && !active))
|
||||||
injectedContextMenu.showHangup(!root.isLocal)
|
injectedContextMenu.showHangup = !root.isLocal
|
||||||
injectedContextMenu.showMaximize(showMaximized)
|
injectedContextMenu.showMaximize = showMaximized
|
||||||
injectedContextMenu.showMinimize(showMinimized)
|
injectedContextMenu.showMinimize = showMinimized
|
||||||
injectedContextMenu.setHeight(
|
|
||||||
(root.isLocal ? 0 : 1)
|
|
||||||
+ (showMaximized ? 1 : 0)
|
|
||||||
+ (showMinimized ? 1 : 0))
|
|
||||||
injectedContextMenu.uri = uri
|
injectedContextMenu.uri = uri
|
||||||
injectedContextMenu.active = active
|
injectedContextMenu.active = active
|
||||||
injectedContextMenu.x = mousePos.x
|
injectedContextMenu.x = mousePos.x
|
||||||
injectedContextMenu.y = mousePos.y - injectedContextMenu.height
|
injectedContextMenu.y = mousePos.y - injectedContextMenu.height
|
||||||
injectedContextMenu.open()
|
injectedContextMenu.openMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
* Copyright (C) 2020 by Savoir-faire Linux
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||||
|
@ -16,24 +15,21 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.14
|
||||||
import net.jami.Models 1.0
|
import net.jami.Models 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take advantage of child can access parent's item (ex: contextMenu, commonBorderWidth).
|
* Menu item wrapper for video device checkable item.
|
||||||
*/
|
*/
|
||||||
GeneralMenuItem {
|
GeneralMenuItem {
|
||||||
id: videoCallPageContextMenuDeviceItem
|
id: videoCallPageContextMenuDeviceItem
|
||||||
|
|
||||||
property int contextMenuPreferredWidth: 250
|
property int contextMenuPreferredWidth: 250
|
||||||
|
|
||||||
leftBorderWidth: commonBorderWidth
|
|
||||||
rightBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
TextMetrics {
|
TextMetrics {
|
||||||
id: textMetrics
|
id: textMetrics
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
|
@ -54,7 +50,6 @@ GeneralMenuItem {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var deviceName = videoCallPageContextMenuDeviceItem.itemName
|
var deviceName = videoCallPageContextMenuDeviceItem.itemName
|
||||||
contextMenu.close()
|
|
||||||
AvAdapter.onVideoContextMenuDeviceItemClicked(deviceName)
|
AvAdapter.onVideoContextMenuDeviceItemClicked(deviceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,24 +40,28 @@ function setVideoContextMenuObject(obj) {
|
||||||
videoContextMenuObject = obj
|
videoContextMenuObject = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
function createVideoDeviceContextMenuItemObjects(deviceName, setChecked, last) {
|
function createVideoDeviceContextMenuItemObjects(deviceName, setChecked) {
|
||||||
|
|
||||||
videoDeviceContextMenuItemComponent = Qt.createComponent(
|
videoDeviceContextMenuItemComponent = Qt.createComponent(
|
||||||
"../components/VideoCallPageContextMenuDeviceItem.qml")
|
"../components/VideoCallPageContextMenuDeviceItem.qml")
|
||||||
if (videoDeviceContextMenuItemComponent.status === Component.Ready)
|
if (videoDeviceContextMenuItemComponent.status === Component.Ready)
|
||||||
finishCreation(deviceName, setChecked, last)
|
finishCreation(deviceName, setChecked)
|
||||||
else if (videoDeviceContextMenuItemComponent.status === Component.Error)
|
else if (videoDeviceContextMenuItemComponent.status === Component.Error)
|
||||||
console.log("Error loading component:",
|
console.log("Error loading component:",
|
||||||
videoDeviceContextMenuItemComponent.errorString())
|
videoDeviceContextMenuItemComponent.errorString())
|
||||||
}
|
}
|
||||||
|
|
||||||
function finishCreation(deviceName, setChecked, last) {
|
function finishCreation(deviceName, setChecked) {
|
||||||
videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject()
|
videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject()
|
||||||
if (videoDeviceContextMenuItemObject === null) {
|
if (videoDeviceContextMenuItemObject === null) {
|
||||||
// Error Handling.
|
// Error Handling.
|
||||||
console.log("Error creating video context menu object")
|
console.log("Error creating video context menu object")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
videoDeviceContextMenuItemObject.leftBorderWidth =
|
||||||
|
videoContextMenuObject.commonBorderWidth
|
||||||
|
videoDeviceContextMenuItemObject.rightBorderWidth =
|
||||||
|
videoContextMenuObject.commonBorderWidth
|
||||||
videoDeviceContextMenuItemObject.itemName = deviceName
|
videoDeviceContextMenuItemObject.itemName = deviceName
|
||||||
videoDeviceContextMenuItemObject.checkable = true
|
videoDeviceContextMenuItemObject.checkable = true
|
||||||
videoDeviceContextMenuItemObject.checked = setChecked
|
videoDeviceContextMenuItemObject.checked = setChecked
|
||||||
|
@ -68,14 +72,11 @@ function finishCreation(deviceName, setChecked, last) {
|
||||||
* Push into the storage array, and insert it into context menu.
|
* Push into the storage array, and insert it into context menu.
|
||||||
*/
|
*/
|
||||||
itemArray.push(videoDeviceContextMenuItemObject)
|
itemArray.push(videoDeviceContextMenuItemObject)
|
||||||
videoContextMenuObject.insertItem(3 /* The button is at pos 3 in the menu */, videoDeviceContextMenuItemObject)
|
videoContextMenuObject.addItem(videoDeviceContextMenuItemObject)
|
||||||
|
|
||||||
|
videoDeviceContextMenuItemObject.clicked.connect(function () {
|
||||||
/*
|
videoContextMenuObject.close()
|
||||||
* If it is the last device context menu item, open the context menu.
|
})
|
||||||
*/
|
|
||||||
if (last)
|
|
||||||
videoContextMenuObject.open()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCreatedItems() {
|
function removeCreatedItems() {
|
||||||
|
|
|
@ -633,24 +633,24 @@ MessagesAdapter::contactIsComposing(const QString &uid, const QString &contactUr
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::acceptInvitation()
|
MessagesAdapter::acceptInvitation(const QString &convUid)
|
||||||
{
|
{
|
||||||
const auto convUid = LRCInstance::getCurrentConvUid();
|
const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
|
||||||
LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
|
LRCInstance::getCurrentConversationModel()->makePermanent(currentConvUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::refuseInvitation()
|
MessagesAdapter::refuseInvitation(const QString &convUid)
|
||||||
{
|
{
|
||||||
auto convUid = LRCInstance::getCurrentConvUid();
|
const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
|
||||||
LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
|
LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, false);
|
||||||
setInvitation(false);
|
setInvitation(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::blockConversation()
|
MessagesAdapter::blockConversation(const QString &convUid)
|
||||||
{
|
{
|
||||||
auto convUid = LRCInstance::getCurrentConvUid();
|
const auto currentConvUid = convUid.isEmpty() ? LRCInstance::getCurrentConvUid() : convUid;
|
||||||
LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
|
LRCInstance::getCurrentConversationModel()->removeConversation(currentConvUid, true);
|
||||||
setInvitation(false);
|
setInvitation(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,9 @@ public:
|
||||||
/*
|
/*
|
||||||
* JS Q_INVOKABLE.
|
* JS Q_INVOKABLE.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void acceptInvitation();
|
Q_INVOKABLE void acceptInvitation(const QString &convUid = "");
|
||||||
Q_INVOKABLE void refuseInvitation();
|
Q_INVOKABLE void refuseInvitation(const QString &convUid = "");
|
||||||
Q_INVOKABLE void blockConversation();
|
Q_INVOKABLE void blockConversation(const QString &convUid = "");
|
||||||
Q_INVOKABLE void setNewMessagesContent(const QString &path);
|
Q_INVOKABLE void setNewMessagesContent(const QString &path);
|
||||||
Q_INVOKABLE void sendMessage(const QString &message);
|
Q_INVOKABLE void sendMessage(const QString &message);
|
||||||
Q_INVOKABLE void sendImage(const QString &message);
|
Q_INVOKABLE void sendImage(const QString &message);
|
||||||
|
|
|
@ -173,7 +173,7 @@ ItemDelegate {
|
||||||
buttonImageHeight: height - 8
|
buttonImageHeight: height - 8
|
||||||
buttonImageWidth: width - 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
|
radius: height / 2
|
||||||
width: 25
|
width: 25
|
||||||
|
|
Loading…
Add table
Reference in a new issue