mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-26 00:08:13 +00:00
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/call/CallCore.hpp"
|
||||
#include "core/call/CallGui.hpp"
|
||||
#include "core/call/CallList.hpp"
|
||||
#include "core/call/CallProxy.hpp"
|
||||
#include "core/camera/CameraGui.hpp"
|
||||
#include "core/friend/FriendCore.hpp"
|
||||
#include "core/friend/FriendGui.hpp"
|
||||
|
|
@ -149,6 +151,8 @@ void App::initCppInterfaces() {
|
|||
qmlRegisterUncreatableType<AccountCore>(Constants::MainQmlUri, 1, 0, "AccountCore", QLatin1String("Uncreatable"));
|
||||
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
||||
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");
|
||||
qmlRegisterUncreatableType<FriendCore>(Constants::MainQmlUri, 1, 0, "FriendCore", QLatin1String("Uncreatable"));
|
||||
qmlRegisterType<MagicSearchProxy>(Constants::MainQmlUri, 1, 0, "MagicSearchProxy");
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ list(APPEND _LINPHONEAPP_SOURCES
|
|||
core/App.cpp
|
||||
core/call/CallCore.cpp
|
||||
core/call/CallGui.cpp
|
||||
core/call/CallList.cpp
|
||||
core/call/CallProxy.cpp
|
||||
core/camera/CameraGui.cpp
|
||||
core/camera/CameraDummy.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 {
|
||||
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 cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
||||
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 remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
||||
|
|
@ -53,6 +53,8 @@ public:
|
|||
~CallCore();
|
||||
void setSelf(QSharedPointer<CallCore> me);
|
||||
|
||||
QString getPeerAddress() const;
|
||||
|
||||
LinphoneEnums::CallStatus getStatus() const;
|
||||
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));
|
||||
mMonitor->terminate();
|
||||
}
|
||||
|
||||
void CallModel::setPaused(bool paused) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
if (paused) {
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ void CoreModel::onCallStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
|||
emit callStatsUpdated(core, call, stats);
|
||||
}
|
||||
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,
|
||||
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
|
||||
|
|
@ -235,6 +235,9 @@ void CoreModel::onEcCalibrationResult(const std::shared_ptr<linphone::Core> &cor
|
|||
int 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,
|
||||
linphone::GlobalState gstate,
|
||||
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) {
|
||||
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,
|
||||
linphone::Core::LogCollectionUploadState state,
|
||||
const std::string &info) {
|
||||
|
|
|
|||
|
|
@ -119,11 +119,13 @@ private:
|
|||
virtual void onEcCalibrationResult(const std::shared_ptr<linphone::Core> &core,
|
||||
linphone::EcCalibratorStatus status,
|
||||
int delayMs) override;
|
||||
virtual void onFirstCallStarted(const std::shared_ptr<linphone::Core> &core) override;
|
||||
virtual void onGlobalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||
linphone::GlobalState gstate,
|
||||
const std::string &message) override;
|
||||
virtual void onIsComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||
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,
|
||||
linphone::Core::LogCollectionUploadState state,
|
||||
const std::string &info) override;
|
||||
|
|
@ -183,7 +185,7 @@ signals:
|
|||
void callStatsUpdated(const std::shared_ptr<linphone::Core> &core,
|
||||
const std::shared_ptr<linphone::Call> &call,
|
||||
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 chatRoomStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||
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
|
||||
ecCalibrationResult(const std::shared_ptr<linphone::Core> &core, linphone::EcCalibratorStatus status, int delayMs);
|
||||
void firstCallStarted();
|
||||
void globalStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||
linphone::GlobalState gstate,
|
||||
const std::string &message);
|
||||
void isComposingReceived(const std::shared_ptr<linphone::Core> &core,
|
||||
const std::shared_ptr<linphone::ChatRoom> &room);
|
||||
void lastCallEnded();
|
||||
void logCollectionUploadStateChanged(const std::shared_ptr<linphone::Core> &core,
|
||||
linphone::Core::LogCollectionUploadState state,
|
||||
const std::string &info);
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Utils::openCallsWindow(CallGui *call) {
|
||||
if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show();
|
||||
}
|
||||
void Utils::closeCallsWindow() {
|
||||
App::getInstance()->closeCallsWindow();
|
||||
}
|
||||
|
|
@ -179,4 +181,4 @@ QString Utils::formatElapsedTime(int seconds) {
|
|||
}
|
||||
|
||||
return (h == 0 ? "" : hours + ":") + min + ":" + sec;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
class QQuickWindow;
|
||||
class VariantObject;
|
||||
class CallGui;
|
||||
|
||||
class Utils : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
@ -51,9 +52,11 @@ public:
|
|||
|
||||
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
||||
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
|
||||
|
||||
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
||||
const QString &prepareTransfertAddress = "",
|
||||
const QHash<QString, QString> &headers = {});
|
||||
Q_INVOKABLE static void openCallsWindow(CallGui *call);
|
||||
Q_INVOKABLE static void closeCallsWindow();
|
||||
Q_INVOKABLE static VariantObject *haveAccount();
|
||||
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@ Window {
|
|||
autoCloseWindow.restart()
|
||||
}
|
||||
}
|
||||
|
||||
CallProxy{
|
||||
id: callList
|
||||
onCurrentCallChanged: {
|
||||
console.log("Current call changed:"+currentCall)
|
||||
if(currentCall) mainWindow.call = currentCall
|
||||
}
|
||||
}
|
||||
|
||||
component BottomButton : Button {
|
||||
required property string enabledIcon
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import Linphone
|
||||
|
||||
import UtilsCpp
|
||||
// =============================================================================
|
||||
|
||||
Notification {
|
||||
|
|
@ -36,10 +36,7 @@ Notification {
|
|||
Layout.rightMargin: 20
|
||||
onClicked: {
|
||||
notification.call.core.lAccept(true)
|
||||
var windowComp = Qt.createComponent("OngoingCallPage.qml")
|
||||
var callWindow = windowComp.createObject(null, {callVarObject: callVarObject})
|
||||
callWindow.modality = Qt.ApplicationModal
|
||||
callWindow.show()
|
||||
UtilsCpp.openCallsWindow(notification.call)
|
||||
}
|
||||
}
|
||||
Item{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ Rectangle {
|
|||
+Math.floor(Math.random()*255).toString(16)
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
color: genRandomColor() //"blue"
|
||||
opacity: 0.2
|
||||
border.color: genRandomColor() //"red"
|
||||
|
|
|
|||
|
|
@ -30,126 +30,162 @@ Window{
|
|||
target: call && call.core || null
|
||||
onLastErrorMessageChanged: if(mainItem.call) errorMessageText.text=mainItem.call.core.lastErrorMessage
|
||||
}
|
||||
ColumnLayout{
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
RowLayout {
|
||||
id: accountLayout
|
||||
Layout.fillWidth: true
|
||||
property AccountProxy accounts: AccountProxy{id: accountProxy}
|
||||
property var haveAccountVar: UtilsCpp.haveAccount()
|
||||
property var haveAccount: haveAccountVar ? haveAccountVar.value : false
|
||||
onHaveAccountChanged: {
|
||||
console.log("HaveAccount: " +haveAccount)
|
||||
logStack.replace(haveAccount ? accountListComponent : loginComponent)
|
||||
}
|
||||
Control.StackView{
|
||||
id: logStack
|
||||
Layout.preferredHeight: 250
|
||||
Layout.preferredWidth: 250
|
||||
//initialItem: loginComponent
|
||||
}
|
||||
Component{
|
||||
id: accountListComponent
|
||||
ListView{
|
||||
id: accountList
|
||||
Layout.fillHeight: true
|
||||
model: AccountProxy{}
|
||||
delegate:Rectangle{
|
||||
color: "#11111111"
|
||||
height: 20
|
||||
width: accountList.width
|
||||
Text{
|
||||
|
||||
text: modelData.core.identityAddress
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: loginComponent
|
||||
LoginForm{}
|
||||
}
|
||||
}
|
||||
ColumnLayout{
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
RowLayout {
|
||||
id: accountLayout
|
||||
Layout.fillWidth: true
|
||||
property AccountProxy accounts: AccountProxy{id: accountProxy}
|
||||
property var haveAccountVar: UtilsCpp.haveAccount()
|
||||
property var haveAccount: haveAccountVar ? haveAccountVar.value : false
|
||||
onHaveAccountChanged: {
|
||||
console.log("HaveAccount: " +haveAccount)
|
||||
logStack.replace(haveAccount ? accountListComponent : loginComponent)
|
||||
}
|
||||
Rectangle{
|
||||
id: accountStatus
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
property int accountCount: accountProxy.count
|
||||
onAccountCountChanged: console.log("AccountCount:"+accountCount)
|
||||
property var defaultAccount: accountProxy.defaultAccount
|
||||
onDefaultAccountChanged: console.log("DefaultAccount:"+defaultAccount)
|
||||
property var state: accountProxy.count > 0 && defaultAccount? defaultAccount.core.registrationState : LoginPageCpp.registrationState
|
||||
onStateChanged: console.log("State:"+state)
|
||||
|
||||
color: state === LinphoneEnums.RegistrationState.Ok
|
||||
? 'green'
|
||||
: state === LinphoneEnums.RegistrationState.Failed || state === LinphoneEnums.RegistrationState.None
|
||||
? 'red'
|
||||
: 'orange'
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked:{
|
||||
logStack.replace(loginComponent)
|
||||
gc()
|
||||
Control.StackView{
|
||||
id: logStack
|
||||
Layout.preferredHeight: 250
|
||||
Layout.preferredWidth: 250
|
||||
//initialItem: loginComponent
|
||||
}
|
||||
Component{
|
||||
id: accountListComponent
|
||||
ListView{
|
||||
id: accountList
|
||||
Layout.fillHeight: true
|
||||
model: AccountProxy{}
|
||||
delegate:Rectangle{
|
||||
color: "#11111111"
|
||||
height: 20
|
||||
width: accountList.width
|
||||
Text{
|
||||
|
||||
text: modelData.core.identityAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: loginComponent
|
||||
LoginForm{}
|
||||
}
|
||||
Rectangle{
|
||||
id: accountStatus
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
property int accountCount: accountProxy.count
|
||||
onAccountCountChanged: console.log("AccountCount:"+accountCount)
|
||||
property var defaultAccount: accountProxy.defaultAccount
|
||||
onDefaultAccountChanged: console.log("DefaultAccount:"+defaultAccount)
|
||||
property var state: accountProxy.count > 0 && defaultAccount? defaultAccount.core.registrationState : LoginPageCpp.registrationState
|
||||
onStateChanged: console.log("State:"+state)
|
||||
|
||||
color: state === LinphoneEnums.RegistrationState.Ok
|
||||
? 'green'
|
||||
: state === LinphoneEnums.RegistrationState.Failed || state === LinphoneEnums.RegistrationState.None
|
||||
? 'red'
|
||||
: 'orange'
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked:{
|
||||
logStack.replace(loginComponent)
|
||||
gc()
|
||||
}
|
||||
}
|
||||
}
|
||||
TextInput {
|
||||
id: usernameToCall
|
||||
label: "Username to call"
|
||||
textInputWidth: 250
|
||||
}
|
||||
Button{
|
||||
text: 'Call'
|
||||
onClicked: {
|
||||
var address = usernameToCall.text + "@sip.linphone.org"
|
||||
console.log("Calling "+address)
|
||||
mainItem.callVarObject = UtilsCpp.createCall(address)
|
||||
proto.component1 = comp
|
||||
}
|
||||
}
|
||||
}
|
||||
TextInput {
|
||||
id: usernameToCall
|
||||
label: "Username to call"
|
||||
textInputWidth: 250
|
||||
}
|
||||
Button{
|
||||
text: 'Call'
|
||||
onClicked: {
|
||||
var address = usernameToCall.text + "@sip.linphone.org"
|
||||
console.log("Calling "+address)
|
||||
mainItem.callVarObject = UtilsCpp.createCall(address)
|
||||
proto.component1 = comp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 50
|
||||
color: call
|
||||
? call.core.state === LinphoneEnums.CallState.StreamsRunning
|
||||
? 'green'
|
||||
: call.core.state === LinphoneEnums.CallState.Released
|
||||
? 'pink'
|
||||
: 'orange'
|
||||
: 'red'
|
||||
|
||||
Rectangle{
|
||||
anchors.centerIn: parent
|
||||
color: 'white'
|
||||
width: stateText.contentWidth
|
||||
height: stateText.contentHeight
|
||||
Text{
|
||||
id: stateText
|
||||
text: "State:"+(mainItem.callState ? mainItem.callState : 'None')
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 50
|
||||
color: call
|
||||
? call.core.state === LinphoneEnums.CallState.StreamsRunning
|
||||
? 'green'
|
||||
: call.core.state === LinphoneEnums.CallState.Released
|
||||
? 'pink'
|
||||
: 'orange'
|
||||
: 'red'
|
||||
Rectangle{
|
||||
anchors.centerIn: parent
|
||||
color: 'white'
|
||||
width: stateText.contentWidth
|
||||
height: stateText.contentHeight
|
||||
Text{
|
||||
id: stateText
|
||||
text: "State:"+(mainItem.callState ? mainItem.callState : 'None')
|
||||
}
|
||||
}
|
||||
}
|
||||
Text{
|
||||
id: errorMessageText
|
||||
color: 'red'
|
||||
}
|
||||
ItemPrototype{
|
||||
id: proto
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Item{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Text{
|
||||
id: errorMessageText
|
||||
color: 'red'
|
||||
}
|
||||
ItemPrototype{
|
||||
id: proto
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Item{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: comp
|
||||
Rectangle{
|
||||
width: 100
|
||||
height: width
|
||||
color: 'pink'
|
||||
Component{
|
||||
id: comp
|
||||
Rectangle{
|
||||
width: 100
|
||||
height: width
|
||||
color: 'pink'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue