Feature : Call list.
- Add CallProxy for GUI to manage call list; - Add a function on Core to retrieve remote address (TODO: change the name) - Connect first/last call events. - Fix wrong parameter in call notification.
This commit is contained in:
parent
1cf6a076d4
commit
577aee8c98
17 changed files with 595 additions and 119 deletions
|
|
@ -36,6 +36,8 @@
|
||||||
#include "core/account/AccountProxy.hpp"
|
#include "core/account/AccountProxy.hpp"
|
||||||
#include "core/call/CallCore.hpp"
|
#include "core/call/CallCore.hpp"
|
||||||
#include "core/call/CallGui.hpp"
|
#include "core/call/CallGui.hpp"
|
||||||
|
#include "core/call/CallList.hpp"
|
||||||
|
#include "core/call/CallProxy.hpp"
|
||||||
#include "core/camera/CameraGui.hpp"
|
#include "core/camera/CameraGui.hpp"
|
||||||
#include "core/friend/FriendCore.hpp"
|
#include "core/friend/FriendCore.hpp"
|
||||||
#include "core/friend/FriendGui.hpp"
|
#include "core/friend/FriendGui.hpp"
|
||||||
|
|
@ -149,6 +151,8 @@ void App::initCppInterfaces() {
|
||||||
qmlRegisterUncreatableType<AccountCore>(Constants::MainQmlUri, 1, 0, "AccountCore", QLatin1String("Uncreatable"));
|
qmlRegisterUncreatableType<AccountCore>(Constants::MainQmlUri, 1, 0, "AccountCore", QLatin1String("Uncreatable"));
|
||||||
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
||||||
qmlRegisterUncreatableType<CallCore>(Constants::MainQmlUri, 1, 0, "CallCore", QLatin1String("Uncreatable"));
|
qmlRegisterUncreatableType<CallCore>(Constants::MainQmlUri, 1, 0, "CallCore", QLatin1String("Uncreatable"));
|
||||||
|
qmlRegisterType<CallProxy>(Constants::MainQmlUri, 1, 0, "CallProxy");
|
||||||
|
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
||||||
qmlRegisterType<FriendGui>(Constants::MainQmlUri, 1, 0, "FriendGui");
|
qmlRegisterType<FriendGui>(Constants::MainQmlUri, 1, 0, "FriendGui");
|
||||||
qmlRegisterUncreatableType<FriendCore>(Constants::MainQmlUri, 1, 0, "FriendCore", QLatin1String("Uncreatable"));
|
qmlRegisterUncreatableType<FriendCore>(Constants::MainQmlUri, 1, 0, "FriendCore", QLatin1String("Uncreatable"));
|
||||||
qmlRegisterType<MagicSearchProxy>(Constants::MainQmlUri, 1, 0, "MagicSearchProxy");
|
qmlRegisterType<MagicSearchProxy>(Constants::MainQmlUri, 1, 0, "MagicSearchProxy");
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/App.cpp
|
core/App.cpp
|
||||||
core/call/CallCore.cpp
|
core/call/CallCore.cpp
|
||||||
core/call/CallGui.cpp
|
core/call/CallGui.cpp
|
||||||
|
core/call/CallList.cpp
|
||||||
|
core/call/CallProxy.cpp
|
||||||
core/camera/CameraGui.cpp
|
core/camera/CameraGui.cpp
|
||||||
core/camera/CameraDummy.cpp
|
core/camera/CameraDummy.cpp
|
||||||
core/friend/FriendCore.cpp
|
core/friend/FriendCore.cpp
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,10 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CallCore::getPeerAddress() const {
|
||||||
|
return mPeerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
LinphoneEnums::CallStatus CallCore::getStatus() const {
|
LinphoneEnums::CallStatus CallCore::getStatus() const {
|
||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class CallCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(bool microphoneMuted READ getMicrophoneMuted WRITE lSetMicrophoneMuted NOTIFY microphoneMutedChanged)
|
Q_PROPERTY(bool microphoneMuted READ getMicrophoneMuted WRITE lSetMicrophoneMuted NOTIFY microphoneMutedChanged)
|
||||||
Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
||||||
Q_PROPERTY(bool paused READ getPaused WRITE lSetPaused NOTIFY pausedChanged)
|
Q_PROPERTY(bool paused READ getPaused WRITE lSetPaused NOTIFY pausedChanged)
|
||||||
Q_PROPERTY(QString peerAddress MEMBER mPeerAddress CONSTANT)
|
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
||||||
Q_PROPERTY(bool peerSecured READ getPeerSecured WRITE setPeerSecured NOTIFY peerSecuredChanged)
|
Q_PROPERTY(bool peerSecured READ getPeerSecured WRITE setPeerSecured NOTIFY peerSecuredChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
||||||
|
|
@ -53,6 +53,8 @@ public:
|
||||||
~CallCore();
|
~CallCore();
|
||||||
void setSelf(QSharedPointer<CallCore> me);
|
void setSelf(QSharedPointer<CallCore> me);
|
||||||
|
|
||||||
|
QString getPeerAddress() const;
|
||||||
|
|
||||||
LinphoneEnums::CallStatus getStatus() const;
|
LinphoneEnums::CallStatus getStatus() const;
|
||||||
void setStatus(LinphoneEnums::CallStatus status);
|
void setStatus(LinphoneEnums::CallStatus status);
|
||||||
|
|
||||||
|
|
|
||||||
175
Linphone/core/call/CallList.cpp
Normal file
175
Linphone/core/call/CallList.cpp
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CallList.hpp"
|
||||||
|
#include "CallCore.hpp"
|
||||||
|
#include "CallGui.hpp"
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <linphone++/linphone.hh>
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(CallList)
|
||||||
|
|
||||||
|
QSharedPointer<CallList> CallList::create() {
|
||||||
|
auto model = QSharedPointer<CallList>(new CallList(), &QObject::deleteLater);
|
||||||
|
model->moveToThread(App::getInstance()->thread());
|
||||||
|
model->setSelf(model);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<CallCore> CallList::createCallCore(const std::shared_ptr<linphone::Call> &call) {
|
||||||
|
auto callCore = CallCore::create(call);
|
||||||
|
connect(callCore.get(), &CallCore::stateChanged, this, &CallList::onStateChanged);
|
||||||
|
return callCore;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallList::CallList(QObject *parent) : ListProxy(parent) {
|
||||||
|
mustBeInMainThread(getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
CallList::~CallList() {
|
||||||
|
mustBeInMainThread("~" + getClassName());
|
||||||
|
mModelConnection = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallList::setSelf(QSharedPointer<CallList> me) {
|
||||||
|
mModelConnection = QSharedPointer<SafeConnection<CallList, CoreModel>>(
|
||||||
|
new SafeConnection<CallList, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
|
||||||
|
|
||||||
|
mModelConnection->makeConnectToCore(&CallList::lUpdate, [this]() {
|
||||||
|
mModelConnection->invokeToModel([this]() {
|
||||||
|
// Avoid copy to lambdas
|
||||||
|
QList<QSharedPointer<CallCore>> *calls = new QList<QSharedPointer<CallCore>>();
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
auto linphoneCalls = CoreModel::getInstance()->getCore()->getCalls();
|
||||||
|
auto currentCall = CoreModel::getInstance()->getCore()->getCurrentCall();
|
||||||
|
QSharedPointer<CallCore> currentCallCore;
|
||||||
|
for (auto it : linphoneCalls) {
|
||||||
|
auto model = createCallCore(it);
|
||||||
|
if (it == currentCall) currentCallCore = model;
|
||||||
|
calls->push_back(model);
|
||||||
|
}
|
||||||
|
mModelConnection->invokeToCore([this, calls, currentCallCore]() {
|
||||||
|
mustBeInMainThread(getClassName());
|
||||||
|
resetData();
|
||||||
|
add(*calls);
|
||||||
|
setHaveCall(calls->size() > 0);
|
||||||
|
setCurrentCall(currentCallCore);
|
||||||
|
delete calls;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
mModelConnection->makeConnectToModel(&CoreModel::firstCallStarted,
|
||||||
|
[this]() { mModelConnection->invokeToCore([this]() { setHaveCall(true); }); });
|
||||||
|
mModelConnection->makeConnectToModel(&CoreModel::lastCallEnded, [this]() {
|
||||||
|
mModelConnection->invokeToCore([this]() {
|
||||||
|
setHaveCall(false);
|
||||||
|
setCurrentCall(nullptr);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mModelConnection->makeConnectToModel(&CoreModel::callCreated, [this](const std::shared_ptr<linphone::Call> &call) {
|
||||||
|
auto model = createCallCore(call);
|
||||||
|
mModelConnection->invokeToCore([this, model]() {
|
||||||
|
// We set the current here and not on firstCallStarted event because we don't want to add unicity check
|
||||||
|
// while keeping the same model between list and current call.
|
||||||
|
if (mList.size() == 0) setCurrentCall(model);
|
||||||
|
add(model);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
lUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<CallCore> CallList::getCurrentCallCore() const {
|
||||||
|
return mCurrentCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallGui *CallList::getCurrentCall() const {
|
||||||
|
auto call = getCurrentCallCore();
|
||||||
|
if (call) return new CallGui(call);
|
||||||
|
else return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallList::setCurrentCall(QSharedPointer<CallCore> call) {
|
||||||
|
if (mCurrentCall != call) {
|
||||||
|
mCurrentCall = call;
|
||||||
|
emit currentCallChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallList::getHaveCall() const {
|
||||||
|
return mHaveCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallList::setHaveCall(bool haveCall) {
|
||||||
|
if (mHaveCall != haveCall) {
|
||||||
|
mHaveCall = haveCall;
|
||||||
|
emit haveCallChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<CallCore> CallList::getNextCall() const {
|
||||||
|
QSharedPointer<CallCore> call;
|
||||||
|
auto currentCall = getCurrentCallCore();
|
||||||
|
for (auto it = mList.rbegin(); !call && it != mList.rend(); ++it) {
|
||||||
|
if (*it != currentCall) {
|
||||||
|
call = it->objectCast<CallCore>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return call;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallList::onStateChanged() {
|
||||||
|
auto call = dynamic_cast<CallCore *>(sender());
|
||||||
|
switch (call->getState()) {
|
||||||
|
case LinphoneEnums::CallState::StreamsRunning:
|
||||||
|
case LinphoneEnums::CallState::Resuming: {
|
||||||
|
auto sharedCall = get(call);
|
||||||
|
setCurrentCall(sharedCall.objectCast<CallCore>());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LinphoneEnums::CallState::Released: {
|
||||||
|
auto sharedCall = get(call);
|
||||||
|
auto currentCall = getCurrentCallCore();
|
||||||
|
// Update current call
|
||||||
|
if (sharedCall == currentCall) {
|
||||||
|
// Unpause the next call. The current call will change on resume.
|
||||||
|
// Assumption: All calls that are not the current are paused.
|
||||||
|
auto nextCall = getNextCall();
|
||||||
|
if (nextCall) nextCall->lSetPaused(false);
|
||||||
|
}
|
||||||
|
sharedCall->disconnect(this);
|
||||||
|
remove(sharedCall);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CallList::data(const QModelIndex &index, int role) const {
|
||||||
|
int row = index.row();
|
||||||
|
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||||
|
if (role == Qt::DisplayRole) return QVariant::fromValue(new CallGui(mList[row].objectCast<CallCore>()));
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
72
Linphone/core/call/CallList.hpp
Normal file
72
Linphone/core/call/CallList.hpp
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALL_LIST_H_
|
||||||
|
#define CALL_LIST_H_
|
||||||
|
|
||||||
|
#include "../proxy/ListProxy.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
#include <QLocale>
|
||||||
|
|
||||||
|
class CallGui;
|
||||||
|
class CallCore;
|
||||||
|
class CoreModel;
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
class CallList : public ListProxy, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static QSharedPointer<CallList> create();
|
||||||
|
// Create a CallCore and make connections to List.
|
||||||
|
QSharedPointer<CallCore> createCallCore(const std::shared_ptr<linphone::Call> &call);
|
||||||
|
CallList(QObject *parent = Q_NULLPTR);
|
||||||
|
~CallList();
|
||||||
|
|
||||||
|
void setSelf(QSharedPointer<CallList> me);
|
||||||
|
|
||||||
|
CallGui *getCurrentCall() const; // Used for Ui
|
||||||
|
QSharedPointer<CallCore> getCurrentCallCore() const;
|
||||||
|
void setCurrentCall(QSharedPointer<CallCore> call);
|
||||||
|
|
||||||
|
bool getHaveCall() const;
|
||||||
|
void setHaveCall(bool haveCall);
|
||||||
|
|
||||||
|
// Get the next call after the current one. Used to switch the current call.
|
||||||
|
// At the moment, it select the last call in the list.
|
||||||
|
QSharedPointer<CallCore> getNextCall() const;
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
signals:
|
||||||
|
void lUpdate();
|
||||||
|
void haveCallChanged();
|
||||||
|
void currentCallChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Check the state from CallCore: sender() must be a CallCore.
|
||||||
|
void onStateChanged();
|
||||||
|
|
||||||
|
bool mHaveCall = false;
|
||||||
|
QSharedPointer<CallCore> mCurrentCall;
|
||||||
|
QSharedPointer<SafeConnection<CallList, CoreModel>> mModelConnection;
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
90
Linphone/core/call/CallProxy.cpp
Normal file
90
Linphone/core/call/CallProxy.cpp
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CallProxy.hpp"
|
||||||
|
#include "CallGui.hpp"
|
||||||
|
#include "CallList.hpp"
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(CallProxy)
|
||||||
|
|
||||||
|
CallProxy::CallProxy(QObject *parent) : SortFilterProxy(parent) {
|
||||||
|
mList = CallList::create();
|
||||||
|
connect(mList.get(), &CallList::currentCallChanged, this, &CallProxy::resetCurrentCall);
|
||||||
|
connect(mList.get(), &CallList::haveCallChanged, this, &CallProxy::haveCallChanged);
|
||||||
|
setSourceModel(mList.get());
|
||||||
|
sort(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallProxy::~CallProxy() {
|
||||||
|
setSourceModel(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CallProxy::getFilterText() const {
|
||||||
|
return mFilterText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallProxy::setFilterText(const QString &filter) {
|
||||||
|
if (mFilterText != filter) {
|
||||||
|
mFilterText = filter;
|
||||||
|
invalidate();
|
||||||
|
emit filterTextChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallGui *CallProxy::getCurrentCall() {
|
||||||
|
if (!mCurrentCall) mCurrentCall = dynamic_cast<CallList *>(sourceModel())->getCurrentCall();
|
||||||
|
return mCurrentCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallProxy::setCurrentCall(CallGui *call) {
|
||||||
|
dynamic_cast<CallList *>(sourceModel())->setCurrentCall(call->mCore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the default account to let UI build its new object if needed.
|
||||||
|
void CallProxy::resetCurrentCall() {
|
||||||
|
mCurrentCall = nullptr;
|
||||||
|
emit this->currentCallChanged(); // Warn the UI
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallProxy::getHaveCall() const {
|
||||||
|
return dynamic_cast<CallList *>(sourceModel())->getHaveCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||||
|
bool show = (mFilterText.isEmpty() || mFilterText == "*");
|
||||||
|
if (!show) {
|
||||||
|
QRegularExpression search(QRegularExpression::escape(mFilterText),
|
||||||
|
QRegularExpression::CaseInsensitiveOption |
|
||||||
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
|
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||||
|
auto model = sourceModel()->data(index);
|
||||||
|
auto call = model.value<CallGui *>();
|
||||||
|
show = call->getCore()->getPeerAddress().contains(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
return show;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const {
|
||||||
|
auto l = sourceModel()->data(left);
|
||||||
|
auto r = sourceModel()->data(right);
|
||||||
|
|
||||||
|
return l.value<CallGui *>()->getCore()->getPeerAddress() < r.value<CallGui *>()->getCore()->getPeerAddress();
|
||||||
|
}
|
||||||
69
Linphone/core/call/CallProxy.hpp
Normal file
69
Linphone/core/call/CallProxy.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALL_PROXY_H_
|
||||||
|
#define CALL_PROXY_H_
|
||||||
|
|
||||||
|
#include "../proxy/SortFilterProxy.hpp"
|
||||||
|
#include "core/call/CallGui.hpp"
|
||||||
|
#include "core/call/CallList.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
class CallProxy : public SortFilterProxy, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
||||||
|
Q_PROPERTY(CallGui *currentCall READ getCurrentCall WRITE setCurrentCall NOTIFY currentCallChanged)
|
||||||
|
Q_PROPERTY(bool haveCall READ getHaveCall NOTIFY haveCallChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
CallProxy(QObject *parent = Q_NULLPTR);
|
||||||
|
~CallProxy();
|
||||||
|
|
||||||
|
QString getFilterText() const;
|
||||||
|
void setFilterText(const QString &filter);
|
||||||
|
// Get a new object from List or give the stored one.
|
||||||
|
CallGui *getCurrentCall();
|
||||||
|
// TODO for manual setting. Changing the currentCall is automatically done by call->onStateChanged() on
|
||||||
|
// StreamRunning and Resuming
|
||||||
|
void setCurrentCall(CallGui *call);
|
||||||
|
void resetCurrentCall(); // Reset the default account to let UI build its new object if needed.
|
||||||
|
|
||||||
|
bool getHaveCall() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void filterTextChanged();
|
||||||
|
void currentCallChanged();
|
||||||
|
void haveCallChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
|
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
|
||||||
|
QString mFilterText;
|
||||||
|
CallGui *mCurrentCall = nullptr; // When null, a new UI object is build from List
|
||||||
|
QSharedPointer<CallList> mList;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -68,6 +68,7 @@ void CallModel::terminate() {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
mMonitor->terminate();
|
mMonitor->terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallModel::setPaused(bool paused) {
|
void CallModel::setPaused(bool paused) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
if (paused) {
|
if (paused) {
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ void CoreModel::onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
emit callStatsUpdated(core, call, stats);
|
emit callStatsUpdated(core, call, stats);
|
||||||
}
|
}
|
||||||
void CoreModel::onCallCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call) {
|
void CoreModel::onCallCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call) {
|
||||||
emit callCreated(lc, call);
|
emit callCreated(call);
|
||||||
}
|
}
|
||||||
void CoreModel::onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onChatRoomRead(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
||||||
|
|
@ -235,6 +235,9 @@ void CoreModel::onEcCalibrationResult(const std::shared_ptr<linphone::Core> &cor
|
||||||
int delayMs) {
|
int delayMs) {
|
||||||
emit ecCalibrationResult(core, status, delayMs);
|
emit ecCalibrationResult(core, status, delayMs);
|
||||||
}
|
}
|
||||||
|
void CoreModel::onFirstCallStarted(const std::shared_ptr<linphone::Core> &core) {
|
||||||
|
emit firstCallStarted();
|
||||||
|
}
|
||||||
void CoreModel::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::GlobalState gstate,
|
linphone::GlobalState gstate,
|
||||||
const std::string &message) {
|
const std::string &message) {
|
||||||
|
|
@ -244,6 +247,11 @@ void CoreModel::onIsComposingReceived(const std::shared_ptr<linphone::Core> &cor
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room) {
|
const std::shared_ptr<linphone::ChatRoom> &room) {
|
||||||
emit isComposingReceived(core, room);
|
emit isComposingReceived(core, room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoreModel::onLastCallEnded(const std::shared_ptr<linphone::Core> &core) {
|
||||||
|
emit lastCallEnded();
|
||||||
|
}
|
||||||
|
|
||||||
void CoreModel::onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void CoreModel::onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::Core::LogCollectionUploadState state,
|
linphone::Core::LogCollectionUploadState state,
|
||||||
const std::string &info) {
|
const std::string &info) {
|
||||||
|
|
|
||||||
|
|
@ -119,11 +119,13 @@ private:
|
||||||
virtual void onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
virtual void onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::EcCalibratorStatus status,
|
linphone::EcCalibratorStatus status,
|
||||||
int delayMs) override;
|
int delayMs) override;
|
||||||
|
virtual void onFirstCallStarted(const std::shared_ptr<linphone::Core> &core) override;
|
||||||
virtual void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
virtual void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::GlobalState gstate,
|
linphone::GlobalState gstate,
|
||||||
const std::string &message) override;
|
const std::string &message) override;
|
||||||
virtual void onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
virtual void onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room) override;
|
const std::shared_ptr<linphone::ChatRoom> &room) override;
|
||||||
|
virtual void onLastCallEnded(const std::shared_ptr<linphone::Core> &core) override;
|
||||||
virtual void onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
virtual void onLogCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::Core::LogCollectionUploadState state,
|
linphone::Core::LogCollectionUploadState state,
|
||||||
const std::string &info) override;
|
const std::string &info) override;
|
||||||
|
|
@ -183,7 +185,7 @@ signals:
|
||||||
void callStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
void callStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::Call> &call,
|
const std::shared_ptr<linphone::Call> &call,
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats);
|
const std::shared_ptr<const linphone::CallStats> &stats);
|
||||||
void callCreated(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call);
|
void callCreated(const std::shared_ptr<linphone::Call> &call);
|
||||||
void chatRoomRead(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
void chatRoomRead(const std::shared_ptr<linphone::Core> &core, const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
||||||
void chatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void chatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
|
@ -198,11 +200,13 @@ signals:
|
||||||
void dtmfReceived(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call, int dtmf);
|
void dtmfReceived(const std::shared_ptr<linphone::Core> &lc, const std::shared_ptr<linphone::Call> &call, int dtmf);
|
||||||
void
|
void
|
||||||
ecCalibrationResult(const std::shared_ptr<linphone::Core> &core, linphone::EcCalibratorStatus status, int delayMs);
|
ecCalibrationResult(const std::shared_ptr<linphone::Core> &core, linphone::EcCalibratorStatus status, int delayMs);
|
||||||
|
void firstCallStarted();
|
||||||
void globalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void globalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::GlobalState gstate,
|
linphone::GlobalState gstate,
|
||||||
const std::string &message);
|
const std::string &message);
|
||||||
void isComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
void isComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||||
const std::shared_ptr<linphone::ChatRoom> &room);
|
const std::shared_ptr<linphone::ChatRoom> &room);
|
||||||
|
void lastCallEnded();
|
||||||
void logCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
void logCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||||
linphone::Core::LogCollectionUploadState state,
|
linphone::Core::LogCollectionUploadState state,
|
||||||
const std::string &info);
|
const std::string &info);
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,9 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
void Utils::openCallsWindow(CallGui *call) {
|
||||||
|
if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show();
|
||||||
|
}
|
||||||
void Utils::closeCallsWindow() {
|
void Utils::closeCallsWindow() {
|
||||||
App::getInstance()->closeCallsWindow();
|
App::getInstance()->closeCallsWindow();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
class VariantObject;
|
class VariantObject;
|
||||||
|
class CallGui;
|
||||||
|
|
||||||
class Utils : public QObject {
|
class Utils : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
@ -51,9 +52,11 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
||||||
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
|
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
|
||||||
|
|
||||||
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
||||||
const QString &prepareTransfertAddress = "",
|
const QString &prepareTransfertAddress = "",
|
||||||
const QHash<QString, QString> &headers = {});
|
const QHash<QString, QString> &headers = {});
|
||||||
|
Q_INVOKABLE static void openCallsWindow(CallGui *call);
|
||||||
Q_INVOKABLE static void closeCallsWindow();
|
Q_INVOKABLE static void closeCallsWindow();
|
||||||
Q_INVOKABLE static VariantObject *haveAccount();
|
Q_INVOKABLE static VariantObject *haveAccount();
|
||||||
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallProxy{
|
||||||
|
id: callList
|
||||||
|
onCurrentCallChanged: {
|
||||||
|
console.log("Current call changed:"+currentCall)
|
||||||
|
if(currentCall) mainWindow.call = currentCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component BottomButton : Button {
|
component BottomButton : Button {
|
||||||
required property string enabledIcon
|
required property string enabledIcon
|
||||||
property string disabledIcon
|
property string disabledIcon
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
import Linphone
|
import Linphone
|
||||||
|
import UtilsCpp
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
Notification {
|
Notification {
|
||||||
|
|
@ -36,10 +36,7 @@ Notification {
|
||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
onClicked: {
|
onClicked: {
|
||||||
notification.call.core.lAccept(true)
|
notification.call.core.lAccept(true)
|
||||||
var windowComp = Qt.createComponent("OngoingCallPage.qml")
|
UtilsCpp.openCallsWindow(notification.call)
|
||||||
var callWindow = windowComp.createObject(null, {callVarObject: callVarObject})
|
|
||||||
callWindow.modality = Qt.ApplicationModal
|
|
||||||
callWindow.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item{
|
Item{
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ Rectangle {
|
||||||
+Math.floor(Math.random()*255).toString(16)
|
+Math.floor(Math.random()*255).toString(16)
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
color: genRandomColor() //"blue"
|
color: genRandomColor() //"blue"
|
||||||
opacity: 0.2
|
opacity: 0.2
|
||||||
border.color: genRandomColor() //"red"
|
border.color: genRandomColor() //"red"
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,43 @@ Window{
|
||||||
target: call && call.core || null
|
target: call && call.core || null
|
||||||
onLastErrorMessageChanged: if(mainItem.call) errorMessageText.text=mainItem.call.core.lastErrorMessage
|
onLastErrorMessageChanged: if(mainItem.call) errorMessageText.text=mainItem.call.core.lastErrorMessage
|
||||||
}
|
}
|
||||||
ColumnLayout{
|
RowLayout{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
Rectangle{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.preferredWidth: 200
|
||||||
|
color: 'gray'
|
||||||
|
opacity: 0.2
|
||||||
|
ListView{
|
||||||
|
id: callList
|
||||||
|
anchors.fill: parent
|
||||||
|
model: CallProxy{
|
||||||
|
id: callsModel
|
||||||
|
onCountChanged: console.log("count:"+count)
|
||||||
|
}
|
||||||
|
delegate: RectangleTest{
|
||||||
|
height: 40
|
||||||
|
width: callList.width
|
||||||
|
Text{
|
||||||
|
id: addressText
|
||||||
|
anchors.fill: parent
|
||||||
|
text: modelData.core.peerAddress
|
||||||
|
onTextChanged: console.log(addressText.text)
|
||||||
|
Component.onCompleted: console.log(addressText.text)
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
//modelData.core.lSetPaused(false)
|
||||||
|
callsModel.currentCall = modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnLayout{
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: accountLayout
|
id: accountLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -152,5 +187,6 @@ Window{
|
||||||
color: 'pink'
|
color: 'pink'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue