mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-07 05:23:06 +00:00
feat(ui/views/App/Calls/Incall): supports TelKeypad.
This commit is contained in:
parent
5829ccc71e
commit
58ee8ae7aa
18 changed files with 331 additions and 91 deletions
|
|
@ -208,6 +208,7 @@
|
|||
<file>ui/modules/Common/Form/Tab/TabButton.qml</file>
|
||||
<file>ui/modules/Common/Form/Tab/TabContainer.qml</file>
|
||||
<file>ui/modules/Common/Form/TransparentTextInput.qml</file>
|
||||
<file>ui/modules/Common/Helpers/DragBox.qml</file>
|
||||
<file>ui/modules/Common/Helpers/InvertedMouseArea.qml</file>
|
||||
<file>ui/modules/Common/Image/Icon.qml</file>
|
||||
<file>ui/modules/Common/Image/RoundedImage.qml</file>
|
||||
|
|
@ -298,13 +299,13 @@
|
|||
<file>ui/modules/Linphone/Notifications/NotificationReceivedMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Presence/PresenceLevel.qml</file>
|
||||
<file>ui/modules/Linphone/qmldir</file>
|
||||
<file>ui/modules/Linphone/SmartSearchBar.qml</file>
|
||||
<file>ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Blocks/CardBlockStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Blocks/RequestBlockStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Calls/CallsStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/ChatStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Codecs/CodecsViewerStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Contact/AvatarStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml</file>
|
||||
|
|
@ -316,11 +317,12 @@
|
|||
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/qmldir</file>
|
||||
<file>ui/modules/Linphone/Styles/SmartSearchBarStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/TimelineStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/SmartSearchBar/SmartSearchBarStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/TelKeypad/TelKeypadStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Timeline/TimelineStyle.qml</file>
|
||||
<file>ui/modules/Linphone/TelKeypad/TelKeypadButton.qml</file>
|
||||
<file>ui/modules/Linphone/TelKeypad/TelKeypad.qml</file>
|
||||
<file>ui/modules/Linphone/Timeline.qml</file>
|
||||
<file>ui/modules/Linphone/Timeline/Timeline.qml</file>
|
||||
<file>ui/scripts/LinphoneUtils/linphone-utils.js</file>
|
||||
<file>ui/scripts/LinphoneUtils/qmldir</file>
|
||||
<file>ui/scripts/Utils/port-tools.js</file>
|
||||
|
|
|
|||
|
|
@ -381,3 +381,9 @@ bool CallModel::getUpdating () const {
|
|||
bool CallModel::getRecording () const {
|
||||
return mRecording;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CallModel::sendDtmf (const QString &dtmf) {
|
||||
mLinphoneCall->sendDtmf(dtmf.constData()[0].toLatin1());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ public:
|
|||
Q_INVOKABLE void startRecording ();
|
||||
Q_INVOKABLE void stopRecording ();
|
||||
|
||||
Q_INVOKABLE void sendDtmf (const QString &dtmf);
|
||||
|
||||
signals:
|
||||
void statusChanged (CallStatus status);
|
||||
void microMutedChanged (bool status);
|
||||
|
|
|
|||
116
linphone-desktop/ui/modules/Common/Helpers/DragBox.qml
Normal file
116
linphone-desktop/ui/modules/Common/Helpers/DragBox.qml
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import QtQuick 2.7
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Item {
|
||||
id: dragBox
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property var container
|
||||
property var draggable
|
||||
|
||||
property var xPosition
|
||||
property var yPosition
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property var _mouseArea: null
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
signal pressed (var mouse)
|
||||
signal released (var mouse)
|
||||
signal wheel (var wheel)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function _create () {
|
||||
draggable.x = Qt.binding(xPosition)
|
||||
draggable.y = Qt.binding(yPosition)
|
||||
|
||||
var drag = draggable.Drag
|
||||
|
||||
drag.hotSpot.x = Qt.binding(function () {
|
||||
return draggable.width / 2
|
||||
})
|
||||
drag.hotSpot.y = Qt.binding(function () {
|
||||
return draggable.height / 2
|
||||
})
|
||||
|
||||
if (_mouseArea == null) {
|
||||
_mouseArea = builder.createObject(draggable)
|
||||
|
||||
drag.active = Qt.binding(function () {
|
||||
return _mouseArea && _mouseArea.held
|
||||
})
|
||||
|
||||
drag.source = Qt.binding(function () {
|
||||
return _mouseArea
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function _delete () {
|
||||
if (_mouseArea != null) {
|
||||
_mouseArea.destroy()
|
||||
_mouseArea = null
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Component.onCompleted: enabled && _create()
|
||||
Component.onDestruction: _delete()
|
||||
|
||||
onEnabledChanged: {
|
||||
_delete()
|
||||
|
||||
if (enabled) {
|
||||
_create()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Component {
|
||||
id: builder
|
||||
|
||||
MouseArea {
|
||||
property bool held: false
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
drag {
|
||||
axis: Drag.XandYAxis
|
||||
target: parent
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
dragBox.pressed(mouse)
|
||||
held = true
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
dragBox.released(mouse)
|
||||
held = false
|
||||
|
||||
var container = dragBox.container
|
||||
|
||||
if (parent.x < 0) {
|
||||
parent.x = 0
|
||||
} else if (parent.x + parent.width >= container.width) {
|
||||
parent.x = container.width - parent.width
|
||||
}
|
||||
|
||||
if (parent.y < 0) {
|
||||
parent.y = 0
|
||||
} else if (parent.y + parent.height >= container.height) {
|
||||
parent.y = container.height - parent.height
|
||||
}
|
||||
}
|
||||
|
||||
onWheel: dragBox.wheel(wheel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ TabBar 1.0 Form/Tab/TabBar.qml
|
|||
TabButton 1.0 Form/Tab/TabButton.qml
|
||||
TabContainer 1.0 Form/Tab/TabContainer.qml
|
||||
|
||||
DragBox 1.0 Helpers/DragBox.qml
|
||||
InvertedMouseArea 1.0 Helpers/InvertedMouseArea.qml
|
||||
|
||||
Icon 1.0 Image/Icon.qml
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.7
|
||||
|
||||
import Common 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
QtObject {
|
||||
property int columnSpacing: 0
|
||||
property int height: 180
|
||||
property int rowSpacing: 0
|
||||
property int width: 150
|
||||
property color color: Colors.k
|
||||
|
||||
property QtObject button: QtObject {
|
||||
property QtObject color: QtObject {
|
||||
property color normal: Colors.k
|
||||
property color pressed: Colors.i
|
||||
}
|
||||
|
||||
property QtObject text: QtObject {
|
||||
property color color: Colors.d
|
||||
property int fontSize: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ singleton AccountStatusStyle 1.0 Account/AccountStatusStyle.qm
|
|||
singleton CardBlockStyle 1.0 Blocks/CardBlockStyle.qml
|
||||
singleton RequestBlockStyle 1.0 Blocks/RequestBlockStyle.qml
|
||||
|
||||
singleton ChatStyle 1.0 ChatStyle.qml
|
||||
singleton ChatStyle 1.0 Chat/ChatStyle.qml
|
||||
|
||||
singleton CallsStyle 1.0 Calls/CallsStyle.qml
|
||||
singleton CallControlsStyle 1.0 Calls/CallControlsStyle.qml
|
||||
|
|
@ -28,6 +28,8 @@ singleton NotificationReceivedCallStyle 1.0 Notifications/NotificationRec
|
|||
singleton NotificationReceivedMessageStyle 1.0 Notifications/NotificationReceivedMessageStyle.qml
|
||||
singleton NotificationReceivedFileMessageStyle 1.0 Notifications/NotificationReceivedFileMessageStyle.qml
|
||||
|
||||
singleton SmartSearchBarStyle 1.0 SmartSearchBarStyle.qml
|
||||
singleton SmartSearchBarStyle 1.0 SmartSearchBar/SmartSearchBarStyle.qml
|
||||
|
||||
singleton TimelineStyle 1.0 TimelineStyle.qml
|
||||
singleton TelKeypadStyle 1.0 TelKeypad/TelKeypadStyle.qml
|
||||
|
||||
singleton TimelineStyle 1.0 Timeline/TimelineStyle.qml
|
||||
|
|
|
|||
|
|
@ -1,48 +1,115 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Common 1.0
|
||||
import Linphone.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Grid {
|
||||
Rectangle {
|
||||
id: telKeypad
|
||||
|
||||
property var container: parent
|
||||
property var call
|
||||
|
||||
color: TelKeypadStyle.color
|
||||
|
||||
layer {
|
||||
effect: PopupShadow {}
|
||||
enabled: true
|
||||
}
|
||||
|
||||
height: TelKeypadStyle.height
|
||||
width: TelKeypadStyle.width
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
columns: 3
|
||||
GridLayout {
|
||||
id: grid
|
||||
|
||||
Repeater {
|
||||
model: [{
|
||||
text: '1',
|
||||
icon: 'answering_machine'
|
||||
}, {
|
||||
text: '2'
|
||||
},{
|
||||
text: '3'
|
||||
}, {
|
||||
text: '4'
|
||||
}, {
|
||||
text: '5'
|
||||
}, {
|
||||
text: '6'
|
||||
}, {
|
||||
text: '7'
|
||||
}, {
|
||||
text: '8'
|
||||
}, {
|
||||
text: '9'
|
||||
}, {
|
||||
text: '*'
|
||||
}, {
|
||||
text: '0',
|
||||
icon: 'plus'
|
||||
}, {
|
||||
text: '#'
|
||||
}]
|
||||
anchors.fill: parent
|
||||
|
||||
TelKeypadButton {
|
||||
icon: modelData.icon
|
||||
text: modelData.text
|
||||
columns: 3 // Not a style.
|
||||
rows: 4 // Same idea.
|
||||
|
||||
onClicked: console.log('TODO')
|
||||
columnSpacing: TelKeypadStyle.columnSpacing
|
||||
rowSpacing: TelKeypadStyle.rowSpacing
|
||||
|
||||
Repeater {
|
||||
model: [{
|
||||
text: '1',
|
||||
icon: 'answering_machine'
|
||||
}, {
|
||||
text: '2'
|
||||
},{
|
||||
text: '3'
|
||||
}, {
|
||||
text: '4'
|
||||
}, {
|
||||
text: '5'
|
||||
}, {
|
||||
text: '6'
|
||||
}, {
|
||||
text: '7'
|
||||
}, {
|
||||
text: '8'
|
||||
}, {
|
||||
text: '9'
|
||||
}, {
|
||||
text: '*'
|
||||
}, {
|
||||
text: '0',
|
||||
icon: 'plus'
|
||||
}, {
|
||||
text: '#'
|
||||
}]
|
||||
|
||||
TelKeypadButton {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
icon: modelData.icon || ''
|
||||
text: modelData.text
|
||||
|
||||
onClicked: {
|
||||
var text = modelData.text
|
||||
console.info('Send dtmf: ' + text)
|
||||
telKeypad.call.sendDtmf(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
DragBox {
|
||||
id: dragBox
|
||||
|
||||
readonly property int delta: 5
|
||||
|
||||
property var _mouseX
|
||||
property var _mouseY
|
||||
|
||||
container: telKeypad.container
|
||||
draggable: parent
|
||||
|
||||
xPosition: (function () {
|
||||
return 0
|
||||
})
|
||||
yPosition: (function () {
|
||||
return 0
|
||||
})
|
||||
|
||||
onPressed: {
|
||||
_mouseX = mouse.x
|
||||
_mouseY = mouse.y
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (Math.abs(_mouseX - mouse.x) <= delta && Math.abs(_mouseY - mouse.y) <= delta) {
|
||||
var id = parseInt(_mouseX / (parent.width / grid.columns)) + parseInt(_mouseY / (parent.height / grid.rows)) * grid.columns
|
||||
grid.children[id].clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,44 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
import Linphone.Styles 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
Item {}
|
||||
Item {
|
||||
id: button
|
||||
|
||||
property string icon: ''
|
||||
property string text: ''
|
||||
|
||||
signal clicked
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Button {
|
||||
anchors.fill: parent
|
||||
|
||||
background: Rectangle {
|
||||
color: TelKeypadStyle.button.color.normal
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
color: TelKeypadStyle.button.text.color
|
||||
|
||||
font {
|
||||
bold: true
|
||||
pointSize: TelKeypadStyle.button.text.fontSize
|
||||
}
|
||||
|
||||
elide: Text.ElideRight
|
||||
text: button.text
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: button.clicked()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ SipAddressesMenu 1.0 Menus/SipAddressesMenu.qml
|
|||
|
||||
PresenceLevel 1.0 Presence/PresenceLevel.qml
|
||||
|
||||
SmartSearchBar 1.0 SmartSearchBar.qml
|
||||
SmartSearchBar 1.0 SmartSearchBar/SmartSearchBar.qml
|
||||
|
||||
TelKeypad 1.0 TelKeypad.qml
|
||||
TelKeypad 1.0 TelKeypad/TelKeypad.qml
|
||||
|
||||
Timeline 1.0 Timeline.qml
|
||||
Timeline 1.0 Timeline/Timeline.qml
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ function handleStatusChanged (status) {
|
|||
if (fullscreen) {
|
||||
fullscreen.close()
|
||||
}
|
||||
|
||||
telKeypad.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -367,4 +367,14 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TelKeypad.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TelKeypad {
|
||||
id: telKeypad
|
||||
|
||||
call: incall.call
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -331,10 +331,13 @@ Window {
|
|||
Camera {
|
||||
property bool scale: false
|
||||
|
||||
Drag.active: cameraDrag.held
|
||||
Drag.source: cameraDrag
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
function xPosition () {
|
||||
return incall.width / 2 - width / 2
|
||||
}
|
||||
|
||||
function yPosition () {
|
||||
return incall.height - height
|
||||
}
|
||||
|
||||
call: incall.call
|
||||
isPreview: true
|
||||
|
|
@ -342,48 +345,12 @@ Window {
|
|||
height: CallStyle.actionArea.userVideo.height * (scale ? 2 : 1)
|
||||
width: CallStyle.actionArea.userVideo.width * (scale ? 2 : 1)
|
||||
|
||||
Component.onCompleted: {
|
||||
x = incall.width / 2 - width / 2
|
||||
y = incall.height - height
|
||||
}
|
||||
DragBox {
|
||||
container: incall
|
||||
draggable: parent
|
||||
|
||||
// Workaround.
|
||||
// x and y are not binded to functions because if the scale is updated,
|
||||
// the position of the preview is reset.
|
||||
Connections {
|
||||
target: incall
|
||||
onHeightChanged: y = incall.height - parent.height
|
||||
onWidthChanged: x = incall.width / 2 - parent.width / 2
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cameraDrag
|
||||
|
||||
property bool held: false
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
drag {
|
||||
axis: Drag.XandYAxis
|
||||
target: parent
|
||||
}
|
||||
|
||||
onPressed: held = true
|
||||
onReleased: {
|
||||
held = false
|
||||
|
||||
if (parent.x < 0) {
|
||||
parent.x = 0
|
||||
} else if (parent.x + parent.width >= incall.width) {
|
||||
parent.x = incall.width - parent.width
|
||||
}
|
||||
|
||||
if (parent.y < 0) {
|
||||
parent.y = 0
|
||||
} else if (parent.y + parent.height >= incall.height) {
|
||||
parent.y = incall.height - parent.height
|
||||
}
|
||||
}
|
||||
xPosition: parent.xPosition
|
||||
yPosition: parent.yPosition
|
||||
|
||||
onWheel: parent.scale = wheel.angleDelta.y > 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue