mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
misc: refinement for various context menus and share actions
Change-Id: I4e6fff2c74ce6ace1464fa6a4569e4b3fbfae68b
This commit is contained in:
parent
8325a6ef51
commit
e1fbb3a7d4
19 changed files with 547 additions and 667 deletions
9
qml.qrc
9
qml.qrc
|
@ -17,13 +17,9 @@
|
||||||
<file>src/commoncomponents/PushButton.qml</file>
|
<file>src/commoncomponents/PushButton.qml</file>
|
||||||
<file>src/commoncomponents/JamiFileDialog.qml</file>
|
<file>src/commoncomponents/JamiFileDialog.qml</file>
|
||||||
<file>src/commoncomponents/TintedButton.qml</file>
|
<file>src/commoncomponents/TintedButton.qml</file>
|
||||||
<file>src/commoncomponents/GeneralMenuItem.qml</file>
|
|
||||||
<file>src/commoncomponents/GeneralMenuSeparator.qml</file>
|
|
||||||
<file>src/commoncomponents/AccountMigrationDialog.qml</file>
|
<file>src/commoncomponents/AccountMigrationDialog.qml</file>
|
||||||
<file>src/commoncomponents/MaterialButton.qml</file>
|
<file>src/commoncomponents/MaterialButton.qml</file>
|
||||||
<file>src/commoncomponents/ElidedTextLabel.qml</file>
|
<file>src/commoncomponents/ElidedTextLabel.qml</file>
|
||||||
<file>src/commoncomponents/js/contextmenugenerator.js</file>
|
|
||||||
<file>src/commoncomponents/BaseContextMenu.qml</file>
|
|
||||||
<file>src/commoncomponents/SpinnerButton.qml</file>
|
<file>src/commoncomponents/SpinnerButton.qml</file>
|
||||||
<file>src/commoncomponents/UsernameLineEdit.qml</file>
|
<file>src/commoncomponents/UsernameLineEdit.qml</file>
|
||||||
<file>src/commoncomponents/Scaffold.qml</file>
|
<file>src/commoncomponents/Scaffold.qml</file>
|
||||||
|
@ -125,7 +121,6 @@
|
||||||
<file>src/mainview/components/RecordBox.qml</file>
|
<file>src/mainview/components/RecordBox.qml</file>
|
||||||
<file>src/mainview/components/SipInputPanel.qml</file>
|
<file>src/mainview/components/SipInputPanel.qml</file>
|
||||||
<file>src/mainview/components/ParticipantOverlayMenu.qml</file>
|
<file>src/mainview/components/ParticipantOverlayMenu.qml</file>
|
||||||
<file>src/mainview/js/videodevicecontextmenuitemcreation.js</file>
|
|
||||||
<file>src/mainview/js/selectscreenwindowcreation.js</file>
|
<file>src/mainview/js/selectscreenwindowcreation.js</file>
|
||||||
<file>src/mainview/js/screenrubberbandcreation.js</file>
|
<file>src/mainview/js/screenrubberbandcreation.js</file>
|
||||||
<file>src/mainview/js/contactpickercreation.js</file>
|
<file>src/mainview/js/contactpickercreation.js</file>
|
||||||
|
@ -145,5 +140,9 @@
|
||||||
<file>src/mainview/components/ParticipantCallInStatusView.qml</file>
|
<file>src/mainview/components/ParticipantCallInStatusView.qml</file>
|
||||||
<file>src/settingsview/components/TroubleshootSettings.qml</file>
|
<file>src/settingsview/components/TroubleshootSettings.qml</file>
|
||||||
<file>src/settingsview/components/LogsView.qml</file>
|
<file>src/settingsview/components/LogsView.qml</file>
|
||||||
|
<file>src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml</file>
|
||||||
|
<file>src/commoncomponents/contextmenu/BaseContextMenu.qml</file>
|
||||||
|
<file>src/commoncomponents/contextmenu/GeneralMenuItem.qml</file>
|
||||||
|
<file>src/commoncomponents/contextmenu/GeneralMenuSeparator.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -46,33 +46,6 @@ AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap
|
|
||||||
AvAdapter::populateVideoDeviceContextMenuItem()
|
|
||||||
{
|
|
||||||
auto activeDevice = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a list of video input devices.
|
|
||||||
*/
|
|
||||||
QVariantMap deciveContextMenuNeededInfo;
|
|
||||||
auto devices = lrcInstance_->avModel().getDevices();
|
|
||||||
for (int i = 0; i < devices.size(); i++) {
|
|
||||||
try {
|
|
||||||
auto settings = lrcInstance_->avModel().getDeviceSettings(devices[i]);
|
|
||||||
deciveContextMenuNeededInfo[settings.name] = QVariant(settings.id == activeDevice);
|
|
||||||
} catch (...) {
|
|
||||||
qDebug().noquote() << "Error in getting device settings";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add size parameter into the map since in qml there is no way to get the size.
|
|
||||||
*/
|
|
||||||
deciveContextMenuNeededInfo["size"] = QVariant(deciveContextMenuNeededInfo.size());
|
|
||||||
|
|
||||||
return deciveContextMenuNeededInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AvAdapter::selectVideoInputDeviceByName(const QString& deviceName)
|
AvAdapter::selectVideoInputDeviceByName(const QString& deviceName)
|
||||||
{
|
{
|
||||||
|
@ -242,7 +215,7 @@ AvAdapter::shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned heig
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AvAdapter::stopSharingScreen()
|
AvAdapter::stopSharing()
|
||||||
{
|
{
|
||||||
auto callId = getCurrentCallId();
|
auto callId = getCurrentCallId();
|
||||||
if (!callId.isEmpty())
|
if (!callId.isEmpty())
|
||||||
|
|
|
@ -45,9 +45,6 @@ Q_SIGNALS:
|
||||||
protected:
|
protected:
|
||||||
void safeInit() override {};
|
void safeInit() override {};
|
||||||
|
|
||||||
// Return needed info for populating video device context menu item.
|
|
||||||
Q_INVOKABLE QVariantMap populateVideoDeviceContextMenuItem();
|
|
||||||
|
|
||||||
// switch preview video input by device name
|
// switch preview video input by device name
|
||||||
Q_INVOKABLE void selectVideoInputDeviceByName(const QString& deviceName);
|
Q_INVOKABLE void selectVideoInputDeviceByName(const QString& deviceName);
|
||||||
|
|
||||||
|
@ -72,8 +69,8 @@ protected:
|
||||||
// Select screen area to display (from all screens).
|
// Select screen area to display (from all screens).
|
||||||
Q_INVOKABLE void shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned height);
|
Q_INVOKABLE void shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned height);
|
||||||
|
|
||||||
// Stop sharing the screen
|
// Stop sharing the screen or file
|
||||||
Q_INVOKABLE void stopSharingScreen();
|
Q_INVOKABLE void stopSharing();
|
||||||
|
|
||||||
Q_INVOKABLE void startAudioMeter(bool async);
|
Q_INVOKABLE void startAudioMeter(bool async);
|
||||||
Q_INVOKABLE void stopAudioMeter(bool async);
|
Q_INVOKABLE void stopAudioMeter(bool async);
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.14
|
|
||||||
|
|
||||||
import net.jami.Constants 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
|
|
||||||
|
|
||||||
modal: true
|
|
||||||
Overlay.modal: Rectangle {
|
|
||||||
color: "transparent"
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: investigate
|
|
||||||
function openMenu(){
|
|
||||||
visible = true
|
|
||||||
visible = false
|
|
||||||
visible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
id: container
|
|
||||||
|
|
||||||
implicitWidth: menuItemsPreferredWidth
|
|
||||||
implicitHeight: menuItemsPreferredHeight
|
|
||||||
* (root.count - generalMenuSeparatorCount)
|
|
||||||
|
|
||||||
border.width: commonBorderWidth
|
|
||||||
border.color: JamiTheme.tabbarBorderColor
|
|
||||||
color: JamiTheme.backgroundColor
|
|
||||||
|
|
||||||
layer.enabled: true
|
|
||||||
layer.effect: DropShadow {
|
|
||||||
z: -1
|
|
||||||
horizontalOffset: 3.0
|
|
||||||
verticalOffset: 3.0
|
|
||||||
radius: 16.0
|
|
||||||
samples: 16
|
|
||||||
color: JamiTheme.shadowColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,49 +24,69 @@ import net.jami.Models 1.0
|
||||||
import net.jami.Adapters 1.0
|
import net.jami.Adapters 1.0
|
||||||
import net.jami.Constants 1.0
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
import "js/contextmenugenerator.js" as ContextMenuGenerator
|
import "contextmenu"
|
||||||
|
|
||||||
Item {
|
ContextMenuAutoLoader {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
function openMenu(lineEditObj, mouseEvent) {
|
// lineEdit (TextEdit) selection will be lost when menu is opened
|
||||||
ContextMenuGenerator.initMenu(Qt.size(150, 25), 2)
|
property var lineEditObj
|
||||||
|
property var selectionStart
|
||||||
|
property var selectionEnd
|
||||||
|
|
||||||
if (lineEditObj.selectedText.length) {
|
property list<GeneralMenuItem> menuItems: [
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Copy"),
|
GeneralMenuItem {
|
||||||
"",
|
id: copy
|
||||||
function (){
|
|
||||||
lineEditObj.copy()
|
|
||||||
})
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Cut"),
|
canTrigger: lineEditObj.selectedText.length
|
||||||
"",
|
itemName: JamiStrings.copy
|
||||||
function (){
|
onClicked: {
|
||||||
lineEditObj.cut()
|
lineEditObj.copy()
|
||||||
})
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: cut
|
||||||
|
|
||||||
|
canTrigger: lineEditObj.selectedText.length
|
||||||
|
itemName: JamiStrings.cut
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
lineEditObj.cut()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: paste
|
||||||
|
|
||||||
|
itemName: JamiStrings.paste
|
||||||
|
onClicked: {
|
||||||
|
lineEditObj.paste()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Paste"),
|
function openMenuAt(mouseEvent) {
|
||||||
"",
|
x = mouseEvent.x
|
||||||
function (){
|
y = mouseEvent.y
|
||||||
lineEditObj.paste()
|
|
||||||
})
|
|
||||||
|
|
||||||
root.height = ContextMenuGenerator.getMenu().height
|
selectionStart = lineEditObj.selectionStart
|
||||||
root.width = ContextMenuGenerator.getMenu().width
|
selectionEnd = lineEditObj.selectionEnd
|
||||||
ContextMenuGenerator.getMenu().x = mouseEvent.x
|
|
||||||
ContextMenuGenerator.getMenu().y = mouseEvent.y
|
|
||||||
|
|
||||||
// lineEdit (TextEdit) selection will be lost when menu is opened
|
root.openMenu()
|
||||||
var selectionStartTemp = lineEditObj.selectionStart
|
|
||||||
var selectionEndTemp = lineEditObj.selectionEnd
|
|
||||||
|
|
||||||
ContextMenuGenerator.getMenu().open()
|
lineEditObj.select(selectionStart, selectionEnd)
|
||||||
|
|
||||||
lineEditObj.select(selectionStartTemp, selectionEndTemp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
contextMenuItemPreferredHeight: JamiTheme.lineEditContextMenuItemsHeight
|
||||||
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
contextMenuItemPreferredWidth: JamiTheme.lineEditContextMenuItemsWidth
|
||||||
|
contextMenuSeparatorPreferredHeight: JamiTheme.lineEditContextMenuSeparatorsHeight
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.item
|
||||||
|
enabled: root.status === Loader.Ready
|
||||||
|
function onOpened() {
|
||||||
|
lineEditObj.select(selectionStart, selectionEnd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: menuItemsToLoad = menuItems
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ TextField {
|
||||||
|
|
||||||
LineEditContextMenu {
|
LineEditContextMenu {
|
||||||
id: lineEditContextMenu
|
id: lineEditContextMenu
|
||||||
|
|
||||||
|
lineEditObj: root
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -142,6 +144,6 @@ TextField {
|
||||||
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
if (event.button == Qt.RightButton)
|
if (event.button == Qt.RightButton)
|
||||||
lineEditContextMenu.openMenu(root, event)
|
lineEditContextMenu.openMenuAt(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
116
src/commoncomponents/contextmenu/BaseContextMenu.qml
Normal file
116
src/commoncomponents/contextmenu/BaseContextMenu.qml
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtGraphicalEffects 1.14
|
||||||
|
|
||||||
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int menuPreferredWidth: 0
|
||||||
|
property int menuItemsPreferredHeight: 0
|
||||||
|
property int menuSeparatorPreferredHeight: 0
|
||||||
|
|
||||||
|
property GeneralMenuSeparator menuTopBorder: GeneralMenuSeparator {
|
||||||
|
separatorPreferredWidth: menuPreferredWidth ?
|
||||||
|
menuPreferredWidth : JamiTheme.menuItemsPreferredWidth
|
||||||
|
separatorPreferredHeight: menuSeparatorPreferredHeight ?
|
||||||
|
menuSeparatorPreferredHeight : JamiTheme.menuBorderPreferredHeight
|
||||||
|
separatorColor: "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
property GeneralMenuSeparator menuBottomBorder: GeneralMenuSeparator {
|
||||||
|
separatorPreferredWidth: menuPreferredWidth ?
|
||||||
|
menuPreferredWidth : JamiTheme.menuItemsPreferredWidth
|
||||||
|
separatorPreferredHeight: menuSeparatorPreferredHeight ?
|
||||||
|
menuSeparatorPreferredHeight : JamiTheme.menuBorderPreferredHeight
|
||||||
|
separatorColor: "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
property var generalMenuSeparatorList: []
|
||||||
|
|
||||||
|
function loadMenuItems(menuItems) {
|
||||||
|
root.addItem(menuTopBorder)
|
||||||
|
|
||||||
|
for (var i = 0; i < menuItems.length; ++i) {
|
||||||
|
if (menuItems[i].canTrigger) {
|
||||||
|
menuItems[i].parentMenu = root
|
||||||
|
root.addItem(menuItems[i])
|
||||||
|
|
||||||
|
if (menuPreferredWidth)
|
||||||
|
menuItems[i].itemPreferredWidth = menuPreferredWidth
|
||||||
|
if (menuItemsPreferredHeight)
|
||||||
|
menuItems[i].itemPreferredHeight = menuItemsPreferredHeight
|
||||||
|
}
|
||||||
|
if (menuItems[i].addMenuSeparatorAfter) {
|
||||||
|
// If the QML file to be loaded is a local file,
|
||||||
|
// you could omit the finishCreation() function
|
||||||
|
var menuSeparatorComponent = Qt.createComponent(
|
||||||
|
"GeneralMenuSeparator.qml",
|
||||||
|
Component.PreferSynchronous, root)
|
||||||
|
var menuSeparatorComponentObj = menuSeparatorComponent.createObject()
|
||||||
|
generalMenuSeparatorList.push(menuSeparatorComponentObj)
|
||||||
|
root.addItem(menuSeparatorComponentObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
root.addItem(menuBottomBorder)
|
||||||
|
|
||||||
|
root.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
modal: true
|
||||||
|
Overlay.modal: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
font.pointSize: JamiTheme.menuFontSize
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
id: container
|
||||||
|
|
||||||
|
implicitWidth: menuPreferredWidth ? menuPreferredWidth : JamiTheme.menuItemsPreferredWidth
|
||||||
|
|
||||||
|
border.width: JamiTheme.menuItemsCommonBorderWidth
|
||||||
|
border.color: JamiTheme.tabbarBorderColor
|
||||||
|
color: JamiTheme.backgroundColor
|
||||||
|
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: DropShadow {
|
||||||
|
z: -1
|
||||||
|
horizontalOffset: 3.0
|
||||||
|
verticalOffset: 3.0
|
||||||
|
radius: 16.0
|
||||||
|
samples: 16
|
||||||
|
color: JamiTheme.shadowColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
for (var i = 0; i < generalMenuSeparatorList.length; ++i) {
|
||||||
|
generalMenuSeparatorList[i].destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml
Normal file
67
src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.14
|
||||||
|
|
||||||
|
import net.jami.Models 1.0
|
||||||
|
import net.jami.Adapters 1.0
|
||||||
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
|
import "../../commoncomponents"
|
||||||
|
import "../../commoncomponents/contextmenu"
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// Cannot have menuItemsToLoad directly assigned as list<GeneralMenuItem>
|
||||||
|
// https://stackoverflow.com/questions/26733011/how-to-declare-list-property-in-qml
|
||||||
|
property var menuItemsToLoad
|
||||||
|
property int contextMenuItemPreferredWidth: 0
|
||||||
|
property int contextMenuItemPreferredHeight: 0
|
||||||
|
property int contextMenuSeparatorPreferredHeight: 0
|
||||||
|
|
||||||
|
function openMenu() {
|
||||||
|
root.active = true
|
||||||
|
root.sourceComponent = menuComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.item
|
||||||
|
enabled: root.status === Loader.Ready
|
||||||
|
function onClosed() {
|
||||||
|
root.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: menuComponent
|
||||||
|
|
||||||
|
BaseContextMenu {
|
||||||
|
id: contextMenu
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
contextMenu.menuPreferredWidth = contextMenuItemPreferredWidth
|
||||||
|
contextMenu.menuItemsPreferredHeight = contextMenuItemPreferredHeight
|
||||||
|
contextMenu.menuSeparatorPreferredHeight = contextMenuSeparatorPreferredHeight
|
||||||
|
contextMenu.loadMenuItems(menuItemsToLoad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ import QtGraphicalEffects 1.14
|
||||||
|
|
||||||
import net.jami.Constants 1.0
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
|
import "../../commoncomponents"
|
||||||
|
|
||||||
// General menu item.
|
// General menu item.
|
||||||
// Can control top, bottom, left, right border width.
|
// Can control top, bottom, left, right border width.
|
||||||
// Use onClicked slot to simulate item click event.
|
// Use onClicked slot to simulate item click event.
|
||||||
|
@ -31,13 +33,16 @@ MenuItem {
|
||||||
id: menuItem
|
id: menuItem
|
||||||
|
|
||||||
property string itemName: ""
|
property string itemName: ""
|
||||||
property string iconSource: ""
|
property alias iconSource: contextMenuItemImage.source
|
||||||
property string iconColor: ""
|
property string iconColor: ""
|
||||||
property int preferredWidth: 220
|
property bool canTrigger: true
|
||||||
property int preferredHeight: 48
|
property bool addMenuSeparatorAfter: false
|
||||||
|
property BaseContextMenu parentMenu
|
||||||
|
|
||||||
property int leftBorderWidth: 0
|
property int itemPreferredWidth: JamiTheme.menuItemsPreferredWidth
|
||||||
property int rightBorderWidth: 0
|
property int itemPreferredHeight: JamiTheme.menuItemsPreferredHeight
|
||||||
|
property int leftBorderWidth: JamiTheme.menuItemsCommonBorderWidth
|
||||||
|
property int rightBorderWidth: JamiTheme.menuItemsCommonBorderWidth
|
||||||
|
|
||||||
signal clicked
|
signal clicked
|
||||||
|
|
||||||
|
@ -57,29 +62,25 @@ MenuItem {
|
||||||
ResponsiveImage {
|
ResponsiveImage {
|
||||||
id: contextMenuItemImage
|
id: contextMenuItemImage
|
||||||
|
|
||||||
anchors.left: menuItemContentRect.left
|
anchors.left: status === Image.Ready ? menuItemContentRect.left : undefined
|
||||||
anchors.leftMargin: (visible ? 24 : 0)
|
anchors.leftMargin: (status === Image.Ready ? 24 : 0)
|
||||||
anchors.verticalCenter: menuItemContentRect.verticalCenter
|
anchors.verticalCenter: menuItemContentRect.verticalCenter
|
||||||
|
|
||||||
width: (visible ? 24 : 0)
|
color: iconColor !== "" ? iconColor : JamiTheme.textColor
|
||||||
height: (visible ? 24 : 0)
|
|
||||||
color: iconColor !== ""? iconColor : JamiTheme.textColor
|
|
||||||
|
|
||||||
visible: false
|
smooth: true
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: contextMenuItemText
|
id: contextMenuItemText
|
||||||
|
|
||||||
anchors.left: contextMenuItemImage.right
|
anchors.left: contextMenuItemImage.status === Image.Ready ?
|
||||||
anchors.leftMargin: contextMenuItemImage.visible ? 20 : 5
|
contextMenuItemImage.right : menuItemContentRect.left
|
||||||
|
anchors.leftMargin: contextMenuItemImage.status === Image.Ready ? 20 : 10
|
||||||
anchors.verticalCenter: menuItemContentRect.verticalCenter
|
anchors.verticalCenter: menuItemContentRect.verticalCenter
|
||||||
|
|
||||||
width: contextMenuItemImage.visible ?
|
height: itemPreferredHeight
|
||||||
(preferredWidth - contextMenuItemImage.width - 58) :
|
|
||||||
preferredWidth - 24
|
|
||||||
height: 30
|
|
||||||
|
|
||||||
text: itemName
|
text: itemName
|
||||||
color: JamiTheme.textColor
|
color: JamiTheme.textColor
|
||||||
|
@ -89,7 +90,10 @@ MenuItem {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: menuItem.clicked()
|
onReleased: {
|
||||||
|
menuItem.clicked()
|
||||||
|
parentMenu.close()
|
||||||
|
}
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
|
@ -103,13 +107,6 @@ MenuItem {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
onIconSourceChanged: {
|
|
||||||
if (iconSource !== "") {
|
|
||||||
contextMenuItemImage.source = iconSource
|
|
||||||
contextMenuItemImage.visible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
highlighted: true
|
highlighted: true
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
|
@ -119,8 +116,8 @@ MenuItem {
|
||||||
anchors.leftMargin: leftBorderWidth
|
anchors.leftMargin: leftBorderWidth
|
||||||
anchors.rightMargin: rightBorderWidth
|
anchors.rightMargin: rightBorderWidth
|
||||||
|
|
||||||
implicitWidth: preferredWidth
|
implicitWidth: itemPreferredWidth
|
||||||
implicitHeight: preferredHeight
|
implicitHeight: itemPreferredHeight
|
||||||
|
|
||||||
border.width: 0
|
border.width: 0
|
||||||
|
|
|
@ -24,16 +24,16 @@ import net.jami.Constants 1.0
|
||||||
MenuSeparator {
|
MenuSeparator {
|
||||||
id: menuSeparator
|
id: menuSeparator
|
||||||
|
|
||||||
property int preferredWidth: 10
|
property int separatorPreferredWidth: JamiTheme.menuItemsPreferredWidth
|
||||||
property int preferredHeight: 1
|
property int separatorPreferredHeight: 1
|
||||||
property string separatorColor: JamiTheme.tabbarBorderColor
|
property string separatorColor: JamiTheme.tabbarBorderColor
|
||||||
|
|
||||||
padding: 0
|
padding: 0
|
||||||
topPadding: 1
|
topPadding: 1
|
||||||
bottomPadding: 1
|
bottomPadding: 1
|
||||||
contentItem: Rectangle {
|
contentItem: Rectangle {
|
||||||
implicitWidth: preferredWidth
|
implicitWidth: separatorPreferredWidth
|
||||||
implicitHeight: preferredHeight
|
implicitHeight: separatorPreferredHeight
|
||||||
color: separatorColor
|
color: separatorColor
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 = []
|
|
||||||
var menuDefaultSeparatorHeight = 8
|
|
||||||
|
|
||||||
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(menuDefaultSeparatorHeight, "transparent")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function initMenu(preferedMenuItemSize, defaultSeparatorHeight) {
|
|
||||||
// Clear any existing items in the menu.
|
|
||||||
for (var i = 0; i < menuItemList.length; i++) {
|
|
||||||
baseContextMenuObject.removeItem(menuItemList[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preferedMenuItemSize) {
|
|
||||||
baseContextMenuObject.menuItemsPreferredWidth = preferedMenuItemSize.width
|
|
||||||
baseContextMenuObject.menuItemsPreferredHeight = preferedMenuItemSize.height
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultSeparatorHeight)
|
|
||||||
menuDefaultSeparatorHeight = defaultSeparatorHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
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, iconColor) {
|
|
||||||
if (!baseContextMenuObject.count) {
|
|
||||||
// Add default separator at the top.
|
|
||||||
addMenuSeparator(menuDefaultSeparatorHeight, "transparent")
|
|
||||||
}
|
|
||||||
|
|
||||||
var menuItemObject
|
|
||||||
var menuItemComponent = Qt.createComponent("../GeneralMenuItem.qml")
|
|
||||||
if (menuItemComponent.status === Component.Ready) {
|
|
||||||
menuItemObject = menuItemComponent.createObject(
|
|
||||||
null, {
|
|
||||||
"itemName": itemName,
|
|
||||||
"iconSource": iconSource,
|
|
||||||
"iconColor": iconColor,
|
|
||||||
"preferredWidth": baseContextMenuObject.menuItemsPreferredWidth,
|
|
||||||
"preferredHeight": baseContextMenuObject.menuItemsPreferredHeight,
|
|
||||||
"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 () {
|
|
||||||
var callback = function () {
|
|
||||||
onClickedCallback()
|
|
||||||
baseContextMenuObject.onVisibleChanged.disconnect(callback)
|
|
||||||
baseContextMenuObject.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
baseContextMenuObject.onVisibleChanged.connect(callback)
|
|
||||||
baseContextMenuObject.visible = false
|
|
||||||
})
|
|
||||||
menuItemObject.icon.color = "green"
|
|
||||||
|
|
||||||
baseContextMenuObject.addItem(menuItemObject)
|
|
||||||
|
|
||||||
menuItemList.push(menuItemObject)
|
|
||||||
} else {
|
|
||||||
// Error handling.
|
|
||||||
console.log("Error creating object")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMenu() {
|
|
||||||
return baseContextMenuObject
|
|
||||||
}
|
|
|
@ -199,6 +199,19 @@ Item {
|
||||||
property string moreOptions: qsTr("More options")
|
property string moreOptions: qsTr("More options")
|
||||||
property string mosaic: qsTr("Mosaic")
|
property string mosaic: qsTr("Mosaic")
|
||||||
|
|
||||||
|
// LineEditContextMenu
|
||||||
|
property string copy: qsTr("Copy")
|
||||||
|
property string cut: qsTr("Cut")
|
||||||
|
property string paste: qsTr("Paste")
|
||||||
|
|
||||||
|
// ConversationContextMenu
|
||||||
|
property string startVideoCall: qsTr("Start video call")
|
||||||
|
property string startAudioCall: qsTr("Start audio call")
|
||||||
|
property string clearConversation: qsTr("Clear conversation")
|
||||||
|
property string removeContact: qsTr("Remove contact")
|
||||||
|
property string blockContact: qsTr("Block contact")
|
||||||
|
property string contactDetails: qsTr("Contact details")
|
||||||
|
|
||||||
// CallViewContextMenu
|
// CallViewContextMenu
|
||||||
property string hold: qsTr("Hold")
|
property string hold: qsTr("Hold")
|
||||||
property string sipInputPanel: qsTr("Sip input panel")
|
property string sipInputPanel: qsTr("Sip input panel")
|
||||||
|
@ -208,7 +221,7 @@ Item {
|
||||||
property string exitFullScreen: qsTr("Exit full screen")
|
property string exitFullScreen: qsTr("Exit full screen")
|
||||||
property string fullScreen: qsTr("Full screen")
|
property string fullScreen: qsTr("Full screen")
|
||||||
property string shareScreen: qsTr("Share screen")
|
property string shareScreen: qsTr("Share screen")
|
||||||
property string stopSharingScreen: qsTr("Stop sharing screen")
|
property string stopSharing: qsTr("Stop sharing screen or file")
|
||||||
property string shareScreenArea: qsTr("Share screen area")
|
property string shareScreenArea: qsTr("Share screen area")
|
||||||
property string shareFile: qsTr("Share file")
|
property string shareFile: qsTr("Share file")
|
||||||
property string viewPlugin: qsTr("View plugin")
|
property string viewPlugin: qsTr("View plugin")
|
||||||
|
|
|
@ -34,6 +34,7 @@ Item {
|
||||||
|
|
||||||
// General
|
// General
|
||||||
property color blackColor: "#000000"
|
property color blackColor: "#000000"
|
||||||
|
property color redColor: "red"
|
||||||
property color whiteColor: "#ffffff"
|
property color whiteColor: "#ffffff"
|
||||||
property color darkGreyColor: "#272727"
|
property color darkGreyColor: "#272727"
|
||||||
property color darkGreyColorOpacity: "#be272727" // 77%
|
property color darkGreyColorOpacity: "#be272727" // 77%
|
||||||
|
@ -214,6 +215,11 @@ Item {
|
||||||
property int mosaicButtonPreferredWidth: 70
|
property int mosaicButtonPreferredWidth: 70
|
||||||
property int mosaicButtonMaxWidth: 100
|
property int mosaicButtonMaxWidth: 100
|
||||||
|
|
||||||
|
property int menuItemsPreferredWidth: 220
|
||||||
|
property int menuItemsPreferredHeight: 48
|
||||||
|
property int menuItemsCommonBorderWidth: 1
|
||||||
|
property int menuBorderPreferredHeight: 8
|
||||||
|
|
||||||
property real maximumWidthSettingsView: 600
|
property real maximumWidthSettingsView: 600
|
||||||
property real settingsHeaderpreferredHeight: 64
|
property real settingsHeaderpreferredHeight: 64
|
||||||
property real preferredFieldWidth: 256
|
property real preferredFieldWidth: 256
|
||||||
|
@ -225,6 +231,10 @@ Item {
|
||||||
property real pluginHandlersPopupViewHeight: 200
|
property real pluginHandlersPopupViewHeight: 200
|
||||||
property real pluginHandlersPopupViewDelegateHeight: 50
|
property real pluginHandlersPopupViewDelegateHeight: 50
|
||||||
|
|
||||||
|
property real lineEditContextMenuItemsHeight: 15
|
||||||
|
property real lineEditContextMenuItemsWidth: 100
|
||||||
|
property real lineEditContextMenuSeparatorsHeight: 2
|
||||||
|
|
||||||
// main application spec
|
// main application spec
|
||||||
property real mainViewMinWidth: 300
|
property real mainViewMinWidth: 300
|
||||||
property real mainViewMinHeight: 400
|
property real mainViewMinHeight: 400
|
||||||
|
|
|
@ -39,7 +39,7 @@ Control {
|
||||||
signal addToConferenceClicked
|
signal addToConferenceClicked
|
||||||
signal transferClicked // TODO: bind this
|
signal transferClicked // TODO: bind this
|
||||||
signal shareScreenClicked
|
signal shareScreenClicked
|
||||||
signal stopSharingScreenClicked
|
signal stopSharingClicked
|
||||||
signal shareScreenAreaClicked // TODO: bind this
|
signal shareScreenAreaClicked // TODO: bind this
|
||||||
signal pluginsClicked
|
signal pluginsClicked
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ Control {
|
||||||
Action {
|
Action {
|
||||||
id: shareAction
|
id: shareAction
|
||||||
onTriggered: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
onTriggered: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
||||||
root.stopSharingScreenClicked() :
|
root.stopSharingClicked() :
|
||||||
root.shareScreenClicked()
|
root.shareScreenClicked()
|
||||||
icon.source: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
icon.source: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
||||||
"qrc:/images/icons/share_stop_black_24dp.svg" :
|
"qrc:/images/icons/share_stop_black_24dp.svg" :
|
||||||
|
@ -197,7 +197,7 @@ Control {
|
||||||
icon.color: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
icon.color: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
||||||
"red" : "white"
|
"red" : "white"
|
||||||
text: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
text: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ?
|
||||||
JamiStrings.stopSharingScreen :
|
JamiStrings.stopSharing :
|
||||||
JamiStrings.shareScreen
|
JamiStrings.shareScreen
|
||||||
property real size: 34
|
property real size: 34
|
||||||
},
|
},
|
||||||
|
@ -248,7 +248,7 @@ Control {
|
||||||
if (isModerator && !isSIP)
|
if (isModerator && !isSIP)
|
||||||
CallOverlayModel.addSecondaryControl(addPersonAction)
|
CallOverlayModel.addSecondaryControl(addPersonAction)
|
||||||
CallOverlayModel.addSecondaryControl(chatAction)
|
CallOverlayModel.addSecondaryControl(chatAction)
|
||||||
if (!isAudioOnly)
|
if (!isAudioOnly && !isSIP)
|
||||||
CallOverlayModel.addSecondaryControl(shareAction)
|
CallOverlayModel.addSecondaryControl(shareAction)
|
||||||
CallOverlayModel.addSecondaryControl(recordAction)
|
CallOverlayModel.addSecondaryControl(recordAction)
|
||||||
if (UtilsAdapter.checkShowPluginsButton(true))
|
if (UtilsAdapter.checkShowPluginsButton(true))
|
||||||
|
|
|
@ -54,11 +54,6 @@ Item {
|
||||||
|
|
||||||
signal chatButtonClicked
|
signal chatButtonClicked
|
||||||
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (!visible)
|
|
||||||
callViewContextMenu.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticipantsLayer {
|
ParticipantsLayer {
|
||||||
id: __participantsLayer
|
id: __participantsLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -195,7 +190,7 @@ Item {
|
||||||
function onAddToConferenceClicked() { openContactPicker(ContactList.CONFERENCE) }
|
function onAddToConferenceClicked() { openContactPicker(ContactList.CONFERENCE) }
|
||||||
function onTransferClicked() { openContactPicker(ContactList.TRANSFER) }
|
function onTransferClicked() { openContactPicker(ContactList.TRANSFER) }
|
||||||
function onShareScreenClicked() { openShareScreen() }
|
function onShareScreenClicked() { openShareScreen() }
|
||||||
function onStopSharingScreenClicked() { AvAdapter.stopSharingScreen() }
|
function onStopSharingClicked() { AvAdapter.stopSharing() }
|
||||||
function onShareScreenAreaClicked() { openShareScreenArea() }
|
function onShareScreenAreaClicked() { openShareScreenArea() }
|
||||||
function onPluginsClicked() { openPluginsMenu() }
|
function onPluginsClicked() { openPluginsMenu() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,11 @@ import net.jami.Adapters 1.0
|
||||||
import net.jami.Constants 1.0
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
|
import "../../commoncomponents/contextmenu"
|
||||||
import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation
|
|
||||||
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation
|
||||||
import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
|
import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation
|
||||||
|
|
||||||
Item {
|
ContextMenuAutoLoader {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool isSIP: false
|
property bool isSIP: false
|
||||||
|
@ -44,140 +43,130 @@ Item {
|
||||||
signal pluginItemClicked
|
signal pluginItemClicked
|
||||||
signal transferCallButtonClicked
|
signal transferCallButtonClicked
|
||||||
|
|
||||||
function close() {
|
property list<GeneralMenuItem> menuItems: [
|
||||||
// leave this debug line is a reminder of a design failure
|
GeneralMenuItem {
|
||||||
console.debug("call view context menu close")
|
id: resumePauseCall
|
||||||
const menu = ContextMenuGenerator.getMenu()
|
|
||||||
if (menu)
|
|
||||||
menu.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
function openMenu() {
|
canTrigger: isSIP
|
||||||
ContextMenuGenerator.initMenu()
|
itemName: isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall
|
||||||
if (isSIP) {
|
iconSource: isPaused ? "qrc:/images/icons/play_circle_outline-24px.svg" :
|
||||||
ContextMenuGenerator.addMenuItem(
|
"qrc:/images/icons/pause_circle_outline-24px.svg"
|
||||||
isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall,
|
onClicked: {
|
||||||
isPaused ? "qrc:/images/icons/play_circle_outline-24px.svg" :
|
CallAdapter.holdThisCallToggle()
|
||||||
"qrc:/images/icons/pause_circle_outline-24px.svg",
|
|
||||||
function () {
|
|
||||||
CallAdapter.holdThisCallToggle()
|
|
||||||
})
|
|
||||||
ContextMenuGenerator.addMenuItem(JamiStrings.sipInputPanel,
|
|
||||||
"qrc:/images/icons/ic_keypad.svg",
|
|
||||||
function () {
|
|
||||||
sipInputPanel.open()
|
|
||||||
})
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiStrings.transferCall,
|
|
||||||
"qrc:/images/icons/phone_forwarded-24px.svg",
|
|
||||||
function () {
|
|
||||||
root.transferCallButtonClicked()
|
|
||||||
})
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuSeparator()
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
localIsRecording ? JamiStrings.stopRec : JamiStrings.startRec,
|
|
||||||
"qrc:/images/icons/av_icons/fiber_manual_record-24px.svg",
|
|
||||||
function () {
|
|
||||||
CallAdapter.recordThisCallToggle()
|
|
||||||
localIsRecording = CallAdapter.isRecordingThisCall()
|
|
||||||
}, JamiTheme.recordIconColor)
|
|
||||||
|
|
||||||
if (isAudioOnly && !isPaused)
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiQmlUtils.callIsFullscreen ? JamiStrings.exitFullScreen : JamiStrings.fullScreen,
|
|
||||||
JamiQmlUtils.callIsFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" :
|
|
||||||
"qrc:/images/icons/open_in_full-24px.svg",
|
|
||||||
function () {
|
|
||||||
callStackView.toggleFullScreen()
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!isAudioOnly && !isPaused) {
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiQmlUtils.callIsFullscreen ? JamiStrings.exitFullScreen : JamiStrings.fullScreen,
|
|
||||||
JamiQmlUtils.callIsFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" :
|
|
||||||
"qrc:/images/icons/open_in_full-24px.svg",
|
|
||||||
function () {
|
|
||||||
callStackView.toggleFullScreen()
|
|
||||||
})
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuSeparator()
|
|
||||||
|
|
||||||
generateDeviceMenuItem()
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuSeparator()
|
|
||||||
|
|
||||||
if (AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY) {
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiStrings.stopSharingScreen,
|
|
||||||
"qrc:/images/icons/share_stop_black_24dp.svg",
|
|
||||||
function () {
|
|
||||||
AvAdapter.stopSharingScreen()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiStrings.shareScreen,
|
|
||||||
"qrc:/images/icons/share_screen_black_24dp.svg",
|
|
||||||
function () {
|
|
||||||
if (Qt.application.screens.length === 1) {
|
|
||||||
AvAdapter.shareEntireScreen(0)
|
|
||||||
} else {
|
|
||||||
SelectScreenWindowCreation.createSelectScreenWindowObject()
|
|
||||||
SelectScreenWindowCreation.showSelectScreenWindow()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiStrings.shareScreenArea,
|
|
||||||
"qrc:/images/icons/share_screen_black_24dp.svg",
|
|
||||||
function () {
|
|
||||||
if (Qt.platform.os !== "windows") {
|
|
||||||
AvAdapter.shareScreenArea(0, 0, 0, 0)
|
|
||||||
} else {
|
|
||||||
ScreenRubberBandCreation.createScreenRubberBandWindowObject()
|
|
||||||
ScreenRubberBandCreation.showScreenRubberBandWindow()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: inputPanelSIP
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
canTrigger: isSIP
|
||||||
JamiStrings.shareFile,
|
itemName: JamiStrings.sipInputPanel
|
||||||
"qrc:/images/icons/insert_photo-24px.svg", function () {
|
iconSource: "qrc:/images/icons/ic_keypad.svg"
|
||||||
jamiFileDialog.open()
|
onClicked: {
|
||||||
})
|
sipInputPanel.open()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: callTransfer
|
||||||
|
|
||||||
|
canTrigger: isSIP
|
||||||
|
itemName: JamiStrings.transferCall
|
||||||
|
iconSource: "qrc:/images/icons/phone_forwarded-24px.svg"
|
||||||
|
addMenuSeparatorAfter: isSIP
|
||||||
|
onClicked: {
|
||||||
|
root.transferCallButtonClicked()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: localRecord
|
||||||
|
|
||||||
|
itemName: localIsRecording ? JamiStrings.stopRec : JamiStrings.startRec
|
||||||
|
iconSource: "qrc:/images/icons/av_icons/fiber_manual_record-24px.svg"
|
||||||
|
iconColor: JamiTheme.recordIconColor
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.recordThisCallToggle()
|
||||||
|
localIsRecording = CallAdapter.isRecordingThisCall()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: fullScreen
|
||||||
|
|
||||||
|
itemName: JamiQmlUtils.callIsFullscreen ?
|
||||||
|
JamiStrings.exitFullScreen : JamiStrings.fullScreen
|
||||||
|
iconSource: JamiQmlUtils.callIsFullscreen ?
|
||||||
|
"qrc:/images/icons/close_fullscreen-24px.svg" :
|
||||||
|
"qrc:/images/icons/open_in_full-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
callStackView.toggleFullScreen()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: stopSharing
|
||||||
|
|
||||||
|
canTrigger: !isAudioOnly
|
||||||
|
&& AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY
|
||||||
|
&& !isSIP
|
||||||
|
itemName: JamiStrings.stopSharing
|
||||||
|
iconSource: "qrc:/images/icons/share_stop_black_24dp.svg"
|
||||||
|
iconColor: JamiTheme.redColor
|
||||||
|
onClicked: {
|
||||||
|
AvAdapter.stopSharing()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: shareScreen
|
||||||
|
|
||||||
|
canTrigger: !isAudioOnly
|
||||||
|
&& AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
|
||||||
|
&& !isSIP
|
||||||
|
itemName: JamiStrings.shareScreen
|
||||||
|
iconSource: "qrc:/images/icons/share_screen_black_24dp.svg"
|
||||||
|
onClicked: {
|
||||||
|
if (Qt.application.screens.length === 1) {
|
||||||
|
AvAdapter.shareEntireScreen(0)
|
||||||
|
} else {
|
||||||
|
SelectScreenWindowCreation.createSelectScreenWindowObject()
|
||||||
|
SelectScreenWindowCreation.showSelectScreenWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: shareScreenArea
|
||||||
|
|
||||||
|
canTrigger: !isAudioOnly
|
||||||
|
&& AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY
|
||||||
|
&& !isSIP
|
||||||
|
itemName: JamiStrings.shareScreenArea
|
||||||
|
iconSource: "qrc:/images/icons/share_screen_black_24dp.svg"
|
||||||
|
onClicked: {
|
||||||
|
if (Qt.platform.os !== "windows") {
|
||||||
|
AvAdapter.shareScreenArea(0, 0, 0, 0)
|
||||||
|
} else {
|
||||||
|
ScreenRubberBandCreation.createScreenRubberBandWindowObject()
|
||||||
|
ScreenRubberBandCreation.showScreenRubberBandWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: shareFile
|
||||||
|
|
||||||
|
canTrigger: !isAudioOnly && !isSIP
|
||||||
|
itemName: JamiStrings.shareFile
|
||||||
|
iconSource: "qrc:/images/icons/insert_photo-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
jamiFileDialog.open()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: viewPlugin
|
||||||
|
|
||||||
|
canTrigger: UtilsAdapter.checkShowPluginsButton(true)
|
||||||
|
itemName: JamiStrings.viewPlugin
|
||||||
|
iconSource: "qrc:/images/icons/extension_24dp.svg"
|
||||||
|
onClicked: {
|
||||||
|
root.pluginItemClicked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
if (UtilsAdapter.checkShowPluginsButton(true)) {
|
|
||||||
ContextMenuGenerator.addMenuItem(
|
|
||||||
JamiStrings.viewPlugin,
|
|
||||||
"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"]
|
|
||||||
|
|
||||||
if (mapSize === 0)
|
|
||||||
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
|
||||||
JamiStrings.noVideoDevice, false)
|
|
||||||
|
|
||||||
for (var deviceName in deviceContextMenuInfoMap) {
|
|
||||||
if (deviceName === "size")
|
|
||||||
continue
|
|
||||||
VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects(
|
|
||||||
deviceName, deviceContextMenuInfoMap[deviceName])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JamiFileDialog {
|
JamiFileDialog {
|
||||||
id: jamiFileDialog
|
id: jamiFileDialog
|
||||||
|
@ -187,28 +176,5 @@ Item {
|
||||||
onAccepted: AvAdapter.shareFile(jamiFileDialog.file)
|
onAccepted: AvAdapter.shareFile(jamiFileDialog.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: menuItemsToLoad = menuItems
|
||||||
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
|
||||||
VideoDeviceContextMenuItemCreation.setVideoContextMenuObject(
|
|
||||||
ContextMenuGenerator.getMenu())
|
|
||||||
|
|
||||||
ContextMenuGenerator.getMenu().closed.connect(function () {
|
|
||||||
VideoDeviceContextMenuItemCreation.removeCreatedItems()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: In the future we want to implement this
|
|
||||||
|
|
||||||
// GeneralMenuItem {
|
|
||||||
// id: advancedInfosItem
|
|
||||||
|
|
||||||
// itemName: qsTr("Advanced informations")
|
|
||||||
// iconSource: "qrc:/images/icons/info-24px.svg"
|
|
||||||
// leftBorderWidth: commonBorderWidth
|
|
||||||
// rightBorderWidth: commonBorderWidth
|
|
||||||
|
|
||||||
// onClicked: {
|
|
||||||
// root.close()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ Rectangle {
|
||||||
|
|
||||||
LineEditContextMenu {
|
LineEditContextMenu {
|
||||||
id: lineEditContextMenu
|
id: lineEditContextMenu
|
||||||
|
|
||||||
|
lineEditObj: contactSearchBar
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponsiveImage {
|
ResponsiveImage {
|
||||||
|
@ -99,7 +101,7 @@ Rectangle {
|
||||||
onTextChanged: root.contactSearchBarTextChanged(contactSearchBar.text)
|
onTextChanged: root.contactSearchBarTextChanged(contactSearchBar.text)
|
||||||
onReleased: {
|
onReleased: {
|
||||||
if (event.button == Qt.RightButton)
|
if (event.button == Qt.RightButton)
|
||||||
lineEditContextMenu.openMenu(contactSearchBar, event)
|
lineEditContextMenu.openMenuAt(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,108 +25,131 @@ import net.jami.Adapters 1.0
|
||||||
import net.jami.Constants 1.0
|
import net.jami.Constants 1.0
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator
|
import "../../commoncomponents/contextmenu"
|
||||||
|
|
||||||
Item {
|
ContextMenuAutoLoader {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string responsibleAccountId: ""
|
property string responsibleAccountId: ""
|
||||||
property string responsibleConvUid: ""
|
property string responsibleConvUid: ""
|
||||||
property int contactType: Profile.Type.INVALID
|
property int contactType: Profile.Type.INVALID
|
||||||
|
property bool hasCall: {
|
||||||
function isOpen() { return ContextMenuGenerator.getMenu().visible }
|
if (responsibleAccountId && responsibleConvUid)
|
||||||
|
return UtilsAdapter.getCallId(responsibleAccountId,
|
||||||
function openMenu() {
|
responsibleConvUid) !== ""
|
||||||
ContextMenuGenerator.initMenu()
|
return false
|
||||||
var hasCall = UtilsAdapter.getCallId(responsibleAccountId, responsibleConvUid) !== ""
|
|
||||||
if (!hasCall) {
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Start video call"),
|
|
||||||
"qrc:/images/icons/videocam-24px.svg",
|
|
||||||
function (){
|
|
||||||
LRCInstance.selectConversation(responsibleConvUid, responsibleAccountId)
|
|
||||||
CallAdapter.placeCall()
|
|
||||||
communicationPageMessageWebView.setSendContactRequestButtonVisible(false)
|
|
||||||
})
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Start audio call"),
|
|
||||||
"qrc:/images/icons/place_audiocall-24px.svg",
|
|
||||||
function (){
|
|
||||||
LRCInstance.selectConversation(responsibleConvUid, responsibleAccountId)
|
|
||||||
CallAdapter.placeAudioOnlyCall()
|
|
||||||
communicationPageMessageWebView.setSendContactRequestButtonVisible(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Clear conversation"),
|
|
||||||
"qrc:/images/icons/ic_clear_24px.svg",
|
|
||||||
function (){
|
|
||||||
MessagesAdapter.clearConversationHistory(
|
|
||||||
responsibleAccountId,
|
|
||||||
responsibleConvUid)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (contactType === Profile.Type.RING || contactType === Profile.Type.SIP) {
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Remove contact"),
|
|
||||||
"qrc:/images/icons/ic_hangup_participant-24px.svg",
|
|
||||||
function (){
|
|
||||||
MessagesAdapter.removeConversation(
|
|
||||||
responsibleAccountId,
|
|
||||||
responsibleConvUid)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ContextMenuGenerator.addMenuItem(JamiStrings.hangup,
|
|
||||||
"qrc:/images/icons/ic_call_end_white_24px.svg",
|
|
||||||
function (){
|
|
||||||
CallAdapter.hangUpACall(responsibleAccountId,
|
|
||||||
responsibleConvUid)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((contactType === Profile.Type.RING || contactType === Profile.Type.PENDING
|
|
||||||
|| contactType === Profile.Type.TEMPORARY)) {
|
|
||||||
if (contactType === Profile.Type.PENDING || !hasCall) {
|
|
||||||
ContextMenuGenerator.addMenuSeparator()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contactType === Profile.Type.PENDING) {
|
|
||||||
ContextMenuGenerator.addMenuItem(JamiStrings.acceptContactRequest,
|
|
||||||
"qrc:/images/icons/add_people-24px.svg",
|
|
||||||
function (){
|
|
||||||
MessagesAdapter.acceptInvitation(
|
|
||||||
responsibleConvUid)
|
|
||||||
communicationPageMessageWebView.
|
|
||||||
setSendContactRequestButtonVisible(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
ContextMenuGenerator.addMenuItem(JamiStrings.declineContactRequest,
|
|
||||||
"qrc:/images/icons/round-close-24px.svg",
|
|
||||||
function (){
|
|
||||||
MessagesAdapter.refuseInvitation(
|
|
||||||
responsibleConvUid)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (!hasCall) {
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Block contact"),
|
|
||||||
"qrc:/images/icons/ic_block_24px.svg",
|
|
||||||
function (){
|
|
||||||
MessagesAdapter.blockConversation(
|
|
||||||
responsibleConvUid)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ContextMenuGenerator.addMenuSeparator()
|
|
||||||
ContextMenuGenerator.addMenuItem(qsTr("Contact details"),
|
|
||||||
"qrc:/images/icons/person-24px.svg",
|
|
||||||
function (){
|
|
||||||
userProfile.open()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
root.height = ContextMenuGenerator.getMenu().height
|
|
||||||
root.width = ContextMenuGenerator.getMenu().width
|
|
||||||
ContextMenuGenerator.getMenu().open()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
property list<GeneralMenuItem> menuItems: [
|
||||||
ContextMenuGenerator.createBaseContextMenuObjects(root)
|
GeneralMenuItem {
|
||||||
}
|
id: startVideoCallItem
|
||||||
|
|
||||||
|
canTrigger: !hasCall
|
||||||
|
itemName: JamiStrings.startVideoCall
|
||||||
|
iconSource: "qrc:/images/icons/videocam-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
LRCInstance.selectConversation(responsibleConvUid,
|
||||||
|
responsibleAccountId)
|
||||||
|
CallAdapter.placeCall()
|
||||||
|
communicationPageMessageWebView.setSendContactRequestButtonVisible(
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: startAudioCall
|
||||||
|
|
||||||
|
canTrigger: !hasCall
|
||||||
|
itemName: JamiStrings.startAudioCall
|
||||||
|
iconSource: "qrc:/images/icons/place_audiocall-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
LRCInstance.selectConversation(responsibleConvUid,
|
||||||
|
responsibleAccountId)
|
||||||
|
CallAdapter.placeAudioOnlyCall()
|
||||||
|
communicationPageMessageWebView.setSendContactRequestButtonVisible(
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: clearConversation
|
||||||
|
|
||||||
|
canTrigger: !hasCall
|
||||||
|
itemName: JamiStrings.clearConversation
|
||||||
|
iconSource: "qrc:/images/icons/ic_clear_24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
MessagesAdapter.clearConversationHistory(responsibleAccountId,
|
||||||
|
responsibleConvUid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: removeContact
|
||||||
|
|
||||||
|
canTrigger: !hasCall && (contactType === Profile.Type.RING
|
||||||
|
|| contactType === Profile.Type.SIP)
|
||||||
|
itemName: JamiStrings.removeContact
|
||||||
|
iconSource: "qrc:/images/icons/ic_hangup_participant-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
MessagesAdapter.removeConversation(responsibleAccountId,
|
||||||
|
responsibleConvUid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: hangup
|
||||||
|
|
||||||
|
canTrigger: hasCall
|
||||||
|
itemName: JamiStrings.hangup
|
||||||
|
iconSource: "qrc:/images/icons/ic_call_end_white_24px.svg"
|
||||||
|
addMenuSeparatorAfter: contactType !== Profile.Type.SIP
|
||||||
|
&& (contactType === Profile.Type.PENDING
|
||||||
|
|| !hasCall)
|
||||||
|
onClicked: {
|
||||||
|
CallAdapter.hangUpACall(responsibleAccountId,
|
||||||
|
responsibleConvUid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: acceptContactRequest
|
||||||
|
|
||||||
|
canTrigger: contactType === Profile.Type.PENDING
|
||||||
|
itemName: JamiStrings.acceptContactRequest
|
||||||
|
iconSource: "qrc:/images/icons/add_people-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
MessagesAdapter.acceptInvitation(responsibleConvUid)
|
||||||
|
communicationPageMessageWebView.setSendContactRequestButtonVisible(
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: declineContactRequest
|
||||||
|
|
||||||
|
canTrigger: contactType === Profile.Type.PENDING
|
||||||
|
itemName: JamiStrings.declineContactRequest
|
||||||
|
iconSource: "qrc:/images/icons/round-close-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
MessagesAdapter.refuseInvitation(responsibleConvUid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: blockContact
|
||||||
|
|
||||||
|
canTrigger: !hasCall && contactType !== Profile.Type.SIP
|
||||||
|
itemName: JamiStrings.blockContact
|
||||||
|
iconSource: "qrc:/images/icons/ic_block_24px.svg"
|
||||||
|
addMenuSeparatorAfter: contactType !== Profile.Type.SIP
|
||||||
|
onClicked: {
|
||||||
|
MessagesAdapter.blockConversation(responsibleConvUid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeneralMenuItem {
|
||||||
|
id: contactDetails
|
||||||
|
|
||||||
|
canTrigger: contactType !== Profile.Type.SIP
|
||||||
|
itemName: JamiStrings.contactDetails
|
||||||
|
iconSource: "qrc:/images/icons/person-24px.svg"
|
||||||
|
onClicked: {
|
||||||
|
userProfile.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Component.onCompleted: menuItemsToLoad = menuItems
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 storage for created video device context menu item,
|
|
||||||
* will be cleared once context menu is closed.
|
|
||||||
*/
|
|
||||||
var itemArray = []
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global videoDeviceContextMenuItem component, object variable for creation.
|
|
||||||
*/
|
|
||||||
var videoContextMenuObject
|
|
||||||
var videoDeviceContextMenuItemComponent
|
|
||||||
var videoDeviceContextMenuItemObject
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init videoContextMenuObject.
|
|
||||||
*/
|
|
||||||
function setVideoContextMenuObject(obj) {
|
|
||||||
videoContextMenuObject = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
function createVideoDeviceContextMenuItemObjects(deviceName, setChecked) {
|
|
||||||
|
|
||||||
videoDeviceContextMenuItemComponent = Qt.createComponent(
|
|
||||||
"../components/VideoCallPageContextMenuDeviceItem.qml")
|
|
||||||
if (videoDeviceContextMenuItemComponent.status === Component.Ready)
|
|
||||||
finishCreation(deviceName, setChecked)
|
|
||||||
else if (videoDeviceContextMenuItemComponent.status === Component.Error)
|
|
||||||
console.log("Error loading component:",
|
|
||||||
videoDeviceContextMenuItemComponent.errorString())
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
videoDeviceContextMenuItemObject.contextMenuPreferredWidth = videoContextMenuObject.implicitWidth
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Push into the storage array, and insert it into context menu.
|
|
||||||
*/
|
|
||||||
itemArray.push(videoDeviceContextMenuItemObject)
|
|
||||||
videoContextMenuObject.addItem(videoDeviceContextMenuItemObject)
|
|
||||||
|
|
||||||
videoDeviceContextMenuItemObject.clicked.connect(function () {
|
|
||||||
videoContextMenuObject.close()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeCreatedItems() {
|
|
||||||
var arrayLength = itemArray.length
|
|
||||||
for (var i = 0; i < arrayLength; i++) {
|
|
||||||
videoContextMenuObject.removeItem(itemArray[i])
|
|
||||||
itemArray[i].destroy()
|
|
||||||
}
|
|
||||||
itemArray = []
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue