Commit 22db039c authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/views/App/Calls/CallsWindow): supports call transfer

parent 9dda95aa
......@@ -280,6 +280,17 @@
<translation>Video</translation>
</message>
</context>
<context>
<name>CallTransfer</name>
<message>
<source>cancel</source>
<translation>CANCEL</translation>
</message>
<message>
<source>callTransferDescription</source>
<translation>Do you want to transfer this call ?</translation>
</message>
</context>
<context>
<name>Calls</name>
<message>
......
......@@ -280,6 +280,17 @@
<translation>Vidéo</translation>
</message>
</context>
<context>
<name>CallTransfer</name>
<message>
<source>cancel</source>
<translation>ANNULER</translation>
</message>
<message>
<source>callTransferDescription</source>
<translation>Voulez-vous transférer cet appel ?</translation>
</message>
</context>
<context>
<name>Calls</name>
<message>
......
......@@ -358,6 +358,7 @@
<file>ui/views/App/Calls/CallsWindow.qml</file>
<file>ui/views/App/Calls/ConferenceManager.qml</file>
<file>ui/views/App/Calls/Conference.qml</file>
<file>ui/views/App/Calls/Dialogs/CallTransfer.qml</file>
<file>ui/views/App/Calls/EndedCall.qml</file>
<file>ui/views/App/Calls/IncallFullscreenWindow.qml</file>
<file>ui/views/App/Calls/Incall.js</file>
......@@ -408,6 +409,7 @@
<file>ui/views/App/Styles/Calls/CallsWindowStyle.qml</file>
<file>ui/views/App/Styles/Calls/ConferenceManagerStyle.qml</file>
<file>ui/views/App/Styles/Calls/ConferenceStyle.qml</file>
<file>ui/views/App/Styles/Calls/Dialogs/CallTransferStyle.qml</file>
<file>ui/views/App/Styles/Main/AboutStyle.qml</file>
<file>ui/views/App/Styles/Main/Assistant/ActivateLinphoneSipAccountWithEmailStyle.qml</file>
<file>ui/views/App/Styles/Main/Assistant/AssistantAbstractViewStyle.qml</file>
......
......@@ -135,10 +135,21 @@ void CallModel::terminate () {
core->unlockVideoRender();
}
// -----------------------------------------------------------------------------
void CallModel::askForTransfer () {
CoreManager::getInstance()->getCallsListModel()->askForTransfer(this);
}
bool CallModel::transferTo (const QString &sipAddress) {
bool status = !!mCall->transfer(::Utils::qStringToLinphoneString(sipAddress));
if (status)
qWarning() << QStringLiteral("Unable to transfer: `%1`.").arg(sipAddress);
return status;
}
// -----------------------------------------------------------------------------
void CallModel::acceptVideoRequest () {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::CallParams> params = core->createCallParams(mCall);
......
......@@ -86,7 +86,9 @@ public:
Q_INVOKABLE void accept ();
Q_INVOKABLE void acceptWithVideo ();
Q_INVOKABLE void terminate ();
Q_INVOKABLE void askForTransfer ();
Q_INVOKABLE bool transferTo (const QString &sipAddress);
Q_INVOKABLE void acceptVideoRequest ();
Q_INVOKABLE void rejectVideoRequest ();
......
......@@ -212,18 +212,20 @@ void CallsListModel::removeCall (const shared_ptr<linphone::Call> &call) {
return;
}
QTimer::singleShot(
DELAY_BEFORE_REMOVE_CALL, this, [this, callModel]() {
qInfo() << QStringLiteral("Removing call:") << callModel;
int index = mList.indexOf(callModel);
if (index == -1 || !removeRow(index))
qWarning() << QStringLiteral("Unable to remove call:") << callModel;
if (mList.empty() && ConferenceHelperModel::getInstancesNumber() == 0) {
qInfo() << QStringLiteral("Last call terminated, close calls window.");
App::getInstance()->getCallsWindow()->close();
}
}
);
QTimer::singleShot(DELAY_BEFORE_REMOVE_CALL, this, [this, callModel] {
removeCallCb(callModel);
});
}
void CallsListModel::removeCallCb (CallModel *callModel) {
qInfo() << QStringLiteral("Removing call:") << callModel;
int index = mList.indexOf(callModel);
if (index == -1 || !removeRow(index))
qWarning() << QStringLiteral("Unable to remove call:") << callModel;
if (mList.empty() && ConferenceHelperModel::getInstancesNumber() == 0) {
qInfo() << QStringLiteral("Last call terminated, close calls window.");
App::getInstance()->getCallsWindow()->close();
}
}
......@@ -64,6 +64,7 @@ private:
void addCall (const std::shared_ptr<linphone::Call> &call);
void removeCall (const std::shared_ptr<linphone::Call> &call);
void removeCallCb (CallModel *callModel);
QList<CallModel *> mList;
......
......@@ -38,9 +38,9 @@ using namespace std;
// Schedule a function in app context.
void scheduleFunctionInApp (function<void()> func) {
App *app = App::getInstance();
if (QThread::currentThread() != app->thread()) {
if (QThread::currentThread() != app->thread())
QTimer::singleShot(0, app, func);
} else
else
func();
}
......@@ -168,3 +168,52 @@ void CoreHandlers::onRegistrationStateChanged (
) {
emit registrationStateChanged(proxyConfig, state);
}
void CoreHandlers::onTransferStateChanged (
const shared_ptr<linphone::Core> &,
const shared_ptr<linphone::Call> &call,
linphone::CallState state
) {
switch (state) {
case linphone::CallStateEarlyUpdatedByRemote:
case linphone::CallStateEarlyUpdating:
case linphone::CallStateIdle:
case linphone::CallStateIncomingEarlyMedia:
case linphone::CallStateIncomingReceived:
case linphone::CallStateOutgoingEarlyMedia:
case linphone::CallStateOutgoingRinging:
case linphone::CallStatePaused:
case linphone::CallStatePausedByRemote:
case linphone::CallStatePausing:
case linphone::CallStateRefered:
case linphone::CallStateReleased:
case linphone::CallStateResuming:
case linphone::CallStateStreamsRunning:
case linphone::CallStateUpdatedByRemote:
case linphone::CallStateUpdating:
break; // Nothing.
// 1. Init.
case linphone::CallStateOutgoingInit:
qInfo() << QStringLiteral("Call transfer init.");
break;
// 2. In progress.
case linphone::CallStateOutgoingProgress:
qInfo() << QStringLiteral("Call transfer in progress.");
break;
// 3. Done.
case linphone::CallStateConnected:
qInfo() << QStringLiteral("Call transfer succeeded.");
emit callTransferSucceeded(call);
break;
// 4. Error.
case linphone::CallStateEnd:
case linphone::CallStateError:
qWarning() << QStringLiteral("Call transfer failed.");
emit callTransferFailed(call);
break;
}
}
......@@ -43,6 +43,8 @@ public:
signals:
void authenticationRequested (const std::shared_ptr<linphone::AuthInfo> &authInfo);
void callStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void callTransferFailed (const std::shared_ptr<linphone::Call> &call);
void callTransferSucceeded (const std::shared_ptr<linphone::Call> &call);
void coreStarted ();
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
void presenceReceived (const QString &sipAddress, const std::shared_ptr<const linphone::PresenceModel> &presenceModel);
......@@ -107,6 +109,12 @@ private:
const std::string &message
) override;
void onTransferStateChanged (
const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<linphone::Call> &call,
linphone::CallState state
) override;
// ---------------------------------------------------------------------------
bool mCoreCreated = false;
......
......@@ -22,7 +22,7 @@ function handleClosing (close) {
}
window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), {
descriptionText: qsTr('acceptClosingDescription'),
descriptionText: qsTr('acceptClosingDescription')
}, function (status) {
if (status) {
forceClose = true
......@@ -71,5 +71,12 @@ function getContent () {
// -----------------------------------------------------------------------------
function handleCallTransferAsked (call) {
console.log('TODO: handle call transfer')
if (!call) {
return
}
window.detachVirtualWindow()
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallTransfer.qml'), {
call: call
})
}
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import App.Styles 1.0
// =============================================================================
DialogPlus {
id: callTransfer
// ---------------------------------------------------------------------------
property var call
// ---------------------------------------------------------------------------
buttons: [
TextButtonA {
text: qsTr('cancel')
onClicked: exit(0)
}
]
centeredButtons: true
descriptionText: qsTr('callTransferDescription')
height: CallTransferStyle.height
width: CallTransferStyle.width
onCallChanged: !call && exit(0)
// ---------------------------------------------------------------------------
ColumnLayout {
anchors {
fill: parent
leftMargin: CallTransferStyle.leftMargin
rightMargin: CallTransferStyle.rightMargin
}
spacing: 0
Contact {
Layout.fillWidth: true
entry: SipAddressesModel.getSipAddressObserver(call ? call.sipAddress : '')
}
// -------------------------------------------------------------------------
// Address selector.
// -------------------------------------------------------------------------
Item {
Layout.fillHeight: true
Layout.fillWidth: true
ColumnLayout {
anchors.fill: parent
spacing: CallTransferStyle.spacing
TextField {
id: filter
Layout.fillWidth: true
icon: 'search'
onTextChanged: sipAddressesModel.setFilter(text)
}
ScrollableListViewField {
Layout.fillHeight: true
Layout.fillWidth: true
SipAddressesView {
anchors.fill: parent
actions: [{
icon: 'transfer',
handler: function (entry) {
callTransfer.call.transferTo(entry.sipAddress)
exit(1)
}
}]
genSipAddress: filter.text
model: SipAddressesProxyModel {
id: sipAddressesModel
}
onEntryClicked: actions[0].handler(entry)
}
}
}
}
}
}
pragma Singleton
import QtQuick 2.7
// =============================================================================
QtObject {
property int height: 420
property int leftMargin: 35
property int rightMargin: 35
property int spacing: 10
property int width: 450
}
......@@ -9,6 +9,8 @@ singleton CallsWindowStyle 1.0 Calls/CallsWindowStyle.qm
singleton ConferenceManagerStyle 1.0 Calls/ConferenceManagerStyle.qml
singleton ConferenceStyle 1.0 Calls/ConferenceStyle.qml
singleton CallTransferStyle 1.0 Calls/Dialogs/CallTransferStyle.qml
singleton ActivateLinphoneSipAccountWithEmailStyle 1.0 Main/Assistant/ActivateLinphoneSipAccountWithEmailStyle.qml
singleton AssistantAbstractViewStyle 1.0 Main/Assistant/AssistantAbstractViewStyle.qml
singleton AssistantHomeStyle 1.0 Main/Assistant/AssistantHomeStyle.qml
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment