mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-07 14:44:01 +00:00
- Add Attended transfer feature (contributed by Chad Attermann)
- Fix crash on loading empty chat room
This commit is contained in:
parent
756f38e2ff
commit
cfdc3069f0
15 changed files with 1235 additions and 1105 deletions
|
|
@ -423,6 +423,16 @@
|
|||
<source>callPause</source>
|
||||
<translation>HOLD CALL</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>attendedTransferComplete</source>
|
||||
<extracomment>'COMPLETE ATTENDED TRANSFER' : Title button, design is in uppercase.</extracomment>
|
||||
<translation>COMPLETE ATTENDED TRANSFER</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>attendedTransferCall</source>
|
||||
<extracomment>'ATTENDED TRANSFER CALL' : Title button, design is in uppercase.</extracomment>
|
||||
<translation>ATTENDED TRANSFER CALL</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CallsWindow</name>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ static void cliCall (QHash<QString, QString> &args) {
|
|||
app->processArguments(args);
|
||||
app->initContentApp();
|
||||
}else
|
||||
CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sip-address"]);
|
||||
CoreManager::getInstance()->getCallsListModel()->launchAudioCall(args["sip-address"], "");
|
||||
}
|
||||
|
||||
static void cliBye (QHash<QString, QString> &args) {
|
||||
|
|
@ -89,7 +89,7 @@ static void cliJoinConference (QHash<QString, QString> &args) {
|
|||
}
|
||||
|
||||
args["method"] = QStringLiteral("join-conference");
|
||||
coreManager->getCallsListModel()->launchAudioCall(sipAddress, args);
|
||||
coreManager->getCallsListModel()->launchAudioCall(sipAddress, "", args);
|
||||
}
|
||||
|
||||
static void cliJoinConferenceAs (QHash<QString, QString> &args) {
|
||||
|
|
@ -121,7 +121,7 @@ static void cliJoinConferenceAs (QHash<QString, QString> &args) {
|
|||
}
|
||||
|
||||
args["method"] = QStringLiteral("join-conference");
|
||||
coreManager->getCallsListModel()->launchAudioCall(toSipAddress, args);
|
||||
coreManager->getCallsListModel()->launchAudioCall(toSipAddress, "", args);
|
||||
}
|
||||
|
||||
static void cliInitiateConference (QHash<QString, QString> &args) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,237 +30,243 @@ class ContactModel;
|
|||
class ChatRoomModel;
|
||||
|
||||
class CallModel : public QObject {
|
||||
Q_OBJECT;
|
||||
|
||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT);
|
||||
Q_PROPERTY(QString localAddress READ getLocalAddress CONSTANT);
|
||||
Q_PROPERTY(QString fullPeerAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged);
|
||||
Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress CONSTANT);
|
||||
Q_OBJECT;
|
||||
|
||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT);
|
||||
Q_PROPERTY(QString localAddress READ getLocalAddress CONSTANT);
|
||||
Q_PROPERTY(QString fullPeerAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged);
|
||||
Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress CONSTANT);
|
||||
|
||||
Q_PROPERTY(ContactModel *contactModel READ getContactModel CONSTANT )
|
||||
Q_PROPERTY(ChatRoomModel * chatRoomModel READ getChatRoomModel CONSTANT)
|
||||
|
||||
/*
|
||||
Q_PROPERTY(QString sipAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged)
|
||||
Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged)
|
||||
Q_PROPERTY(QString avatar READ getAvatar NOTIFY avatarChanged)
|
||||
Q_PROPERTY(int presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged)*/
|
||||
|
||||
Q_PROPERTY(CallStatus status READ getStatus NOTIFY statusChanged);
|
||||
Q_PROPERTY(QString callError READ getCallError NOTIFY callErrorChanged);
|
||||
|
||||
Q_PROPERTY(bool isOutgoing READ isOutgoing CONSTANT);
|
||||
|
||||
Q_PROPERTY(bool isInConference READ isInConference NOTIFY isInConferenceChanged);
|
||||
|
||||
Q_PROPERTY(int duration READ getDuration CONSTANT); // Constants but called with a timer in qml.
|
||||
Q_PROPERTY(float quality READ getQuality CONSTANT);
|
||||
Q_PROPERTY(float speakerVu READ getSpeakerVu CONSTANT);
|
||||
Q_PROPERTY(float microVu READ getMicroVu CONSTANT);
|
||||
|
||||
Q_PROPERTY(bool speakerMuted READ getSpeakerMuted WRITE setSpeakerMuted NOTIFY speakerMutedChanged);
|
||||
Q_PROPERTY(bool microMuted READ getMicroMuted WRITE setMicroMuted NOTIFY microMutedChanged);
|
||||
|
||||
Q_PROPERTY(bool pausedByUser READ getPausedByUser WRITE setPausedByUser NOTIFY statusChanged);
|
||||
Q_PROPERTY(bool videoEnabled READ getVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged);
|
||||
Q_PROPERTY(bool updating READ getUpdating NOTIFY statusChanged)
|
||||
|
||||
Q_PROPERTY(bool recording READ getRecording NOTIFY recordingChanged);
|
||||
|
||||
Q_PROPERTY(QVariantList audioStats READ getAudioStats NOTIFY statsUpdated);
|
||||
Q_PROPERTY(QVariantList videoStats READ getVideoStats NOTIFY statsUpdated);
|
||||
|
||||
Q_PROPERTY(CallEncryption encryption READ getEncryption NOTIFY securityUpdated);
|
||||
Q_PROPERTY(bool isSecured READ isSecured NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString localSas READ getLocalSas NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString remoteSas READ getRemoteSas NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString securedString READ getSecuredString NOTIFY securityUpdated);
|
||||
|
||||
Q_PROPERTY(float speakerVolumeGain READ getSpeakerVolumeGain WRITE setSpeakerVolumeGain NOTIFY speakerVolumeGainChanged);
|
||||
Q_PROPERTY(float microVolumeGain READ getMicroVolumeGain WRITE setMicroVolumeGain NOTIFY microVolumeGainChanged);
|
||||
|
||||
|
||||
|
||||
Q_PROPERTY(CallStatus status READ getStatus NOTIFY statusChanged);
|
||||
Q_PROPERTY(QString callError READ getCallError NOTIFY callErrorChanged);
|
||||
|
||||
Q_PROPERTY(bool isOutgoing READ isOutgoing CONSTANT);
|
||||
|
||||
Q_PROPERTY(bool isInConference READ isInConference NOTIFY isInConferenceChanged);
|
||||
|
||||
Q_PROPERTY(int duration READ getDuration CONSTANT); // Constants but called with a timer in qml.
|
||||
Q_PROPERTY(float quality READ getQuality CONSTANT);
|
||||
Q_PROPERTY(float speakerVu READ getSpeakerVu CONSTANT);
|
||||
Q_PROPERTY(float microVu READ getMicroVu CONSTANT);
|
||||
|
||||
Q_PROPERTY(bool speakerMuted READ getSpeakerMuted WRITE setSpeakerMuted NOTIFY speakerMutedChanged);
|
||||
Q_PROPERTY(bool microMuted READ getMicroMuted WRITE setMicroMuted NOTIFY microMutedChanged);
|
||||
|
||||
Q_PROPERTY(float speakerVolumeGain READ getSpeakerVolumeGain WRITE setSpeakerVolumeGain NOTIFY speakerVolumeGainChanged);
|
||||
Q_PROPERTY(float microVolumeGain READ getMicroVolumeGain WRITE setMicroVolumeGain NOTIFY microVolumeGainChanged);
|
||||
|
||||
Q_PROPERTY(bool pausedByUser READ getPausedByUser WRITE setPausedByUser NOTIFY statusChanged);
|
||||
Q_PROPERTY(bool videoEnabled READ getVideoEnabled WRITE setVideoEnabled NOTIFY statusChanged);
|
||||
Q_PROPERTY(bool updating READ getUpdating NOTIFY statusChanged)
|
||||
|
||||
Q_PROPERTY(bool recording READ getRecording NOTIFY recordingChanged);
|
||||
|
||||
Q_PROPERTY(QVariantList audioStats READ getAudioStats NOTIFY statsUpdated);
|
||||
Q_PROPERTY(QVariantList videoStats READ getVideoStats NOTIFY statsUpdated);
|
||||
|
||||
Q_PROPERTY(CallEncryption encryption READ getEncryption NOTIFY securityUpdated);
|
||||
Q_PROPERTY(bool isSecured READ isSecured NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString localSas READ getLocalSas NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString remoteSas READ getRemoteSas NOTIFY securityUpdated);
|
||||
Q_PROPERTY(QString securedString READ getSecuredString NOTIFY securityUpdated);
|
||||
|
||||
Q_PROPERTY(QString transferAddress READ getTransferAddress WRITE setTransferAddress NOTIFY transferAddressChanged);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
enum CallStatus {
|
||||
CallStatusConnected,
|
||||
CallStatusEnded,
|
||||
CallStatusIdle,
|
||||
CallStatusIncoming,
|
||||
CallStatusOutgoing,
|
||||
CallStatusPaused
|
||||
};
|
||||
Q_ENUM(CallStatus);
|
||||
|
||||
enum CallEncryption {
|
||||
CallEncryptionNone = int(linphone::MediaEncryption::None),
|
||||
CallEncryptionDtls = int(linphone::MediaEncryption::DTLS),
|
||||
CallEncryptionSrtp = int(linphone::MediaEncryption::SRTP),
|
||||
CallEncryptionZrtp = int(linphone::MediaEncryption::ZRTP)
|
||||
};
|
||||
Q_ENUM(CallEncryption);
|
||||
|
||||
CallModel (std::shared_ptr<linphone::Call> call);
|
||||
~CallModel ();
|
||||
|
||||
std::shared_ptr<linphone::Call> getCall () const {
|
||||
return mCall;
|
||||
}
|
||||
|
||||
QString getPeerAddress () const;
|
||||
QString getLocalAddress () const;
|
||||
QString getFullPeerAddress () const;
|
||||
QString getFullLocalAddress () const;
|
||||
|
||||
ContactModel *getContactModel() const;
|
||||
|
||||
ChatRoomModel * getChatRoomModel() const;
|
||||
|
||||
bool isInConference () const {
|
||||
return mIsInConference;
|
||||
}
|
||||
|
||||
void setRecordFile (const std::shared_ptr<linphone::CallParams> &callParams);
|
||||
static void setRecordFile (const std::shared_ptr<linphone::CallParams> &callParams, const QString &to);
|
||||
|
||||
void updateStats (const std::shared_ptr<const linphone::CallStats> &callStats);
|
||||
|
||||
void notifyCameraFirstFrameReceived (unsigned int width, unsigned int height);
|
||||
|
||||
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 ();
|
||||
|
||||
Q_INVOKABLE void takeSnapshot ();
|
||||
|
||||
Q_INVOKABLE void startRecording ();
|
||||
Q_INVOKABLE void stopRecording ();
|
||||
|
||||
Q_INVOKABLE void sendDtmf (const QString &dtmf);
|
||||
|
||||
Q_INVOKABLE void verifyAuthenticationToken (bool verify);
|
||||
|
||||
Q_INVOKABLE void updateStreams ();
|
||||
|
||||
Q_INVOKABLE void toggleSpeakerMute();
|
||||
|
||||
void setRemoteDisplayName(const std::string& name);
|
||||
|
||||
static constexpr int DtmfSoundDelay = 200;
|
||||
|
||||
std::shared_ptr<linphone::Call> mCall;
|
||||
std::shared_ptr<linphone::Address> mRemoteAddress;
|
||||
std::shared_ptr<linphone::MagicSearch> mMagicSearch;
|
||||
|
||||
enum CallStatus {
|
||||
CallStatusConnected,
|
||||
CallStatusEnded,
|
||||
CallStatusIdle,
|
||||
CallStatusIncoming,
|
||||
CallStatusOutgoing,
|
||||
CallStatusPaused
|
||||
};
|
||||
Q_ENUM(CallStatus);
|
||||
|
||||
enum CallEncryption {
|
||||
CallEncryptionNone = int(linphone::MediaEncryption::None),
|
||||
CallEncryptionDtls = int(linphone::MediaEncryption::DTLS),
|
||||
CallEncryptionSrtp = int(linphone::MediaEncryption::SRTP),
|
||||
CallEncryptionZrtp = int(linphone::MediaEncryption::ZRTP)
|
||||
};
|
||||
Q_ENUM(CallEncryption);
|
||||
|
||||
CallModel (std::shared_ptr<linphone::Call> call);
|
||||
~CallModel ();
|
||||
|
||||
std::shared_ptr<linphone::Call> getCall () const {
|
||||
return mCall;
|
||||
}
|
||||
|
||||
QString getPeerAddress () const;
|
||||
QString getLocalAddress () const;
|
||||
QString getFullPeerAddress () const;
|
||||
QString getFullLocalAddress () const;
|
||||
|
||||
ContactModel *getContactModel() const;
|
||||
|
||||
ChatRoomModel * getChatRoomModel() const;
|
||||
|
||||
bool isInConference () const {
|
||||
return mIsInConference;
|
||||
}
|
||||
|
||||
void setRecordFile (const std::shared_ptr<linphone::CallParams> &callParams);
|
||||
static void setRecordFile (const std::shared_ptr<linphone::CallParams> &callParams, const QString &to);
|
||||
|
||||
void updateStats (const std::shared_ptr<const linphone::CallStats> &callStats);
|
||||
|
||||
void notifyCameraFirstFrameReceived (unsigned int width, unsigned int height);
|
||||
|
||||
Q_INVOKABLE void accept ();
|
||||
Q_INVOKABLE void acceptWithVideo ();
|
||||
Q_INVOKABLE void terminate ();
|
||||
|
||||
Q_INVOKABLE void askForTransfer ();
|
||||
Q_INVOKABLE void askForAttendedTransfer ();
|
||||
Q_INVOKABLE bool transferTo (const QString &sipAddress);
|
||||
Q_INVOKABLE bool transferToAnother (const QString &peerAddress);
|
||||
|
||||
Q_INVOKABLE void acceptVideoRequest ();
|
||||
Q_INVOKABLE void rejectVideoRequest ();
|
||||
|
||||
Q_INVOKABLE void takeSnapshot ();
|
||||
|
||||
Q_INVOKABLE void startRecording ();
|
||||
Q_INVOKABLE void stopRecording ();
|
||||
|
||||
Q_INVOKABLE void sendDtmf (const QString &dtmf);
|
||||
|
||||
Q_INVOKABLE void verifyAuthenticationToken (bool verify);
|
||||
|
||||
Q_INVOKABLE void updateStreams ();
|
||||
|
||||
Q_INVOKABLE void toggleSpeakerMute();
|
||||
|
||||
void setRemoteDisplayName(const std::string& name);
|
||||
|
||||
QString getTransferAddress () const;
|
||||
void setTransferAddress (const QString &transferAddress);
|
||||
static void prepareTransfert(std::shared_ptr<linphone::Call> call, const QString& transfertAddress);
|
||||
|
||||
std::shared_ptr<linphone::Address> getRemoteAddress()const;
|
||||
|
||||
static constexpr int DtmfSoundDelay = 200;
|
||||
|
||||
std::shared_ptr<linphone::Call> mCall;
|
||||
std::shared_ptr<linphone::Address> mRemoteAddress;
|
||||
std::shared_ptr<linphone::MagicSearch> mMagicSearch;
|
||||
|
||||
public slots:
|
||||
// Set remote display name when a search has been done
|
||||
void searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> results);
|
||||
void callEnded();
|
||||
|
||||
// Set remote display name when a search has been done
|
||||
void searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> results);
|
||||
void callEnded();
|
||||
|
||||
signals:
|
||||
void callErrorChanged (const QString &callError);
|
||||
void isInConferenceChanged (bool status);
|
||||
void speakerMutedChanged (bool status);
|
||||
void microMutedChanged (bool status);
|
||||
void recordingChanged (bool status);
|
||||
void statsUpdated ();
|
||||
void statusChanged (CallStatus status);
|
||||
void videoRequested ();
|
||||
void securityUpdated ();
|
||||
void speakerVolumeGainChanged (float volume);
|
||||
void microVolumeGainChanged (float volume);
|
||||
|
||||
void cameraFirstFrameReceived (unsigned int width, unsigned int height);
|
||||
|
||||
void fullPeerAddressChanged();
|
||||
|
||||
void callErrorChanged (const QString &callError);
|
||||
void isInConferenceChanged (bool status);
|
||||
void speakerMutedChanged (bool status);
|
||||
void microMutedChanged (bool status);
|
||||
void recordingChanged (bool status);
|
||||
void statsUpdated ();
|
||||
void statusChanged (CallStatus status);
|
||||
void videoRequested ();
|
||||
void securityUpdated ();
|
||||
void speakerVolumeGainChanged (float volume);
|
||||
void microVolumeGainChanged (float volume);
|
||||
|
||||
void cameraFirstFrameReceived (unsigned int width, unsigned int height);
|
||||
|
||||
void fullPeerAddressChanged();
|
||||
void transferAddressChanged (const QString &transferAddress);
|
||||
|
||||
private:
|
||||
void handleCallEncryptionChanged (const std::shared_ptr<linphone::Call> &call);
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
||||
void accept (bool withVideo);
|
||||
|
||||
void stopAutoAnswerTimer () const;
|
||||
|
||||
CallStatus getStatus () const;
|
||||
|
||||
bool isOutgoing () const {
|
||||
return mCall->getDir() == linphone::Call::Dir::Outgoing;
|
||||
}
|
||||
|
||||
void updateIsInConference ();
|
||||
|
||||
void acceptWithAutoAnswerDelay ();
|
||||
|
||||
QString getCallError () const;
|
||||
void setCallErrorFromReason (linphone::Reason reason);
|
||||
|
||||
int getDuration () const;
|
||||
float getQuality () const;
|
||||
float getMicroVu () const;
|
||||
float getSpeakerVu () const;
|
||||
|
||||
bool getSpeakerMuted () const;
|
||||
void setSpeakerMuted (bool status);
|
||||
|
||||
bool getMicroMuted () const;
|
||||
void setMicroMuted (bool status);
|
||||
|
||||
bool getPausedByUser () const;
|
||||
void setPausedByUser (bool status);
|
||||
|
||||
bool getVideoEnabled () const;
|
||||
void setVideoEnabled (bool status);
|
||||
|
||||
bool getUpdating () const;
|
||||
|
||||
bool getRecording () const;
|
||||
|
||||
CallEncryption getEncryption () const;
|
||||
bool isSecured () const;
|
||||
|
||||
QString getLocalSas () const;
|
||||
QString getRemoteSas () const;
|
||||
|
||||
QString getSecuredString () const;
|
||||
|
||||
QVariantList getAudioStats () const;
|
||||
QVariantList getVideoStats () const;
|
||||
void updateStats (const std::shared_ptr<const linphone::CallStats> &callStats, QVariantList &statsList);
|
||||
|
||||
QString iceStateToString (linphone::IceState state) const;
|
||||
|
||||
float getSpeakerVolumeGain () const;
|
||||
void setSpeakerVolumeGain (float volume);
|
||||
|
||||
float getMicroVolumeGain () const;
|
||||
void setMicroVolumeGain (float volume);
|
||||
|
||||
QString generateSavedFilename () const;
|
||||
|
||||
static QString generateSavedFilename (const QString &from, const QString &to);
|
||||
|
||||
bool mIsInConference = false;
|
||||
|
||||
bool mPausedByRemote = false;
|
||||
bool mPausedByUser = false;
|
||||
bool mRecording = false;
|
||||
|
||||
bool mWasConnected = false;
|
||||
|
||||
bool mNotifyCameraFirstFrameReceived = true;
|
||||
|
||||
QString mCallError;
|
||||
|
||||
QVariantList mAudioStats;
|
||||
QVariantList mVideoStats;
|
||||
std::shared_ptr<SearchHandler> mSearch;
|
||||
void handleCallEncryptionChanged (const std::shared_ptr<linphone::Call> &call);
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
||||
void accept (bool withVideo);
|
||||
|
||||
void stopAutoAnswerTimer () const;
|
||||
|
||||
CallStatus getStatus () const;
|
||||
|
||||
bool isOutgoing () const {
|
||||
return mCall->getDir() == linphone::Call::Dir::Outgoing;
|
||||
}
|
||||
|
||||
void updateIsInConference ();
|
||||
|
||||
void acceptWithAutoAnswerDelay ();
|
||||
|
||||
QString getCallError () const;
|
||||
void setCallErrorFromReason (linphone::Reason reason);
|
||||
|
||||
int getDuration () const;
|
||||
float getQuality () const;
|
||||
float getMicroVu () const;
|
||||
float getSpeakerVu () const;
|
||||
|
||||
bool getSpeakerMuted () const;
|
||||
void setSpeakerMuted (bool status);
|
||||
|
||||
bool getMicroMuted () const;
|
||||
void setMicroMuted (bool status);
|
||||
|
||||
bool getPausedByUser () const;
|
||||
void setPausedByUser (bool status);
|
||||
|
||||
bool getVideoEnabled () const;
|
||||
void setVideoEnabled (bool status);
|
||||
|
||||
bool getUpdating () const;
|
||||
|
||||
bool getRecording () const;
|
||||
|
||||
CallEncryption getEncryption () const;
|
||||
bool isSecured () const;
|
||||
|
||||
QString getLocalSas () const;
|
||||
QString getRemoteSas () const;
|
||||
|
||||
QString getSecuredString () const;
|
||||
|
||||
QVariantList getAudioStats () const;
|
||||
QVariantList getVideoStats () const;
|
||||
void updateStats (const std::shared_ptr<const linphone::CallStats> &callStats, QVariantList &statsList);
|
||||
|
||||
QString iceStateToString (linphone::IceState state) const;
|
||||
|
||||
float getSpeakerVolumeGain () const;
|
||||
void setSpeakerVolumeGain (float volume);
|
||||
|
||||
float getMicroVolumeGain () const;
|
||||
void setMicroVolumeGain (float volume);
|
||||
|
||||
QString generateSavedFilename () const;
|
||||
|
||||
static QString generateSavedFilename (const QString &from, const QString &to);
|
||||
|
||||
bool mIsInConference = false;
|
||||
|
||||
bool mPausedByRemote = false;
|
||||
bool mPausedByUser = false;
|
||||
bool mRecording = false;
|
||||
|
||||
bool mWasConnected = false;
|
||||
|
||||
bool mNotifyCameraFirstFrameReceived = true;
|
||||
|
||||
QString mCallError;
|
||||
|
||||
QVariantList mAudioStats;
|
||||
QVariantList mVideoStats;
|
||||
std::shared_ptr<SearchHandler> mSearch;
|
||||
QString mTransferAddress;
|
||||
};
|
||||
|
||||
#endif // CALL_MODEL_H_
|
||||
|
|
|
|||
|
|
@ -93,15 +93,27 @@ QVariant CallsListModel::data (const QModelIndex &index, int role) const {
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
CallModel *CallsListModel::findCallModelFromPeerAddress (const QString &peerAddress) const {
|
||||
std::shared_ptr<linphone::Address> address = Utils::interpretUrl(peerAddress);
|
||||
auto it = find_if(mList.begin(), mList.end(), [address](CallModel *callModel) {
|
||||
return callModel->getRemoteAddress()->weakEqual(address);
|
||||
});
|
||||
return it != mList.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CallsListModel::askForTransfer (CallModel *callModel) {
|
||||
emit callTransferAsked(callModel);
|
||||
}
|
||||
|
||||
void CallsListModel::askForAttendedTransfer (CallModel *callModel) {
|
||||
emit callAttendedTransferAsked(callModel);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CallsListModel::launchAudioCall (const QString &sipAddress, const QHash<QString, QString> &headers) const {
|
||||
void CallsListModel::launchAudioCall (const QString &sipAddress, const QString& prepareTransfertAddress, const QHash<QString, QString> &headers) const {
|
||||
CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = true;
|
||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||
|
||||
|
|
@ -122,23 +134,23 @@ void CallsListModel::launchAudioCall (const QString &sipAddress, const QHash<QSt
|
|||
shared_ptr<linphone::ProxyConfig> currentProxyConfig = core->getDefaultProxyConfig();
|
||||
if(currentProxyConfig){
|
||||
if(!CoreManager::getInstance()->getSettingsModel()->getWaitRegistrationForCall() || currentProxyConfig->getState() == linphone::RegistrationState::Ok)
|
||||
core->inviteAddressWithParams(address, params);
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
else{
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged,context,
|
||||
[address,core,params,currentProxyConfig, context](const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state) mutable {
|
||||
[address,core,params,currentProxyConfig,prepareTransfertAddress, context](const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state) mutable {
|
||||
if(context && proxyConfig==currentProxyConfig && state==linphone::RegistrationState::Ok){
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
delete context;
|
||||
context = nullptr;
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
}else
|
||||
core->inviteAddressWithParams(address, params);
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
}
|
||||
|
||||
void CallsListModel::launchSecureAudioCall (const QString &sipAddress, LinphoneEnums::MediaEncryption encryption, const QHash<QString, QString> &headers) const {
|
||||
void CallsListModel::launchSecureAudioCall (const QString &sipAddress, LinphoneEnums::MediaEncryption encryption, const QHash<QString, QString> &headers, const QString& prepareTransfertAddress) const {
|
||||
CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = true;
|
||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||
|
||||
|
|
@ -160,28 +172,28 @@ void CallsListModel::launchSecureAudioCall (const QString &sipAddress, LinphoneE
|
|||
params->setMediaEncryption(LinphoneEnums::toLinphone(encryption));
|
||||
if(currentProxyConfig){
|
||||
if(!CoreManager::getInstance()->getSettingsModel()->getWaitRegistrationForCall() || currentProxyConfig->getState() == linphone::RegistrationState::Ok)
|
||||
core->inviteAddressWithParams(address, params);
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
else{
|
||||
QObject * context = new QObject();
|
||||
QObject::connect(CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged,context,
|
||||
[address,core,params,currentProxyConfig, context](const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state) mutable {
|
||||
[address,core,params,currentProxyConfig,prepareTransfertAddress, context](const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state) mutable {
|
||||
if(context && proxyConfig==currentProxyConfig && state==linphone::RegistrationState::Ok){
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
delete context;
|
||||
context = nullptr;
|
||||
core->inviteAddressWithParams(address, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
}else
|
||||
core->inviteAddressWithParams(address, params);
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
}
|
||||
|
||||
void CallsListModel::launchVideoCall (const QString &sipAddress) const {
|
||||
void CallsListModel::launchVideoCall (const QString &sipAddress, const QString& prepareTransfertAddress) const {
|
||||
CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = true;
|
||||
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
|
||||
if (!core->videoSupported()) {
|
||||
qWarning() << QStringLiteral("Unable to launch video call. (Video not supported.) Launching audio call...");
|
||||
launchAudioCall(sipAddress);
|
||||
launchAudioCall(sipAddress, prepareTransfertAddress, {});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +205,7 @@ void CallsListModel::launchVideoCall (const QString &sipAddress) const {
|
|||
params->enableVideo(true);
|
||||
params->setProxyConfig(core->getDefaultProxyConfig());
|
||||
CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
|
||||
core->inviteAddressWithParams(address, params);
|
||||
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);
|
||||
}
|
||||
|
||||
ChatRoomModel* CallsListModel::launchSecureChat (const QString &sipAddress) const {
|
||||
|
|
@ -249,7 +261,7 @@ ChatRoomModel* CallsListModel::createChat (const QString &participantAddress) co
|
|||
params->setBackend(linphone::ChatRoomBackend::Basic);
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> chatRoom = core->createChatRoom(params, localAddress, participants);
|
||||
|
||||
|
||||
if( chatRoom != nullptr){
|
||||
auto timelineList = CoreManager::getInstance()->getTimelineListModel();
|
||||
auto timeline = timelineList->getTimeline(chatRoom, true);
|
||||
|
|
@ -315,7 +327,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
|
|||
address = Utils::interpretUrl(participant);
|
||||
}
|
||||
if( address)
|
||||
chatRoomParticipants.push_back( address );
|
||||
chatRoomParticipants.push_back( address );
|
||||
}
|
||||
auto proxy = core->getDefaultProxyConfig();
|
||||
params->enableEncryption(securityLevel>0);
|
||||
|
|
@ -344,7 +356,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
|
|||
chatRoom = core->createChatRoom(params, localAddress, chatRoomParticipants);
|
||||
if(chatRoom != nullptr && admins.size() > 0)
|
||||
ChatRoomInitializer::setAdminsAsync(params->getSubject(), params->getBackend(), params->groupEnabled(), admins );
|
||||
timeline = timelineList->getTimeline(chatRoom, false);
|
||||
timeline = timelineList->getTimeline(chatRoom, false);
|
||||
}else{
|
||||
if(admins.size() > 0){
|
||||
ChatRoomInitializer::setAdminsSync(chatRoom, admins);
|
||||
|
|
@ -391,6 +403,7 @@ void CallsListModel::terminateCall (const QString& sipAddress) const{
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static void joinConference (const shared_ptr<linphone::Call> &call) {
|
||||
|
|
|
|||
|
|
@ -33,53 +33,56 @@ class ChatRoomModel;
|
|||
class CoreHandlers;
|
||||
|
||||
class CallsListModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CallsListModel (QObject *parent = Q_NULLPTR);
|
||||
|
||||
int rowCount (const QModelIndex &index = QModelIndex()) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames () const override;
|
||||
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void askForTransfer (CallModel *callModel);
|
||||
|
||||
Q_INVOKABLE void launchAudioCall (const QString &sipAddress, const QHash<QString, QString> &headers = {}) const;
|
||||
Q_INVOKABLE void launchSecureAudioCall (const QString &sipAddress, LinphoneEnums::MediaEncryption encryption, const QHash<QString, QString> &headers = {}) const;
|
||||
Q_INVOKABLE void launchVideoCall (const QString &sipAddress) const;
|
||||
Q_INVOKABLE ChatRoomModel* launchSecureChat (const QString &sipAddress) const;
|
||||
Q_INVOKABLE QVariantMap launchChat(const QString &sipAddress, const int& securityLevel) const;
|
||||
Q_INVOKABLE ChatRoomModel* createChat (const QString &participantAddress) const;
|
||||
Q_INVOKABLE ChatRoomModel* createChat (const CallModel * ) const;
|
||||
Q_INVOKABLE bool createSecureChat (const QString& subject, const QString &participantAddress) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap createChatRoom(const QString& subject, const int& securityLevel, const QVariantList& participants, const bool& selectAfterCreation) const;
|
||||
|
||||
Q_INVOKABLE int getRunningCallsNumber () const;
|
||||
|
||||
Q_INVOKABLE void terminateAllCalls () const;
|
||||
Q_INVOKABLE void terminateCall (const QString& sipAddress) const;
|
||||
|
||||
CallsListModel (QObject *parent = Q_NULLPTR);
|
||||
|
||||
int rowCount (const QModelIndex &index = QModelIndex()) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames () const override;
|
||||
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
CallModel *findCallModelFromPeerAddress (const QString &peerAddress) const;
|
||||
|
||||
void askForTransfer (CallModel *callModel);
|
||||
void askForAttendedTransfer (CallModel *callModel);
|
||||
|
||||
Q_INVOKABLE void launchAudioCall (const QString &sipAddress, const QString& prepareTransfertAddress = "", const QHash<QString, QString> &headers = {}) const;
|
||||
Q_INVOKABLE void launchSecureAudioCall (const QString &sipAddress, LinphoneEnums::MediaEncryption encryption, const QHash<QString, QString> &headers = {}, const QString& prepareTransfertAddress = "") const;
|
||||
Q_INVOKABLE void launchVideoCall (const QString &sipAddress, const QString& prepareTransfertAddress = "") const;
|
||||
Q_INVOKABLE ChatRoomModel* launchSecureChat (const QString &sipAddress) const;
|
||||
Q_INVOKABLE QVariantMap launchChat(const QString &sipAddress, const int& securityLevel) const;
|
||||
Q_INVOKABLE ChatRoomModel* createChat (const QString &participantAddress) const;
|
||||
Q_INVOKABLE ChatRoomModel* createChat (const CallModel * ) const;
|
||||
Q_INVOKABLE bool createSecureChat (const QString& subject, const QString &participantAddress) const;
|
||||
|
||||
Q_INVOKABLE QVariantMap createChatRoom(const QString& subject, const int& securityLevel, const QVariantList& participants, const bool& selectAfterCreation) const;
|
||||
|
||||
Q_INVOKABLE int getRunningCallsNumber () const;
|
||||
|
||||
Q_INVOKABLE void terminateAllCalls () const;
|
||||
Q_INVOKABLE void terminateCall (const QString& sipAddress) const;
|
||||
|
||||
signals:
|
||||
void callRunning (int index, CallModel *callModel);
|
||||
void callTransferAsked (CallModel *callModel);
|
||||
|
||||
void callMissed (CallModel *callModel);
|
||||
|
||||
void callRunning (int index, CallModel *callModel);
|
||||
void callTransferAsked (CallModel *callModel);
|
||||
void callAttendedTransferAsked (CallModel *callModel);
|
||||
|
||||
void callMissed (CallModel *callModel);
|
||||
|
||||
private:
|
||||
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
|
||||
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
||||
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;
|
||||
|
||||
std::shared_ptr<CoreHandlers> mCoreHandlers;
|
||||
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
|
||||
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
||||
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;
|
||||
|
||||
std::shared_ptr<CoreHandlers> mCoreHandlers;
|
||||
};
|
||||
|
||||
#endif // CALLS_LIST_MODEL_H_
|
||||
|
|
|
|||
|
|
@ -139,17 +139,19 @@ void ChatRoomProxyModel::compose (const QString& text) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomProxyModel::loadMoreEntries () {
|
||||
int count = rowCount();
|
||||
int parentCount = sourceModel()->rowCount();
|
||||
if (count == mMaxDisplayedEntries)
|
||||
mMaxDisplayedEntries += EntriesChunkSize;
|
||||
|
||||
if (count + 10 >= parentCount) // Magic number : try to load more entries if near to max event count
|
||||
mChatRoomModel->loadMoreEntries();
|
||||
invalidateFilter();
|
||||
count = rowCount() - count;
|
||||
if (count > 0)
|
||||
emit moreEntriesLoaded(count);
|
||||
if(mChatRoomModel ) {
|
||||
int count = rowCount();
|
||||
int parentCount = sourceModel()->rowCount();
|
||||
if (count == mMaxDisplayedEntries)
|
||||
mMaxDisplayedEntries += EntriesChunkSize;
|
||||
|
||||
if (count + 10 >= parentCount) // Magic number : try to load more entries if near to max event count
|
||||
mChatRoomModel->loadMoreEntries();
|
||||
invalidateFilter();
|
||||
count = rowCount() - count;
|
||||
if (count > 0)
|
||||
emit moreEntriesLoaded(count);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatRoomProxyModel::setEntryTypeFilter (int type) {
|
||||
|
|
|
|||
|
|
@ -30,123 +30,155 @@
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
function getParams (call) {
|
||||
if (!call) {
|
||||
return
|
||||
}
|
||||
|
||||
var CallModel = Linphone.CallModel
|
||||
var status = call.status
|
||||
|
||||
if (status === CallModel.CallStatusConnected) {
|
||||
var optActions = []
|
||||
if (Linphone.SettingsModel.callPauseEnabled) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = true }),
|
||||
name: qsTr('callPause')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: optActions.concat([{
|
||||
handler: call.askForTransfer,
|
||||
name: qsTr('transferCall')
|
||||
}, {
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'connected'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusEnded) {
|
||||
return {
|
||||
string: 'ended'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusIncoming) {
|
||||
var optActions = []
|
||||
if (Linphone.SettingsModel.videoSupported) {
|
||||
optActions.push({
|
||||
handler: call.acceptWithVideo,
|
||||
name: qsTr('acceptVideoCall')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: [{
|
||||
handler: (function () { call.accept() }),
|
||||
name: qsTr('acceptAudioCall')
|
||||
}].concat(optActions).concat([{
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'incoming'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusOutgoing) {
|
||||
return {
|
||||
component: callAction,
|
||||
handler: call.terminate,
|
||||
icon: 'hangup',
|
||||
string: 'outgoing'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusPaused) {
|
||||
var optActions = []
|
||||
if (call.pausedByUser) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = false }),
|
||||
name: qsTr('resumeCall')
|
||||
})
|
||||
} else if (Linphone.SettingsModel.callPauseEnabled) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = true }),
|
||||
name: qsTr('callPause')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: optActions.concat([{
|
||||
handler: call.askForTransfer,
|
||||
name: qsTr('transferCall')
|
||||
}, {
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'paused'
|
||||
}
|
||||
}
|
||||
if (!call) {
|
||||
return
|
||||
}
|
||||
|
||||
var CallModel = Linphone.CallModel
|
||||
var status = call.status
|
||||
|
||||
if (status === CallModel.CallStatusConnected) {
|
||||
var optActions = []
|
||||
if (Linphone.SettingsModel.callPauseEnabled) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = true }),
|
||||
name: qsTr('callPause')
|
||||
})
|
||||
}
|
||||
|
||||
if (call.transferAddress !== '') {
|
||||
optActions.push({
|
||||
handler: call.askForTransfer,
|
||||
//: 'COMPLETE ATTENDED TRANSFER' : Title button, design is in uppercase.
|
||||
name: qsTr('attendedTransferComplete')
|
||||
})
|
||||
}
|
||||
else {
|
||||
optActions.push({
|
||||
handler: call.askForTransfer,
|
||||
name: qsTr('transferCall')
|
||||
})
|
||||
optActions.push({
|
||||
handler: call.askForAttendedTransfer,
|
||||
//: 'ATTENDED TRANSFER CALL' : Title button, design is in uppercase.
|
||||
name: qsTr('attendedTransferCall')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: optActions.concat([{
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'connected'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusEnded) {
|
||||
return {
|
||||
string: 'ended'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusIncoming) {
|
||||
var optActions = []
|
||||
if (Linphone.SettingsModel.videoSupported) {
|
||||
optActions.push({
|
||||
handler: call.acceptWithVideo,
|
||||
name: qsTr('acceptVideoCall')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: [{
|
||||
handler: (function () { call.accept() }),
|
||||
name: qsTr('acceptAudioCall')
|
||||
}].concat(optActions).concat([{
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'incoming'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusOutgoing) {
|
||||
return {
|
||||
component: callAction,
|
||||
handler: call.terminate,
|
||||
icon: 'hangup',
|
||||
string: 'outgoing'
|
||||
}
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusPaused) {
|
||||
var optActions = []
|
||||
if (call.pausedByUser) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = false }),
|
||||
name: qsTr('resumeCall')
|
||||
})
|
||||
} else if (Linphone.SettingsModel.callPauseEnabled) {
|
||||
optActions.push({
|
||||
handler: (function () { call.pausedByUser = true }),
|
||||
name: qsTr('callPause')
|
||||
})
|
||||
}
|
||||
|
||||
if (call.transferAddress !== '') {
|
||||
optActions.push({
|
||||
handler: call.askForTransfer,
|
||||
//: 'COMPLETE ATTENDED TRANSFER' : Title button, design is in uppercase.
|
||||
name: qsTr('attendedTransferComplete')
|
||||
})
|
||||
}
|
||||
else {
|
||||
optActions.push({
|
||||
handler: call.askForTransfer,
|
||||
name: qsTr('transferCall')
|
||||
})
|
||||
optActions.push({
|
||||
handler: call.askForAttendedTransfer,
|
||||
//: 'ATTENDED TRANSFER CALL' : Title button, design is in uppercase.
|
||||
name: qsTr('attendedTransferCall')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
actions: optActions.concat([{
|
||||
handler: call.terminate,
|
||||
name: qsTr('terminateCall')
|
||||
}]),
|
||||
component: callActions,
|
||||
string: 'paused'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateSelectedCall (call, index) {
|
||||
calls._selectedCall = call
|
||||
if (index != null) {
|
||||
calls.currentIndex = index
|
||||
}
|
||||
calls._selectedCall = call
|
||||
if (index != null) {
|
||||
calls.currentIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
function resetSelectedCall () {
|
||||
updateSelectedCall(null, -1)
|
||||
updateSelectedCall(null, -1)
|
||||
}
|
||||
|
||||
function setIndexWithCall (call) {
|
||||
var count = calls.count
|
||||
var model = calls.model
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (call === model.data(model.index(i, 0))) {
|
||||
updateSelectedCall(call, i)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
updateSelectedCall(call, -1)
|
||||
var count = calls.count
|
||||
var model = calls.model
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (call === model.data(model.index(i, 0))) {
|
||||
updateSelectedCall(call, i)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
updateSelectedCall(call, -1)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -154,23 +186,23 @@ function setIndexWithCall (call) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
function handleCountChanged (count) {
|
||||
if (count === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
var call = calls._selectedCall
|
||||
|
||||
if (call == null) {
|
||||
if (calls.conferenceModel.count > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
var model = calls.model
|
||||
var index = count - 1
|
||||
updateSelectedCall(model.data(model.index(index, 0)), index)
|
||||
} else {
|
||||
setIndexWithCall(call)
|
||||
}
|
||||
if (count === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
var call = calls._selectedCall
|
||||
|
||||
if (call == null) {
|
||||
if (calls.conferenceModel.count > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
var model = calls.model
|
||||
var index = count - 1
|
||||
updateSelectedCall(model.data(model.index(index, 0)), index)
|
||||
} else {
|
||||
setIndexWithCall(call)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -178,36 +210,36 @@ function handleCountChanged (count) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
function handleCallRunning (call) {
|
||||
if (!call.isInConference) {
|
||||
setIndexWithCall(call)
|
||||
}
|
||||
if (!call.isInConference) {
|
||||
setIndexWithCall(call)
|
||||
}
|
||||
}
|
||||
|
||||
function handleRowsAboutToBeRemoved (_, first, last) {
|
||||
var index = calls.currentIndex
|
||||
|
||||
if (index >= first && index <= last) {
|
||||
resetSelectedCall()
|
||||
}
|
||||
var index = calls.currentIndex
|
||||
|
||||
if (index >= first && index <= last) {
|
||||
resetSelectedCall()
|
||||
}
|
||||
}
|
||||
|
||||
function handleRowsInserted (_, first, last) {
|
||||
// The last inserted outgoing element become the selected call.
|
||||
var model = calls.model
|
||||
for (var index = last; index >= first; index--) {
|
||||
var call = model.data(model.index(index, 0))
|
||||
|
||||
if (call.isOutgoing && !call.isInConference) {
|
||||
updateSelectedCall(call)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// First received call.
|
||||
if (first === 0 && model.rowCount() === 1) {
|
||||
var call = model.data(model.index(0, 0))
|
||||
if (!call.isInConference) {
|
||||
updateSelectedCall(model.data(model.index(0, 0)))
|
||||
}
|
||||
}
|
||||
// The last inserted outgoing element become the selected call.
|
||||
var model = calls.model
|
||||
for (var index = last; index >= first; index--) {
|
||||
var call = model.data(model.index(index, 0))
|
||||
|
||||
if (call.isOutgoing && !call.isInConference) {
|
||||
updateSelectedCall(call)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// First received call.
|
||||
if (first === 0 && model.rowCount() === 1) {
|
||||
var call = model.data(model.index(0, 0))
|
||||
if (!call.isInConference) {
|
||||
updateSelectedCall(model.data(model.index(0, 0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ Rectangle {
|
|||
|
||||
borderColor: ChatStyle.sendArea.border.color
|
||||
topWidth: ChatStyle.sendArea.border.width
|
||||
visible: SettingsModel.chatEnabled && !proxyModel.chatRoomModel.hasBeenLeft
|
||||
visible: SettingsModel.chatEnabled && proxyModel.chatRoomModel && !proxyModel.chatRoomModel.hasBeenLeft
|
||||
|
||||
DroppableTextArea {
|
||||
id: textArea
|
||||
|
|
|
|||
|
|
@ -28,86 +28,109 @@
|
|||
// =============================================================================
|
||||
|
||||
function handleClosing (close) {
|
||||
var callsList = Linphone.CallsListModel
|
||||
|
||||
window.detachVirtualWindow()
|
||||
|
||||
if (callsList.getRunningCallsNumber() === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), {
|
||||
descriptionText: qsTr('acceptClosingDescription')
|
||||
}, function (status) {
|
||||
if (status) {
|
||||
callsList.terminateAllCalls()
|
||||
window.close()
|
||||
}
|
||||
})
|
||||
|
||||
close.accepted = false
|
||||
var callsList = Linphone.CallsListModel
|
||||
|
||||
window.detachVirtualWindow()
|
||||
|
||||
if (callsList.getRunningCallsNumber() === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), {
|
||||
descriptionText: qsTr('acceptClosingDescription')
|
||||
}, function (status) {
|
||||
if (status) {
|
||||
callsList.terminateAllCalls()
|
||||
window.close()
|
||||
}
|
||||
})
|
||||
|
||||
close.accepted = false
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function openCallSipAddress () {
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallSipAddress.qml'))
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallSipAddress.qml'))
|
||||
}
|
||||
|
||||
function openConferenceManager (params, exitHandler) {
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/ConferenceManager.qml'), params, exitHandler)
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/ConferenceManager.qml'), params, exitHandler)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Used to get Component based from Call Status
|
||||
function getContent () {
|
||||
var call = window.call
|
||||
if (call == null) {
|
||||
return conference
|
||||
}
|
||||
|
||||
var status = call.status
|
||||
if (status == null) {
|
||||
return calls.conferenceModel.count > 0 ? conference : null
|
||||
}
|
||||
|
||||
var CallModel = Linphone.CallModel
|
||||
if (status === CallModel.CallStatusIncoming) {
|
||||
return incomingCall
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusOutgoing) {
|
||||
return outgoingCall
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusEnded) {
|
||||
return endedCall
|
||||
}
|
||||
|
||||
return incall
|
||||
var call = window.call
|
||||
if (call == null) {
|
||||
return conference
|
||||
}
|
||||
|
||||
var status = call.status
|
||||
if (status == null) {
|
||||
return calls.conferenceModel.count > 0 ? conference : null
|
||||
}
|
||||
|
||||
var CallModel = Linphone.CallModel
|
||||
if (status === CallModel.CallStatusIncoming) {
|
||||
return incomingCall
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusOutgoing) {
|
||||
return outgoingCall
|
||||
}
|
||||
|
||||
if (status === CallModel.CallStatusEnded) {
|
||||
return endedCall
|
||||
}
|
||||
|
||||
return incall
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function handleCallTransferAsked (call) {
|
||||
if (!call) {
|
||||
return
|
||||
}
|
||||
if (!call) {
|
||||
return
|
||||
}
|
||||
|
||||
if (call.transferAddress !== '') {
|
||||
console.debug('Attended transfer to call ' + call.transferAddress)
|
||||
call.transferToAnother(call.transferAddress)
|
||||
return
|
||||
}
|
||||
|
||||
window.detachVirtualWindow()
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallTransfer.qml'), {
|
||||
call: call,
|
||||
attended: false
|
||||
})
|
||||
}
|
||||
|
||||
window.detachVirtualWindow()
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallTransfer.qml'), {
|
||||
call: call
|
||||
})
|
||||
function handleCallAttendedTransferAsked (call) {
|
||||
if (!call) {
|
||||
return
|
||||
}
|
||||
if (call.transferAddress !== '') {
|
||||
console.debug('Attended transfer to call ' + call.transferAddress)
|
||||
call.transferToAnother(call.transferAddress)
|
||||
return
|
||||
}
|
||||
window.detachVirtualWindow()
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallTransfer.qml'), {
|
||||
call: call,
|
||||
attended: true
|
||||
})
|
||||
}
|
||||
|
||||
function windowMustBeClosed () {
|
||||
return Linphone.CallsListModel.rowCount() === 0 && !window.virtualWindowVisible
|
||||
return Linphone.CallsListModel.rowCount() === 0 && !window.virtualWindowVisible
|
||||
}
|
||||
|
||||
function tryToCloseWindow () {
|
||||
if (windowMustBeClosed()) {
|
||||
// Workaround, it's necessary to use a timeout because at last call termination
|
||||
// a segfault is emit in `QOpenGLContext::functions() const ()`.
|
||||
Utils.setTimeout(window, 0, function () { windowMustBeClosed() && window.close() })
|
||||
}
|
||||
if (windowMustBeClosed()) {
|
||||
// Workaround, it's necessary to use a timeout because at last call termination
|
||||
// a segfault is emit in `QOpenGLContext::functions() const ()`.
|
||||
Utils.setTimeout(window, 0, function () { windowMustBeClosed() && window.close() })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ Window {
|
|||
Connections {
|
||||
target: CallsListModel
|
||||
onCallTransferAsked: Logic.handleCallTransferAsked(callModel)
|
||||
onCallAttendedTransferAsked: Logic.handleCallAttendedTransferAsked(callModel)
|
||||
onRowsRemoved: Logic.tryToCloseWindow()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ DialogPlus {
|
|||
secure:0,
|
||||
visible:true,
|
||||
handler: function (entry) {
|
||||
CallsListModel.launchAudioCall(entry.sipAddress)
|
||||
CallsListModel.launchAudioCall(entry.sipAddress, "")
|
||||
exit(1)
|
||||
}
|
||||
}]
|
||||
|
|
|
|||
|
|
@ -9,93 +9,98 @@ import App.Styles 1.0
|
|||
// =============================================================================
|
||||
|
||||
DialogPlus {
|
||||
id: callTransfer
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property var call
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
buttons: [
|
||||
TextButtonA {
|
||||
text: qsTr('cancel')
|
||||
|
||||
onClicked: exit(0)
|
||||
}
|
||||
]
|
||||
|
||||
buttonsAlignment: Qt.AlignCenter
|
||||
descriptionText: qsTr('callTransferDescription')
|
||||
|
||||
height: CallTransferStyle.height + 30
|
||||
width: CallTransferStyle.width
|
||||
|
||||
onCallChanged: !call && exit(0)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Contact.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Contact {
|
||||
Layout.fillWidth: true
|
||||
|
||||
entry: SipAddressesModel.getSipAddressObserver(call ? call.fullPeerAddress : '', call ? call.fullLocalAddress : '')
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 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: SearchSipAddressesModel {
|
||||
id: sipAddressesModel
|
||||
}
|
||||
|
||||
onEntryClicked: actions[0].handler(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
id: callTransfer
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property var call
|
||||
property bool attended: false
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
buttons: [
|
||||
TextButtonA {
|
||||
text: qsTr('cancel')
|
||||
|
||||
onClicked: exit(0)
|
||||
}
|
||||
]
|
||||
|
||||
buttonsAlignment: Qt.AlignCenter
|
||||
descriptionText: qsTr('callTransferDescription')
|
||||
|
||||
height: CallTransferStyle.height + 30
|
||||
width: CallTransferStyle.width
|
||||
|
||||
onCallChanged: !call && exit(0)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Contact.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Contact {
|
||||
Layout.fillWidth: true
|
||||
|
||||
entry: SipAddressesModel.getSipAddressObserver(call ? call.fullPeerAddress : '', call ? call.fullLocalAddress : '')
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 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) {
|
||||
if (attended) {
|
||||
var call = CallsListModel.launchAudioCall(entry.sipAddress, callTransfer.call.peerAddress)
|
||||
} else {
|
||||
callTransfer.call.transferTo(entry.sipAddress)
|
||||
}
|
||||
exit(1)
|
||||
}
|
||||
}]
|
||||
|
||||
genSipAddress: filter.text
|
||||
|
||||
model: SearchSipAddressesModel {
|
||||
id: sipAddressesModel
|
||||
}
|
||||
|
||||
onEntryClicked: actions[0].handler(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,7 +259,6 @@ ColumnLayout {
|
|||
icon: 'group_chat'
|
||||
visible: SettingsModel.outgoingCallsEnabled && conversation.haveMoreThanOneParticipants && conversation.haveLessThanMinParticipantsForCall && !conversation.hasBeenLeft
|
||||
|
||||
//onClicked: CallsListModel.launchAudioCall(conversation.chatRoomModel)
|
||||
onClicked: Logic.openConferenceManager({chatRoomModel:conversation.chatRoomModel, autoCall:true})
|
||||
TooltipArea {
|
||||
//: "Call all chat room's participants" : tooltip on a button for calling all participant in the current chat room
|
||||
|
|
|
|||
|
|
@ -182,10 +182,10 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
onLaunchCall: CallsListModel.launchAudioCall(sipAddress)
|
||||
onLaunchCall: CallsListModel.launchAudioCall(sipAddress, "")
|
||||
onLaunchChat: CallsListModel.launchChat( sipAddress,0 )
|
||||
onLaunchSecureChat: CallsListModel.launchChat( sipAddress,1 )
|
||||
onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress)
|
||||
onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress, "")
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue