diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0925c545..0ccfeacda 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## 5.0.0 - [undefined]
+## 5.0.0 - 2022-12-07
### Added
- Video conference and iCalendars.
@@ -13,8 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New call layouts.
- Display a waiting room before going into a conference.
- Log viewer.
+- Read contacts from all friends lists.
- Option to set the display name in "using an account" tab of assistant.
- Long pressed buttons.
+- Date and Time pickers.
- Phone dialpad on main window.
- Animated file in chats/notifications.
- Round progress bar for transferring a file and allow to cancel it.
@@ -25,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Mark as Read synchronized between devices.
- Merge messages into one notification to avoid spam.
- Design overhaul on calls.
+- Audio devices can be changed while being in call.
- Use a cryptographic checksum when downloading openH264 from CISCO (Update to 2.2.0)
### Fixed
diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt
index 656baf131..431756981 100644
--- a/linphone-app/CMakeLists.txt
+++ b/linphone-app/CMakeLists.txt
@@ -204,6 +204,7 @@ set(SOURCES
src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp
src/components/file/FileDownloader.cpp
src/components/file/FileExtractor.cpp
+ src/components/friend/FriendListListener.cpp
src/components/history/HistoryModel.cpp
src/components/history/HistoryProxyModel.cpp
src/components/ldap/LdapModel.cpp
@@ -338,6 +339,7 @@ set(HEADERS
src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp
src/components/file/FileDownloader.hpp
src/components/file/FileExtractor.hpp
+ src/components/friend/FriendListListener.hpp
src/components/history/HistoryModel.hpp
src/components/history/HistoryProxyModel.hpp
src/components/ldap/LdapModel.hpp
diff --git a/linphone-app/assets/icons/genicons.sh b/linphone-app/assets/icons/genicons.sh
index 858411db9..360f52d04 100755
--- a/linphone-app/assets/icons/genicons.sh
+++ b/linphone-app/assets/icons/genicons.sh
@@ -25,3 +25,4 @@ do
inkscape -z -e hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg
done
convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico
+png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png
diff --git a/linphone-app/assets/icons/genicons_1.0.sh b/linphone-app/assets/icons/genicons_1.0.sh
index 2994f1b34..2ff6a9242 100755
--- a/linphone-app/assets/icons/genicons_1.0.sh
+++ b/linphone-app/assets/icons/genicons_1.0.sh
@@ -25,3 +25,4 @@ do
inkscape -z --export-type=png --export-file=hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg
done
convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico
+png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png
diff --git a/linphone-app/assets/icons/genicons_1.1.sh b/linphone-app/assets/icons/genicons_1.1.sh
index 19982c5e0..91d2b2fdc 100755
--- a/linphone-app/assets/icons/genicons_1.1.sh
+++ b/linphone-app/assets/icons/genicons_1.1.sh
@@ -25,3 +25,4 @@ do
inkscape -z --export-type=png --export-filename=hicolor/${i}x${i}/apps/icon.png -w $i -h $i ../images/linphone_logo.svg
done
convert hicolor/16x16/apps/icon.png hicolor/22x22/apps/icon.png hicolor/24x24/apps/icon.png hicolor/32x32/apps/icon.png hicolor/64x64/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png -colors 256 ../icon.ico
+png2icns ../../cmake_builder/linphone_package/macos/linphone.icns hicolor/16x16/apps/icon.png hicolor/32x32/apps/icon.png hicolor/128x128/apps/icon.png hicolor/256x256/apps/icon.png
diff --git a/linphone-app/assets/images/chat_room_custom.svg b/linphone-app/assets/images/chat_room_custom.svg
index 408e19619..a9d140c6d 100644
--- a/linphone-app/assets/images/chat_room_custom.svg
+++ b/linphone-app/assets/images/chat_room_custom.svg
@@ -3,16 +3,19 @@
width="80"
height="80"
viewBox="0 0 80 80"
+ fill="none"
version="1.1"
- id="svg21"
+ id="svg8"
sodipodi:docname="chat_room_custom.svg"
- inkscape:version="1.1 (c68e22c387, 2021-05-23)"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
+
-
-
-
-
-
+ inkscape:current-layer="svg8" />
-
-
-
-
-
-
-
-
-
-
+ id="g832"
+ transform="matrix(0.67345025,0,0,0.67345025,9.9999997,20)">
+
+
+
diff --git a/linphone-app/assets/images/conference_merge_custom.svg b/linphone-app/assets/images/conference_merge_custom.svg
new file mode 100644
index 000000000..8f195ab4b
--- /dev/null
+++ b/linphone-app/assets/images/conference_merge_custom.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/linphone-app/assets/images/draft_custom.svg b/linphone-app/assets/images/draft_custom.svg
deleted file mode 100644
index 069924dae..000000000
--- a/linphone-app/assets/images/draft_custom.svg
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
diff --git a/linphone-app/assets/languages/da.ts b/linphone-app/assets/languages/da.ts
index 9aa50fa99..ef140d3c4 100644
--- a/linphone-app/assets/languages/da.ts
+++ b/linphone-app/assets/languages/da.ts
@@ -569,6 +569,11 @@ Server url ikke konfigureret.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/de.ts b/linphone-app/assets/languages/de.ts
index 695bad434..978ccf4a7 100644
--- a/linphone-app/assets/languages/de.ts
+++ b/linphone-app/assets/languages/de.ts
@@ -569,6 +569,11 @@ Server URL ist nicht konfiguriert.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/en.ts b/linphone-app/assets/languages/en.ts
index 80206faa0..5f69dff3a 100644
--- a/linphone-app/assets/languages/en.ts
+++ b/linphone-app/assets/languages/en.ts
@@ -569,6 +569,11 @@ Server URL not configured.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
Do you really want do cancel this meeting?
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+ Meeting has been cancelled
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/es.ts b/linphone-app/assets/languages/es.ts
index 659fa342d..039bd89a1 100644
--- a/linphone-app/assets/languages/es.ts
+++ b/linphone-app/assets/languages/es.ts
@@ -569,6 +569,11 @@ URL del servidor no configurada.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/fr_FR.ts b/linphone-app/assets/languages/fr_FR.ts
index 64d39b8da..1360155b1 100644
--- a/linphone-app/assets/languages/fr_FR.ts
+++ b/linphone-app/assets/languages/fr_FR.ts
@@ -569,6 +569,11 @@ URL du serveur non configurée.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
Voulez-vous supprimer cette réunion ?
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+ La réunion a été annulée
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/hu.ts b/linphone-app/assets/languages/hu.ts
index 9a20f7ba0..ce392ee15 100644
--- a/linphone-app/assets/languages/hu.ts
+++ b/linphone-app/assets/languages/hu.ts
@@ -568,6 +568,11 @@ A kiszolgáló URL-je nincs konfigurálva.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/it.ts b/linphone-app/assets/languages/it.ts
index 36fe51dec..c4d768163 100644
--- a/linphone-app/assets/languages/it.ts
+++ b/linphone-app/assets/languages/it.ts
@@ -569,6 +569,11 @@ URL del server non configurato.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/ja.ts b/linphone-app/assets/languages/ja.ts
index d8bce574f..557a37a20 100644
--- a/linphone-app/assets/languages/ja.ts
+++ b/linphone-app/assets/languages/ja.ts
@@ -568,6 +568,11 @@
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/lt.ts b/linphone-app/assets/languages/lt.ts
index 360c55639..29cb489f1 100644
--- a/linphone-app/assets/languages/lt.ts
+++ b/linphone-app/assets/languages/lt.ts
@@ -570,6 +570,11 @@ Nesukonfigūruotas serverio url.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/pt_BR.ts b/linphone-app/assets/languages/pt_BR.ts
index 96a09ec62..aaced721e 100644
--- a/linphone-app/assets/languages/pt_BR.ts
+++ b/linphone-app/assets/languages/pt_BR.ts
@@ -569,6 +569,11 @@ URL do servidor não configurado.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/ru.ts b/linphone-app/assets/languages/ru.ts
index 2509e66ac..770bd2d14 100644
--- a/linphone-app/assets/languages/ru.ts
+++ b/linphone-app/assets/languages/ru.ts
@@ -570,6 +570,11 @@
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/sv.ts b/linphone-app/assets/languages/sv.ts
index 0f5b48209..da6160940 100644
--- a/linphone-app/assets/languages/sv.ts
+++ b/linphone-app/assets/languages/sv.ts
@@ -569,6 +569,11 @@ Serverwebbadressen är inte konfigurerad.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/tr.ts b/linphone-app/assets/languages/tr.ts
index d4ab8547c..9b6612885 100644
--- a/linphone-app/assets/languages/tr.ts
+++ b/linphone-app/assets/languages/tr.ts
@@ -568,6 +568,11 @@ Sunucu url'si yapılandırılmadı.
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/uk.ts b/linphone-app/assets/languages/uk.ts
index 603506eca..5f7d0b467 100644
--- a/linphone-app/assets/languages/uk.ts
+++ b/linphone-app/assets/languages/uk.ts
@@ -570,6 +570,11 @@
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/assets/languages/zh_CN.ts b/linphone-app/assets/languages/zh_CN.ts
index faa1aa2d5..f715c304e 100644
--- a/linphone-app/assets/languages/zh_CN.ts
+++ b/linphone-app/assets/languages/zh_CN.ts
@@ -568,6 +568,11 @@
'Do you really want do cancel this meeting?' : Warning message to confirm the cancellation of a meeting.
+
+ icsCancelledMeetingInvite
+ 'Meeting has been cancelled' : ICS Title for cancelled meetings
+
+
ChatConferenceInvitationMessage
diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc
index 41e57a845..a5ff5052e 100644
--- a/linphone-app/resources.qrc
+++ b/linphone-app/resources.qrc
@@ -62,6 +62,7 @@
assets/images/conference_audio_only_custom.svg
assets/images/conference_layout_grid_custom.svg
assets/images/conference_layout_active_speaker_custom.svg
+ assets/images/conference_merge_custom.svg
assets/images/contact_add_custom.svg
assets/images/contact_card_photo_custom.svg
assets/images/contact_custom.svg
@@ -77,7 +78,6 @@
assets/images/declined_outgoing_call_custom.svg
assets/images/delete_custom.svg
assets/images/download_custom.svg
- assets/images/draft_custom.svg
assets/images/drop_down_custom.svg
assets/images/edit_custom.svg
assets/images/ended_call_custom.svg
diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp
index 4dd083b69..2d6fd820a 100644
--- a/linphone-app/src/app/App.cpp
+++ b/linphone-app/src/app/App.cpp
@@ -153,7 +153,7 @@ static inline bool installLocale (App &app, QTranslator &translator, const QLoca
}
static inline string getConfigPathIfExists (const QCommandLineParser &parser) {
- QString filePath = parser.value("config");
+ QString filePath = parser.isSet("config") ? parser.value("config") : "";
string configPath;
if(!QUrl(filePath).isRelative()){
configPath = Utils::appStringToCoreString(FileDownloader::synchronousDownload(filePath, Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true));
@@ -217,12 +217,21 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
}
bctbx_set_default_encoding(Constants::LinphoneLocaleEncoding);// Use UTF-8 for internals. Linphone uses UTF-8 so there will be no loss on data with less precise encodings. Qt will do the rest.
+
createParser();
+ mParser->parse(this->arguments());
+// Get configuration for translators
+ shared_ptr config = Utils::getConfigIfExists (QString::fromStdString(getConfigPathIfExists(*mParser)));
+
+ // Init locale.
+ mTranslator = new DefaultTranslator(this);
+ mDefaultTranslator = new DefaultTranslator(this);
+ initLocale(config);
+ Logger::init(config);
+
+ createParser();// Recreate parser in order to use translations from config.
mParser->process(*this);
- // Initialize logger.
- shared_ptr config = Utils::getConfigIfExists (QString::fromStdString(getConfigPathIfExists(*mParser)));
- Logger::init(config);
if (mParser->isSet("verbose"))
Logger::getInstance()->setVerbose(true);
@@ -230,11 +239,6 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
for (const auto &locale : QDir(Constants::LanguagePath).entryList())
mAvailableLocales << QLocale(locale);
- // Init locale.
- mTranslator = new DefaultTranslator(this);
- mDefaultTranslator = new DefaultTranslator(this);
- initLocale(config);
-
if (mParser->isSet("help")) {
mParser->showHelp();
}
diff --git a/linphone-app/src/app/proxyModel/ProxyModel.cpp b/linphone-app/src/app/proxyModel/ProxyModel.cpp
index 9734c7ff2..d47472a0c 100644
--- a/linphone-app/src/app/proxyModel/ProxyModel.cpp
+++ b/linphone-app/src/app/proxyModel/ProxyModel.cpp
@@ -35,6 +35,19 @@ ProxyModel::ProxyModel (QAbstractItemModel * model, const int& defaultFilterMode
sort(0, Qt::DescendingOrder);
}
+ProxyModel::~ProxyModel(){
+ if(mDeleteSourceModel)
+ deleteSourceModel();
+}
+
+void ProxyModel::deleteSourceModel(){
+ auto oldSourceModel = sourceModel();
+ if(oldSourceModel) {
+ oldSourceModel->deleteLater();
+ setSourceModel(nullptr);
+ }
+}
+
int ProxyModel::getFilterMode () const {
return mFilterMode;
}
diff --git a/linphone-app/src/app/proxyModel/ProxyModel.hpp b/linphone-app/src/app/proxyModel/ProxyModel.hpp
index d85e950b8..a85bb45bb 100644
--- a/linphone-app/src/app/proxyModel/ProxyModel.hpp
+++ b/linphone-app/src/app/proxyModel/ProxyModel.hpp
@@ -35,6 +35,9 @@ public:
ProxyModel (QObject *parent = Q_NULLPTR);
ProxyModel (QAbstractItemModel * list, const int& defaultFilterMode, QObject *parent = Q_NULLPTR);
+ virtual ~ProxyModel();
+
+ virtual void deleteSourceModel();
int getFilterMode () const;
void setFilterMode (int filterMode);
@@ -56,6 +59,8 @@ protected:
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
+ bool mDeleteSourceModel = false;
+
private:
int mFilterMode;
};
diff --git a/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp b/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp
index f60c5149f..cc4da2f43 100644
--- a/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp
+++ b/linphone-app/src/app/proxyModel/SortFilterProxyModel.cpp
@@ -26,6 +26,19 @@ SortFilterProxyModel::SortFilterProxyModel(QObject * parent) : QSortFilterProxyM
connect(this, &SortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged);
}
+SortFilterProxyModel::~SortFilterProxyModel(){
+ if(mDeleteSourceModel)
+ deleteSourceModel();
+}
+
+void SortFilterProxyModel::deleteSourceModel(){
+ auto oldSourceModel = sourceModel();
+ if(oldSourceModel) {
+ oldSourceModel->deleteLater();
+ setSourceModel(nullptr);
+ }
+}
+
int SortFilterProxyModel::getCount() const{
return rowCount();
}
diff --git a/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp b/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp
index 518593faa..e0df17682 100644
--- a/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp
+++ b/linphone-app/src/app/proxyModel/SortFilterProxyModel.hpp
@@ -30,6 +30,8 @@ public:
Q_PROPERTY(int filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged)
SortFilterProxyModel(QObject * parent = nullptr);
+ virtual ~SortFilterProxyModel();
+ virtual void deleteSourceModel();
virtual int getCount() const;
virtual int getFilterType () const;
@@ -47,6 +49,7 @@ signals:
protected:
int mFilterType;
+ bool mDeleteSourceModel = false;
};
#endif
diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp
index e8a1a8623..63225c720 100644
--- a/linphone-app/src/components/call/CallModel.cpp
+++ b/linphone-app/src/components/call/CallModel.cpp
@@ -116,8 +116,10 @@ CallModel::CallModel (shared_ptr call){
if(mCall) {
mRemoteAddress = mCall->getRemoteAddress()->clone();
- if(mCall->getConference())
+ if(mCall->getConference()) {
mConferenceModel = ConferenceModel::create(mCall->getConference());
+ connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged);
+ }
auto conferenceInfo = CoreManager::getInstance()->getCore()->findConferenceInformationFromUri(getConferenceAddress());
if( conferenceInfo ){
mConferenceInfoModel = ConferenceInfoModel::create(conferenceInfo);
@@ -239,7 +241,8 @@ ConferenceInfoModel * CallModel::getConferenceInfoModel(){
QSharedPointer CallModel::getConferenceSharedModel(){
if(mCall->getConference() && !mConferenceModel){
- mConferenceModel = ConferenceModel::create(mCall->getConference());
+ mConferenceModel = ConferenceModel::create(mCall->getConference());
+ connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged);
emit conferenceModelChanged();
}
return mConferenceModel;
@@ -247,7 +250,24 @@ QSharedPointer CallModel::getConferenceSharedModel(){
bool CallModel::isConference () const{
// Check status to avoid crash when requesting a conference on an ended call.
- return mCall && (Utils::coreStringToAppString(mCall->getRemoteAddress()->asString()).toLower().contains("conf-id") || (getStatus() != CallStatusEnded && mCall->getConference() != nullptr));
+ bool isConf = false;
+ if(mCall){
+ // Do not call getConference on Ended status.
+ isConf = (getStatus() != CallStatusEnded && mCall->getConference() != nullptr) || mConferenceInfoModel != nullptr;
+
+ if(!isConf){// Check special cases for Linphone. Having conf-id for a conference URI is not standard.
+ auto remoteAddress = mCall->getRemoteAddress();
+ if( remoteAddress->getDomain() == Constants::LinphoneDomain){
+ isConf = remoteAddress->hasUriParam("conf-id");
+ }
+ }
+ }
+
+ return isConf;
+}
+
+bool CallModel::isOneToOne() const{
+ return !isConference();
}
// -----------------------------------------------------------------------------
@@ -972,6 +992,12 @@ void CallModel::onChatRoomInitialized(int state){
emit chatRoomModelChanged();
}
+void CallModel::onParticipantAdminStatusChanged(const std::shared_ptr & participant){
+ if(mConferenceModel && participant == mConferenceModel->getConference()->getMe()) {
+ emit meAdminChanged();
+ }
+}
+
void CallModel::setRemoteDisplayName(const std::string& name){
mRemoteAddress->setDisplayName(name);
if(mCall) {
diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp
index e11de11de..1d0c4f53f 100644
--- a/linphone-app/src/components/call/CallModel.hpp
+++ b/linphone-app/src/components/call/CallModel.hpp
@@ -55,7 +55,9 @@ class CallModel : public QObject {
Q_PROPERTY(bool isOutgoing READ isOutgoing CONSTANT)
Q_PROPERTY(bool isInConference READ isInConference NOTIFY isInConferenceChanged)
- Q_PROPERTY(bool isConference READ isConference CONSTANT)
+ Q_PROPERTY(bool isConference READ isConference NOTIFY conferenceInfoModelChanged)
+ Q_PROPERTY(bool isOneToOne READ isOneToOne NOTIFY conferenceInfoModelChanged)
+
Q_PROPERTY(int duration READ getDuration CONSTANT) // Constants but called with a timer in qml.
Q_PROPERTY(float quality READ getQuality CONSTANT)
@@ -145,6 +147,7 @@ public:
return mIsInConference;
}
bool isConference () const;
+ bool isOneToOne() const;
void setRecordFile (const std::shared_ptr &callParams);
static void setRecordFile (const std::shared_ptr &callParams, const QString &to);
@@ -205,8 +208,10 @@ public slots:
void endCall();
void onRemoteRecording(const std::shared_ptr & call, bool recording);
void onChatRoomInitialized(int state);
+ void onParticipantAdminStatusChanged(const std::shared_ptr & participant);
signals:
+ void meAdminChanged();
void callErrorChanged (const QString &callError);
void callIdChanged();
void isInConferenceChanged (bool status);
diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp
index e2c50ca14..4ab22c46b 100644
--- a/linphone-app/src/components/calls/CallsListModel.cpp
+++ b/linphone-app/src/components/calls/CallsListModel.cpp
@@ -69,6 +69,7 @@ CallsListModel::CallsListModel (QObject *parent) : ProxyListModel(parent) {
mCoreHandlers.get(), &CoreHandlers::callStateChanged,
this, &CallsListModel::handleCallStateChanged
);
+ connect(this, &CallsListModel::countChanged, this, &CallsListModel::canMergeCallsChanged);
}
CallModel *CallsListModel::findCallModelFromPeerAddress (const QString &peerAddress) const {
@@ -343,7 +344,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
initializer->setAdminsData(admins);
ChatRoomInitializer::start(initializer);
}
- timeline = timelineList->getTimeline(chatRoom, ChatRoomModel::isTerminated(chatRoom));
+ timeline = timelineList->getTimeline(chatRoom, true);
}else{
if(admins.size() > 0){
ChatRoomInitializer::create(chatRoom)->setAdmins(admins);
@@ -354,9 +355,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = false;
result["chatRoomModel"] = QVariant::fromValue(timeline->getChatRoomModel());
if(selectAfterCreation) {// The timeline here will not receive the first creation event. Set Selected if needed
- QTimer::singleShot(200, [timeline](){// Delay process in order to let GUI time for Timeline building/linking before doing actions
- timeline->setSelected(true);
- });
+ timeline->delaySelected();
}
}
}
@@ -368,19 +367,106 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
}
void CallsListModel::prepareConferenceCall(ConferenceInfoModel * model){
- auto app = App::getInstance();
- app->smartShowWindow(app->getCallsWindow());
- emit callConferenceAsked(model);
+ if(model->getConferenceInfoState() != LinphoneEnums::ConferenceInfoStateCancelled) {
+ auto app = App::getInstance();
+ app->smartShowWindow(app->getCallsWindow());
+ emit callConferenceAsked(model);
+ }
}
+
int CallsListModel::addAllToConference(){
return CoreManager::getInstance()->getCore()->addAllToConference();
}
+
+void CallsListModel::mergeAll(){
+ auto core = CoreManager::getInstance()->getCore();
+ auto currentCalls = CoreManager::getInstance()->getCore()->getCalls();
+ shared_ptr conference = core->getConference();
+
+ // Search a managable conference from calls
+ if(!conference){
+ for(auto call : currentCalls){
+ auto dbConference = call->getConference();
+ if(dbConference && dbConference->getMe()->isAdmin()){
+ conference = dbConference;
+ break;
+ }
+ }
+ }
+
+ auto currentCall = CoreManager::getInstance()->getCore()->getCurrentCall();
+ bool enablingVideo = false;
+ if( currentCall )
+ enablingVideo = currentCall->getCurrentParams()->videoEnabled();
+ if(!conference){
+ auto parameters = core->createConferenceParams(conference);
+
+ if(!CoreManager::getInstance()->getSettingsModel()->getVideoConferenceEnabled()) {
+ parameters->enableVideo(false);
+ parameters->setConferenceFactoryAddress(nullptr);// Do a local conference
+ parameters->setSubject("Local meeting");
+ }else{
+ parameters->enableVideo(enablingVideo);
+ parameters->setSubject("Meeting");
+ }
+ conference = core->createConferenceWithParams(parameters);
+ }
+
+ list> allLinphoneAddresses;
+ list> newCalls;
+ list> runningCallsToAdd;
+
+ for(auto call : currentCalls){
+ if(!call->getConference()){
+ runningCallsToAdd.push_back(call);
+ }
+ }
+
+// 1) Add running calls
+ if( runningCallsToAdd.size() > 0){
+ conference->addParticipants(runningCallsToAdd);
+ }
+ /*
+// 2) Put in pause and remove all calls that are not in the conference list
+ for(const auto &call : CoreManager::getInstance()->getCore()->getCalls()){
+ const std::string callAddress = call->getRemoteAddress()->asStringUriOnly();
+ auto address = allLinphoneAddresses.begin();
+ while(address != allLinphoneAddresses.end() && (*address)->asStringUriOnly() != callAddress)
+ ++address;
+ if(address == allLinphoneAddresses.end()){// Not in conference list : put in pause and remove it from conference if it's the case
+ if( call->getParams()->getLocalConferenceMode() ){// Remove conference if it is not yet requested
+ CoreManager::getInstance()->getCore()->removeFromConference(call);
+ }else
+ call->pause();
+ }
+ }*/
+}
// -----------------------------------------------------------------------------
int CallsListModel::getRunningCallsNumber () const {
return CoreManager::getInstance()->getCore()->getCallsNb();
}
+bool CallsListModel::canMergeCalls()const{
+ auto calls = CoreManager::getInstance()->getCore()->getCalls();
+
+ bool mergableConference = false;
+ int mergableCalls = 0;
+ bool mergable = false;
+ for(auto itCall = calls.begin(); !mergable && itCall != calls.end() ; ++itCall ) {
+ auto conference = (*itCall)->getConference();
+ if(conference){
+ if( !mergableConference )
+ mergableConference = (conference && conference->getMe()->isAdmin());
+ }else{
+ ++mergableCalls;
+ }
+ mergable = (mergableConference && mergableCalls>0) // A call can be merged into the conference
+ || mergableCalls>1;// 2 calls can be merged
+ }
+ return mergable;
+}
+
void CallsListModel::terminateAllCalls () const {
CoreManager::getInstance()->getCore()->terminateAllCalls();
}
@@ -479,6 +565,8 @@ void CallsListModel::addCall (const shared_ptr &call) {
qInfo() << QStringLiteral("Add call:") << callModel->getFullLocalAddress() << callModel->getFullPeerAddress();
App::getInstance()->getEngine()->setObjectOwnership(callModel.get(), QQmlEngine::CppOwnership);
+ connect(callModel.get(), &CallModel::meAdminChanged, this, &CallsListModel::canMergeCallsChanged);
+
add(callModel);
emit layoutChanged();
@@ -511,7 +599,7 @@ void CallsListModel::addDummyCall () {
int id = findCallIndex(mList, *callModel);
emit dataChanged(index(id, 0), index(id, 0));
});
-
+ connect(callModel.get(), &CallModel::meAdminChanged, this, &CallsListModel::canMergeCallsChanged);
add(callModel);
emit layoutChanged();
diff --git a/linphone-app/src/components/calls/CallsListModel.hpp b/linphone-app/src/components/calls/CallsListModel.hpp
index c7ed56ce1..1c774c039 100644
--- a/linphone-app/src/components/calls/CallsListModel.hpp
+++ b/linphone-app/src/components/calls/CallsListModel.hpp
@@ -37,6 +37,9 @@ class CallsListModel : public ProxyListModel {
Q_OBJECT
public:
+ Q_PROPERTY(bool canMergeCalls READ canMergeCalls NOTIFY canMergeCallsChanged)
+
+
CallsListModel (QObject *parent = Q_NULLPTR);
CallModel *findCallModelFromPeerAddress (const QString &peerAddress) const;
@@ -57,9 +60,11 @@ public:
Q_INVOKABLE void prepareConferenceCall(ConferenceInfoModel * model);
Q_INVOKABLE int addAllToConference();
+ Q_INVOKABLE void mergeAll();
Q_INVOKABLE int getRunningCallsNumber () const;
+ bool canMergeCalls()const;
Q_INVOKABLE void terminateAllCalls () const;
Q_INVOKABLE void terminateCall (const QString& sipAddress) const;
@@ -73,6 +78,7 @@ signals:
void callConferenceAsked(ConferenceInfoModel * conferenceInfoModel);
void callMissed (CallModel *callModel);
+ void canMergeCallsChanged();
private:
diff --git a/linphone-app/src/components/camera/Camera.cpp b/linphone-app/src/components/camera/Camera.cpp
index 5f58d7046..bacbd5afd 100644
--- a/linphone-app/src/components/camera/Camera.cpp
+++ b/linphone-app/src/components/camera/Camera.cpp
@@ -44,6 +44,7 @@ int Camera::mPreviewCounter;
// =============================================================================
Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
+ qDebug() << "[Camera] Camera constructor" << this;
updateWindowIdLocation();
setTextureFollowsItemSize(true);
// The fbo content must be y-mirrored because the ms rendering is y-inverted.
@@ -66,9 +67,11 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
Camera::~Camera(){
qDebug() << "[Camera] Camera destructor" << this;
+ mRefreshTimer->stop();
+
if(mIsPreview)
deactivatePreview();
- setWindowIdLocation(None);
+ setWindowIdLocation(None);// We need to remove the Qt Buffer from SDK ot avoid to reuse it.
}
void Camera::resetWindowId() const{
@@ -157,8 +160,6 @@ void Camera::removeParticipantDeviceModel(){
}
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
- resetWindowId();
-
QQuickFramebufferObject::Renderer * renderer = NULL;
if(mWindowIdLocation == CorePreview){
qDebug() << "[Camera] Setting Camera to Preview";
diff --git a/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp b/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp
index 8139f3fc3..97d5c682e 100644
--- a/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp
+++ b/linphone-app/src/components/chat-room/ChatRoomInitializer.cpp
@@ -83,7 +83,7 @@ void ChatRoomInitializer::setAdmins(QList< std::shared_ptr> a
void ChatRoomInitializer::start(QSharedPointer initializer){
QObject * context = new QObject();
- QObject::connect(initializer.get(), &ChatRoomInitializer::finished, context, [context, initializer](int state){
+ QObject::connect(initializer.get(), &ChatRoomInitializer::finished, context, [context, initializer](LinphoneEnums::ChatRoomState state){
qDebug() << "[ChatRoomInitializer] initialized";
context->deleteLater();// This will destroy context and initializer
});
@@ -93,7 +93,7 @@ void ChatRoomInitializer::checkInitialization(){
if( mAdmins.size() > 0 && !mAdminsSet)
return;
- emit finished((int)mChatRoom->getState());
+ emit finished(LinphoneEnums::fromLinphone(mChatRoom->getState()));
}
void ChatRoomInitializer::onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) {
diff --git a/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp b/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp
index 3e2efd470..d7852fece 100644
--- a/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp
+++ b/linphone-app/src/components/chat-room/ChatRoomInitializer.hpp
@@ -24,6 +24,7 @@
#include
#include "ChatRoomInitializer.hpp"
+#include "utils/LinphoneEnums.hpp"
#include
@@ -54,7 +55,7 @@ public:
virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState);
signals:
- void finished(int state); // this signal is emit before deletion and give the current linphone::ChatRoom:State of the chat room.
+ void finished(LinphoneEnums::ChatRoomState state); // this signal is emit before deletion and give the current linphone::ChatRoom:State of the chat room.
private:
void connectTo(ChatRoomListener * listener);
diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp
index 28a7ace0b..02a52440b 100644
--- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp
+++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp
@@ -107,7 +107,7 @@ void ChatRoomModel::connectTo(ChatRoomListener * listener){
}
// -----------------------------------------------------------------------------
-QSharedPointer ChatRoomModel::create(std::shared_ptr chatRoom, const std::list>& callLogs){
+QSharedPointer ChatRoomModel::create(const std::shared_ptr& chatRoom, const std::list>& callLogs){
QSharedPointer model = QSharedPointer::create(chatRoom, callLogs);
if(model){
model->mSelf = model;
@@ -117,7 +117,7 @@ QSharedPointer ChatRoomModel::create(std::shared_ptr chatRoom, const std::list>& callLogs, QObject * parent) : ProxyListModel(parent){
+ChatRoomModel::ChatRoomModel (const std::shared_ptr& chatRoom, const std::list>& callLogs, QObject * parent) : ProxyListModel(parent){
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
CoreManager *coreManager = CoreManager::getInstance();
mCoreHandlers = coreManager->getHandlers();
@@ -149,6 +149,7 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr chatRoom, cons
QObject::connect(coreManager->getContactsListModel(), &ContactsListModel::contactUpdated, this, &ChatRoomModel::avatarChanged);
connect(this, &ChatRoomModel::fullPeerAddressChanged, this, &ChatRoomModel::usernameChanged);
+ connect(this, &ChatRoomModel::stateChanged, this, &ChatRoomModel::updatingChanged);
if(mChatRoom){
mParticipantListModel = QSharedPointer::create(this);
@@ -311,11 +312,11 @@ QString ChatRoomModel::getLocalAddress () const {
}
QString ChatRoomModel::getFullPeerAddress () const {
- return mChatRoom ? Utils::coreStringToAppString(mChatRoom->getPeerAddress()->asString()) : "";
+ return mChatRoom && mChatRoom->getPeerAddress() ? Utils::coreStringToAppString(mChatRoom->getPeerAddress()->asString()) : "";
}
QString ChatRoomModel::getFullLocalAddress () const {
- return mChatRoom ? Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asString()) : "";
+ return mChatRoom && mChatRoom->getLocalAddress()? Utils::coreStringToAppString(mChatRoom->getLocalAddress()->asString()) : "";
}
QString ChatRoomModel::getConferenceAddress () const {
@@ -404,8 +405,8 @@ std::list> ChatRoomModel::getParticipants
return participantList;
}
-int ChatRoomModel::getState() const {
- return mChatRoom ? (int)mChatRoom->getState() : 0;
+LinphoneEnums::ChatRoomState ChatRoomModel::getState() const {
+ return mChatRoom ? LinphoneEnums::fromLinphone(mChatRoom->getState()) : LinphoneEnums::ChatRoomStateNone;
}
bool ChatRoomModel::isReadOnly() const{
@@ -481,6 +482,10 @@ bool ChatRoomModel::isBasic() const{
return mChatRoom && mChatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic);
}
+bool ChatRoomModel::isUpdating() const{
+ return getState() == LinphoneEnums::ChatRoomStateCreationPending || getState() == LinphoneEnums::ChatRoomStateTerminationPending;
+}
+
std::shared_ptr ChatRoomModel::getChatRoom(){
return mChatRoom;
}
@@ -523,14 +528,6 @@ int ChatRoomModel::getAllUnreadCount(){
return mUnreadMessagesCount + mMissedCallsCount;
}
-QString ChatRoomModel::getCachedText()const{
- return mCachedText;
-}
-
-bool ChatRoomModel::hasDraft() const{
- return mHasDraft;
-}
-
//------------------------------------------------------------------------------------------------
void ChatRoomModel::setSubject(QString& subject){
@@ -605,23 +602,6 @@ void ChatRoomModel::enableMarkAsRead(const bool& enable){
}
}
-bool ChatRoomModel::setCachedText(const QString& text){
- if(mCachedText != text){
- mCachedText = text;
- emit cachedTextChanged();
- setHasDraft(!mCachedText.isEmpty());
- return true;
- }else
- return false;
-}
-
-void ChatRoomModel::setHasDraft(const bool& cached){
- if(mHasDraft != cached){
- mHasDraft = cached;
- emit hasDraftChanged();
- }
-}
-
void ChatRoomModel::setReply(ChatMessageModel * model){
if(model != mReplyModel.get()){
if( model && model->getChatMessage() )
@@ -645,15 +625,14 @@ void ChatRoomModel::markAsToDelete(){
void ChatRoomModel::deleteChatRoom(){
qInfo() << "Deleting ChatRoom : " << getSubject() << ", address=" << getFullPeerAddress();
if(mChatRoom){
- mChatRoom->removeListener(mChatRoomListener);
CoreManager::getInstance()->getCore()->deleteChatRoom(mChatRoom);
}
- emit chatRoomDeleted();
}
void ChatRoomModel::leaveChatRoom (){
if(mChatRoom){
- mChatRoom->leave();
+ if(!isReadOnly())
+ mChatRoom->leave();
if( mChatRoom->getHistorySize() == 0 && mChatRoom->getHistoryEventsSize() == 0)
deleteChatRoom();
}
@@ -724,7 +703,6 @@ void ChatRoomModel::sendMessage (const QString &message) {
if(recorder->haveVocalRecorder())
recorder->clearVocalRecorder();
CoreManager::getInstance()->getChatModel()->clear();
- setCachedText("");
}
}
@@ -744,8 +722,8 @@ void ChatRoomModel::forwardMessage(ChatMessageModel * model){
}
// -----------------------------------------------------------------------------
-void ChatRoomModel::compose (const QString& text) {
- if( setCachedText(text) && mChatRoom)// only send a compose if text has changed
+void ChatRoomModel::compose () {
+ if( mChatRoom)
mChatRoom->compose();
}
@@ -880,23 +858,31 @@ int ChatRoomModel::loadTillMessage(ChatMessageModel * message){
});
// if not find, load more entries and find it in new entries.
if( entry == mList.end()){
+ mPostModelChangedEvents = false;
+ beginResetModel();
int newEntries = loadMoreEntries();
while( newEntries > 0){// no more new entries
int entryCount = 0;
entry = mList.begin();
- auto chatEventEntry = entry->objectCast();
+ auto chatEventEntry = entry->objectCast();
while(entryCount < newEntries &&
(chatEventEntry->mType != ChatRoomModel::EntryType::MessageEntry || chatEventEntry.objectCast()->getChatMessage() != linphoneMessage)
){
++entryCount;
++entry;
+ if( entry != mList.end())
+ chatEventEntry = entry->objectCast();
}
if( entryCount < newEntries){// We got it
qDebug() << "Find message at " << entryCount << " after loading new entries";
+ mPostModelChangedEvents = true;
+ endResetModel();
return entryCount;
}else
newEntries = loadMoreEntries();// continue
}
+ mPostModelChangedEvents = true;
+ endResetModel();
}else{
int entryCount = entry - mList.begin();
qDebug() << "Find message at " << entryCount;
@@ -1051,18 +1037,21 @@ int ChatRoomModel::loadMoreEntries(){
EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this);
if(entries.size() >0){
- beginInsertRows(QModelIndex(), 0, entries.size()-1);
+ if(mPostModelChangedEvents)
+ beginInsertRows(QModelIndex(), 0, entries.size()-1);
for(auto entry : entries)
mList.prepend(entry);
- endInsertRows();
+ if(mPostModelChangedEvents)
+ endInsertRows();
//emit layoutChanged();
updateLastUpdateTime();
}
newEntries = entries.size();
}while( newEntries>0 && currentRowCount == rowCount());
- currentRowCount = rowCount() - currentRowCount + 1;
+ currentRowCount = rowCount() - currentRowCount;
setEntriesLoading(false);
- emit moreEntriesLoaded(currentRowCount);
+ if(mPostModelChangedEvents)
+ emit moreEntriesLoaded(currentRowCount);
return currentRowCount;
}
@@ -1337,6 +1326,11 @@ void ChatRoomModel::onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState){
updateLastUpdateTime();
emit stateChanged(getState());
+ if(newState == linphone::ChatRoom::State::Deleted){
+ mChatRoom->removeListener(mChatRoomListener);
+ mChatRoom = nullptr;
+ emit chatRoomDeleted();
+ }
}
void ChatRoomModel::onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){
diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp
index bcac30bd0..4c25d05e6 100644
--- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp
+++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp
@@ -25,6 +25,8 @@
#include "app/proxyModel/ProxyListModel.hpp"
#include
+#include "utils/LinphoneEnums.hpp"
+
// =============================================================================
// Fetch all N messages of a ChatRoom.
// =============================================================================
@@ -73,13 +75,14 @@ public:
Q_PROPERTY(bool isComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged)
Q_PROPERTY(QList composers READ getComposers NOTIFY isRemoteComposingChanged)
Q_PROPERTY(bool isReadOnly READ isReadOnly NOTIFY isReadOnlyChanged)
+ Q_PROPERTY(bool updating READ isUpdating NOTIFY updatingChanged)
Q_PROPERTY(QString sipAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged)
Q_PROPERTY(QString sipAddressUriOnly READ getPeerAddress 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(int state READ getState NOTIFY stateChanged)
+ Q_PROPERTY(LinphoneEnums::ChatRoomState state READ getState NOTIFY stateChanged)
Q_PROPERTY(long ephemeralLifetime READ getEphemeralLifetime WRITE setEphemeralLifetime NOTIFY ephemeralLifetimeChanged)
Q_PROPERTY(bool ephemeralEnabled READ isEphemeralEnabled WRITE setEphemeralEnabled NOTIFY ephemeralEnabledChanged)
@@ -92,12 +95,9 @@ public:
Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged)
- Q_PROPERTY(QString cachedText READ getCachedText WRITE setCachedText NOTIFY cachedTextChanged)
- Q_PROPERTY(bool hasDraft READ hasDraft WRITE setHasDraft NOTIFY hasDraftChanged)
-
- static QSharedPointer create(std::shared_ptr chatRoom, const std::list>& callLogs = std::list>());
- ChatRoomModel (std::shared_ptr chatRoom, const std::list>& callLogs = std::list>(), QObject * parent = nullptr);
+ static QSharedPointer create(const std::shared_ptr& chatRoom, const std::list>& callLogs = std::list>());
+ ChatRoomModel (const std::shared_ptr& chatRoom, const std::list>& callLogs = std::list>(), QObject * parent = nullptr);
~ChatRoomModel ();
@@ -119,7 +119,7 @@ public:
QString getUsername () const;
QString getAvatar () const;
int getPresenceStatus() const;
- int getState() const;
+ LinphoneEnums::ChatRoomState getState() const;
bool isReadOnly() const;
bool isEphemeralEnabled() const;
long getEphemeralLifetime() const;
@@ -138,14 +138,14 @@ public:
bool getIsRemoteComposing () const;
bool isEntriesLoading() const;
bool isBasic() const;
+ bool isUpdating() const;
+
ParticipantListModel* getParticipantListModel() const;
std::list> getParticipants(const bool& withMe = true) const;
std::shared_ptr getChatRoom();
QList getComposers();
QString getParticipantAddress(); // return peerAddress if not secure else return the first participant SIP address.
int getAllUnreadCount(); // Return unread messages and missed call.
- QString getCachedText() const;
- bool hasDraft() const;
//---- Setters
void setSubject(QString& subject);
@@ -159,8 +159,6 @@ public:
void setEphemeralEnabled(bool enabled);
void setEphemeralLifetime(long lifetime);
void enableMarkAsRead(const bool& enable);
- bool setCachedText(const QString& text); // return true if cache changed
- void setHasDraft(const bool& draft);
void setReply(ChatMessageModel * model);
ChatMessageModel * getReply()const;
@@ -175,7 +173,7 @@ public:
Q_INVOKABLE void updateParticipants(const QVariantList& participants);
void sendMessage (const QString &message);
Q_INVOKABLE void forwardMessage(ChatMessageModel * model);
- void compose (const QString& text);
+ void compose ();
Q_INVOKABLE void resetMessageCount ();
void initEntries();
Q_INVOKABLE int loadMoreEntries(); // return new entries count
@@ -280,8 +278,7 @@ signals:
void markAsReadEnabledChanged();
void chatRoomDeleted();// Must be connected with DirectConnection mode
void replyChanged();
- void cachedTextChanged();
- void hasDraftChanged();
+ void updatingChanged();
// Chat Room listener callbacks
@@ -314,8 +311,7 @@ private:
QSharedPointer mReplyModel;
QSharedPointer mUnreadMessageNotice;
int mBindingCalls = 0;
- QString mCachedText; // TODO : replace it by content to manage files/audio etc.
- bool mHasDraft = false;
+ bool mPostModelChangedEvents = true;
QWeakPointer mSelf;
};
diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
index cc644c9bd..fd37071b3 100644
--- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
+++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
@@ -36,6 +36,8 @@
using namespace std;
+QString ChatRoomProxyModel::gCachedText;
+
// =============================================================================
ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
@@ -55,6 +57,7 @@ ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel
}
ChatRoomProxyModel::~ChatRoomProxyModel(){
+ setSourceModel(nullptr);
setChatRoomModel(nullptr); // Do remove process like setting haveCall if is Call.
}
@@ -99,7 +102,8 @@ CREATE_PARENT_MODEL_FUNCTION(deleteChatRoom)
void ChatRoomProxyModel::compose (const QString& text) {
if (mChatRoomModel)
- mChatRoomModel->compose(text);
+ mChatRoomModel->compose();
+ gCachedText = text;
}
int ChatRoomProxyModel::getEntryTypeFilter () {
@@ -239,6 +243,10 @@ QVariant ChatRoomProxyModel::getAt(int row){
return sourceModel()->data(sourceIndex);
}
+QString ChatRoomProxyModel::getCachedText() const{
+ return gCachedText;
+}
+
void ChatRoomProxyModel::setIsCall(const bool& isCall){
if(mIsCall != isCall) {
if(mChatRoomModel){
@@ -328,7 +336,7 @@ void ChatRoomProxyModel::setChatRoomModel (ChatRoomModel *chatRoomModel){
}else{
if(mIsCall && mChatRoomModel)
mChatRoomModel->removeBindingCall();
- mChatRoomModel = nullptr;
+ mChatRoomModel = nullptr;
}
}
// -----------------------------------------------------------------------------
diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
index 03758ec28..39a5dc675 100644
--- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
+++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
@@ -40,6 +40,7 @@ class ChatRoomProxyModel : public QSortFilterProxyModel {
Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress WRITE setFullLocalAddress NOTIFY fullLocalAddressChanged)
Q_PROPERTY(ChatRoomModel *chatRoomModel READ getChatRoomModel WRITE setChatRoomModel NOTIFY chatRoomModelChanged)
Q_PROPERTY(QList composers READ getComposers NOTIFY isRemoteComposingChanged)
+ Q_PROPERTY(QString cachedText READ getCachedText)
Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged)
Q_PROPERTY(bool markAsReadEnabled READ markAsReadEnabled WRITE enableMarkAsRead NOTIFY markAsReadEnabledChanged)// Focus is at end of the list. Used to reset message count if not at end
@@ -119,6 +120,9 @@ private:
void setChatRoomModel (ChatRoomModel *chatRoomModel);
QList getComposers () const;
+
+ QString getCachedText() const;
+
void reload (ChatRoomModel *chatRoomModel);
void handleIsActiveChanged (QWindow *window);
@@ -134,6 +138,7 @@ private:
QString mLocalAddress;
QString mFullPeerAddress;
QString mFullLocalAddress;
+ static QString gCachedText;
bool mMarkAsReadEnabled;
bool mIsCall = false;
diff --git a/linphone-app/src/components/conference/ConferenceListener.cpp b/linphone-app/src/components/conference/ConferenceListener.cpp
index 32a5a55f1..19f65c159 100644
--- a/linphone-app/src/components/conference/ConferenceListener.cpp
+++ b/linphone-app/src/components/conference/ConferenceListener.cpp
@@ -41,6 +41,11 @@ ConferenceListener::~ConferenceListener(){
//-----------------------------------------------------------------------------------------------------------------------
// LINPHONE LISTENERS
//-----------------------------------------------------------------------------------------------------------------------
+void ConferenceListener::onActiveSpeakerParticipantDevice(const std::shared_ptr & conference, const std::shared_ptr & participantDevice) {
+ qDebug() << "onActiveSpeakerParticipantDevice: " << participantDevice->getAddress()->asString().c_str();
+ emit activeSpeakerParticipantDevice(participantDevice);
+}
+
void ConferenceListener::onParticipantAdded(const std::shared_ptr & conference, const std::shared_ptr & participant){
qDebug() << "onParticipantAdded: " << participant->getAddress()->asString().c_str();
emit participantAdded(participant);
diff --git a/linphone-app/src/components/conference/ConferenceListener.hpp b/linphone-app/src/components/conference/ConferenceListener.hpp
index 7ad651fb3..8b80dbd47 100644
--- a/linphone-app/src/components/conference/ConferenceListener.hpp
+++ b/linphone-app/src/components/conference/ConferenceListener.hpp
@@ -35,6 +35,7 @@ public:
virtual ~ConferenceListener();
// LINPHONE LISTENERS
+ virtual void onActiveSpeakerParticipantDevice(const std::shared_ptr & conference, const std::shared_ptr & participantDevice) override;
virtual void onParticipantAdded(const std::shared_ptr & conference, const std::shared_ptr & participant) override;
virtual void onParticipantRemoved(const std::shared_ptr & conference, const std::shared_ptr & participant) override;
virtual void onParticipantAdminStatusChanged(const std::shared_ptr & conference, const std::shared_ptr & participant) override;
@@ -50,6 +51,7 @@ public:
//---------------------------------------------------------------------------
signals:
+ void activeSpeakerParticipantDevice(const std::shared_ptr & participantDevice);
void participantAdded(const std::shared_ptr & participant);
void participantRemoved(const std::shared_ptr & participant);
void participantAdminStatusChanged(const std::shared_ptr & participant);
@@ -61,6 +63,7 @@ signals:
void participantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking);
void conferenceStateChanged(linphone::Conference::State newState);
void subjectChanged(const std::string & subject);
+
};
diff --git a/linphone-app/src/components/conference/ConferenceModel.cpp b/linphone-app/src/components/conference/ConferenceModel.cpp
index aad85a9ac..e09a7d510 100644
--- a/linphone-app/src/components/conference/ConferenceModel.cpp
+++ b/linphone-app/src/components/conference/ConferenceModel.cpp
@@ -37,6 +37,7 @@
#include "components/Components.hpp"
void ConferenceModel::connectTo(ConferenceListener * listener){
+ connect(listener, &ConferenceListener::activeSpeakerParticipantDevice, this, &ConferenceModel::onActiveSpeakerParticipantDevice);
connect(listener, &ConferenceListener::participantAdded, this, &ConferenceModel::onParticipantAdded);
connect(listener, &ConferenceListener::participantRemoved, this, &ConferenceModel::onParticipantRemoved);
connect(listener, &ConferenceListener::participantAdminStatusChanged, this, &ConferenceModel::onParticipantAdminStatusChanged);
@@ -140,6 +141,9 @@ void ConferenceModel::setIsReady(bool state){
//-----------------------------------------------------------------------------------------------------------------------
// LINPHONE LISTENERS
//-----------------------------------------------------------------------------------------------------------------------
+void ConferenceModel::onActiveSpeakerParticipantDevice(const std::shared_ptr & participantDevice){
+ emit activeSpeakerParticipantDevice(participantDevice);
+}
void ConferenceModel::onParticipantAdded(const std::shared_ptr & participant){
qDebug() << "Added call, participant count: " << getParticipantList().size() << ". Me devices : " << mConference->getMe()->getDevices().size();
updateLocalParticipant();
diff --git a/linphone-app/src/components/conference/ConferenceModel.hpp b/linphone-app/src/components/conference/ConferenceModel.hpp
index f5936b8ef..214681e2a 100644
--- a/linphone-app/src/components/conference/ConferenceModel.hpp
+++ b/linphone-app/src/components/conference/ConferenceModel.hpp
@@ -62,7 +62,7 @@ public:
void setIsReady(bool state);
-
+ virtual void onActiveSpeakerParticipantDevice(const std::shared_ptr & participantDevice);
virtual void onParticipantAdded(const std::shared_ptr & participant);
virtual void onParticipantRemoved(const std::shared_ptr & participant);
virtual void onParticipantAdminStatusChanged(const std::shared_ptr & participant);
@@ -77,6 +77,7 @@ public:
//---------------------------------------------------------------------------
signals:
+ void activeSpeakerParticipantDevice(const std::shared_ptr & participantDevice);
void localParticipantChanged();
void participantAdded(const std::shared_ptr & participant);
void participantRemoved(const std::shared_ptr & participant);
diff --git a/linphone-app/src/components/conference/ConferenceProxyModel.cpp b/linphone-app/src/components/conference/ConferenceProxyModel.cpp
index a2a922a13..bf028b98b 100644
--- a/linphone-app/src/components/conference/ConferenceProxyModel.cpp
+++ b/linphone-app/src/components/conference/ConferenceProxyModel.cpp
@@ -38,6 +38,7 @@
using namespace std;
ConferenceProxyModel::ConferenceProxyModel (QObject *parent) : SortFilterProxyModel(parent) {
+ mDeleteSourceModel = false;
setSourceModel(CoreManager::getInstance()->getCallsListModel());
emit conferenceChanged();
diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp
index 1aa28f80c..b889ecf02 100644
--- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp
+++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp
@@ -43,7 +43,7 @@ ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListMo
auto conferenceInfos = coreManager->getCore()->getConferenceInformationList();
QList > items;
for(auto conferenceInfo : conferenceInfos){
- auto item = build(conferenceInfo);
+ auto item = build(conferenceInfo, mBuildAll);
if(item)
items << item;
}
@@ -53,10 +53,10 @@ ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListMo
// -----------------------------------------------------------------------------
-QSharedPointer ConferenceInfoListModel::build(const std::shared_ptr & conferenceInfo) const{
+QSharedPointer ConferenceInfoListModel::build(const std::shared_ptr & conferenceInfo, const bool& buildAll) const{
auto me = CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress();
std::list> participants = conferenceInfo->getParticipants();
- bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me);
+ bool haveMe = buildAll || conferenceInfo->getOrganizer()->weakEqual(me);
if(!haveMe)
haveMe = (std::find_if(participants.begin(), participants.end(), [me](const std::shared_ptr& address){
return me->weakEqual(address);
@@ -70,7 +70,7 @@ QSharedPointer ConferenceInfoListModel::build(const std::sh
}
void ConferenceInfoListModel::add(const std::shared_ptr & conferenceInfo, const bool& sendEvents){
- auto item = build(conferenceInfo);
+ auto item = build(conferenceInfo, mBuildAll);
if( item)
ProxyListModel::add(item);
}
@@ -89,7 +89,7 @@ QVariant ConferenceInfoListModel::data (const QModelIndex &index, int role ) con
if (role == Qt::DisplayRole)
return QVariant::fromValue(mList[row].get());
else if (role == Qt::DisplayRole +1 )
- return QVariant::fromValue(mList[row].objectCast()->getDateTimeUtc().date());
+ return QVariant::fromValue(mList[row].objectCast()->getDateTimeSystem().date());
return QVariant();
}
diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp
index c7ee051f5..abf586002 100644
--- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp
+++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp
@@ -37,7 +37,7 @@ class ConferenceInfoListModel : public ProxyListModel {
public:
ConferenceInfoListModel (QObject *parent = Q_NULLPTR);
- QSharedPointer build(const std::shared_ptr & conferenceInfo) const;
+ QSharedPointer build(const std::shared_ptr & conferenceInfo, const bool& buildAll) const;
void add(const std::shared_ptr & conferenceInfo, const bool& sendEvents = true);
@@ -50,7 +50,8 @@ public slots:
void onRemoved(bool byUser);
signals:
void filterTypeChanged(int filterType);
-
+private:
+ bool mBuildAll = true; // Short term design choice : display all. As of 5.2.0 SDK and on cancel, there are no more more links between conference info and current account.
};
Q_DECLARE_METATYPE(ConferenceInfoListModel*)
#endif
diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp
index 583e8a855..2ee413582 100644
--- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp
+++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp
@@ -104,6 +104,7 @@ ConferenceInfoModel::ConferenceInfoModel (QObject * parent) : QObject(parent){
connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::isScheduledChanged);
connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::inviteModeChanged);
connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::conferenceInfoStateChanged);
+ connect(this, &ConferenceInfoModel::conferenceInfoChanged, this, &ConferenceInfoModel::conferenceSchedulerStateChanged);
}
// Callable from C++
@@ -124,6 +125,7 @@ ConferenceInfoModel::ConferenceInfoModel (std::shared_ptr ConferenceInfoModel::findConferenceInf
//------------------------------------------------------------------------------------------------
-
-QDateTime ConferenceInfoModel::getDateTimeUtc() const{
- return QDateTime::fromMSecsSinceEpoch(mConferenceInfo->getDateTime() * 1000).toUTC();
+//Note conferenceInfo->getDateTime uses system timezone and fromMSecsSinceEpoch need a UTC
+QDateTime ConferenceInfoModel::getDateTimeSystem() const{
+ QDateTime reference(QDateTime::fromMSecsSinceEpoch(mConferenceInfo->getDateTime() * 1000));// Get a reference for timezone offset computing
+ qint64 utcMs = (mConferenceInfo->getDateTime() - QTimeZone::systemTimeZone().offsetFromUtc(reference)) * 1000;// Remove system timezone offset to get UTC
+ return QDateTime::fromMSecsSinceEpoch(utcMs, QTimeZone::systemTimeZone()); // Return a System Timezone datetime based
}
-QDateTime ConferenceInfoModel::getDateTimeSystem() const{
- QDateTime utc = getDateTimeUtc();
- return utc.addSecs(QTimeZone::systemTimeZone().offsetFromUtc(utc));
+QDateTime ConferenceInfoModel::getDateTimeUtc() const{
+ return getDateTimeSystem().toUTC();
}
int ConferenceInfoModel::getDuration() const{
@@ -204,11 +207,29 @@ QVariantList ConferenceInfoModel::getParticipants() const{
}
return addresses;
}
+QVariantList ConferenceInfoModel::getAllParticipants() const{
+ QVariantList addresses = getParticipants();
+ QString organizerAddress = QString::fromStdString(mConferenceInfo->getOrganizer()->asStringUriOnly());
+ for(auto item : addresses){
+ if( item.toMap()["address"] == organizerAddress)
+ return addresses;
+ }
+ QVariantMap participant;
+ participant["displayName"] = Utils::getDisplayName(mConferenceInfo->getOrganizer());
+ participant["address"] = organizerAddress;
+ addresses << participant;
+ return addresses;
+}
+
int ConferenceInfoModel::getParticipantCount()const{
return mConferenceInfo->getParticipants().size();
}
+int ConferenceInfoModel::getAllParticipantCount()const{
+ return getAllParticipants().size();
+}
+
TimeZoneModel* ConferenceInfoModel::getTimeZoneModel() const{
TimeZoneModel * model = new TimeZoneModel(mTimeZone);
App::getInstance()->getEngine()->setObjectOwnership(model, QQmlEngine::JavaScriptOwnership);
@@ -223,12 +244,18 @@ LinphoneEnums::ConferenceInfoState ConferenceInfoModel::getConferenceInfoState()
return LinphoneEnums::fromLinphone(mConferenceInfo->getState());
}
+LinphoneEnums::ConferenceSchedulerState ConferenceInfoModel::getConferenceSchedulerState() const{
+ return LinphoneEnums::fromLinphone(mLastConferenceSchedulerState);
+}
+
//------------------------------------------------------------------------------------------------
-// Convert into UTC with TimeZone and pass system timezone to conference info
+// Datetime is in Custom (Locale/UTC/System). Convert into system timezone for conference info
void ConferenceInfoModel::setDateTime(const QDateTime& dateTime){
- QDateTime utc = dateTime.addSecs( -mTimeZone.offsetFromUtc(dateTime));
- QDateTime system = utc.addSecs(QTimeZone::systemTimeZone().offsetFromUtc(utc));
- mConferenceInfo->setDateTime(system.toMSecsSinceEpoch() / 1000);
+ QDateTime system = dateTime.toTimeZone(QTimeZone::systemTimeZone());//System
+ int offset = QTimeZone::systemTimeZone().offsetFromUtc(system);//Get UTC offset in system coordinate
+ system = system.addSecs( offset - mTimeZone.offsetFromUtc(dateTime));// Delta on offsets
+ mConferenceInfo->setDateTime(system.toMSecsSinceEpoch() / 1000 + offset);// toMSecsSinceEpoch() is UTC, add system reference.
+
emit dateTimeChanged();
}
@@ -254,6 +281,7 @@ void ConferenceInfoModel::setDescription(const QString& description){
void ConferenceInfoModel::setParticipants(ParticipantListModel * participants){
mConferenceInfo->setParticipants(participants->getParticipants());
+ emit participantsChanged();
}
void ConferenceInfoModel::setTimeZoneModel(TimeZoneModel * model){
@@ -314,23 +342,22 @@ void ConferenceInfoModel::createConference(const int& securityLevel) {
CoreManager::getInstance()->getTimelineListModel()->mAutoSelectAfterCreation = false;
shared_ptr core = CoreManager::getInstance()->getCore();
static std::shared_ptr conference;
- qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer();
+ qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer() << " for " << getDateTimeSystem().toString();
qInfo() << "Participants:";
for(auto p : mConferenceInfo->getParticipants())
qInfo() << "\t" << p->asString().c_str();
-
mConferenceScheduler = ConferenceScheduler::create();
mConferenceScheduler->mSendInvite = mInviteMode;
connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent);
- connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onStateChanged);
+ connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onConferenceSchedulerStateChanged);
mConferenceScheduler->getConferenceScheduler()->setInfo(mConferenceInfo);
}
void ConferenceInfoModel::cancelConference(){
mConferenceScheduler = ConferenceScheduler::create();
connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent);
- connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onStateChanged);
+ connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onConferenceSchedulerStateChanged);
mConferenceScheduler->getConferenceScheduler()->cancelConference(mConferenceInfo);
}
@@ -343,12 +370,14 @@ void ConferenceInfoModel::deleteConferenceInfo(){
//-------------------------------------------------------------------------------------------------
-void ConferenceInfoModel::onStateChanged(linphone::ConferenceScheduler::State state){
- qDebug() << "ConferenceInfoModel::onStateChanged: " << (int) state;
+void ConferenceInfoModel::onConferenceSchedulerStateChanged(linphone::ConferenceScheduler::State state){
+ qDebug() << "ConferenceInfoModel::onConferenceSchedulerStateChanged: " << (int) state;
+ mLastConferenceSchedulerState = state;
if( state == linphone::ConferenceScheduler::State::Ready)
emit conferenceCreated();
else if( state == linphone::ConferenceScheduler::State::Error)
emit conferenceCreationFailed();
+ emit conferenceInfoChanged();
}
void ConferenceInfoModel::onInvitationsSent(const std::list> & failedInvitations) {
qDebug() << "ConferenceInfoModel::onInvitationsSent";
diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp
index 17087a240..7f2ec0e27 100644
--- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp
+++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp
@@ -49,7 +49,10 @@ public:
Q_PROPERTY(QString uri READ getUri NOTIFY uriChanged)
Q_PROPERTY(bool isScheduled READ isScheduled WRITE setIsScheduled NOTIFY isScheduledChanged)
Q_PROPERTY(int inviteMode READ getInviteMode WRITE setInviteMode NOTIFY inviteModeChanged)
+ Q_PROPERTY(int participantCount READ getParticipantCount NOTIFY participantsChanged)
+ Q_PROPERTY(int allParticipantCount READ getAllParticipantCount NOTIFY participantsChanged)
Q_PROPERTY(LinphoneEnums::ConferenceInfoState state READ getConferenceInfoState NOTIFY conferenceInfoStateChanged)
+ Q_PROPERTY(LinphoneEnums::ConferenceSchedulerState conferenceSchedulerState READ getConferenceSchedulerState NOTIFY conferenceSchedulerStateChanged)
static QSharedPointer create(std::shared_ptr conferenceInfo);
ConferenceInfoModel (QObject * parent = nullptr);
@@ -72,10 +75,13 @@ public:
bool isScheduled() const;
int getInviteMode() const;
Q_INVOKABLE QVariantList getParticipants() const;
+ Q_INVOKABLE QVariantList getAllParticipants() const;
Q_INVOKABLE int getParticipantCount()const;
+ Q_INVOKABLE int getAllParticipantCount()const;
Q_INVOKABLE TimeZoneModel* getTimeZoneModel() const;
Q_INVOKABLE QString getIcalendarString() const;
LinphoneEnums::ConferenceInfoState getConferenceInfoState() const;
+ LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const;
void setDateTime(const QDateTime& dateTime);
void setDuration(const int& duration);
@@ -97,10 +103,9 @@ public:
// SCHEDULER
- virtual void onStateChanged(linphone::ConferenceScheduler::State state);
+ virtual void onConferenceSchedulerStateChanged(linphone::ConferenceScheduler::State state);
virtual void onInvitationsSent(const std::list> & failedInvitations);
-
signals:
void timeZoneModelChanged();
void dateTimeChanged();
@@ -113,6 +118,7 @@ signals:
void isScheduledChanged();
void inviteModeChanged();
void conferenceInfoStateChanged();
+ void conferenceSchedulerStateChanged();
void conferenceCreated();
void conferenceCreationFailed();
@@ -128,6 +134,7 @@ private:
bool mIsScheduled = true;
int mInviteMode = 0;
bool mRemoveRequested = false;// true if user has request its deletion from DB
+ linphone::ConferenceScheduler::State mLastConferenceSchedulerState = linphone::ConferenceScheduler::State::Idle;// Workaround for missing getter in scheduler.
};
Q_DECLARE_METATYPE(QSharedPointer)
diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp
index 885b8c058..c3eb602ec 100644
--- a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp
+++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp
@@ -54,6 +54,8 @@ bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelInde
QModelIndex index = listModel->index(sourceRow, 0, QModelIndex());
const ConferenceInfoModel* ics = sourceModel()->data(index).value();
if(ics){
+ if(ics->getDuration() == 0)
+ return false;
QDateTime currentDateTime = QDateTime::currentDateTime();
if( mFilterType == 0){
return ics->getEndDateTime() < currentDateTime;
@@ -65,7 +67,7 @@ bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelInde
return mFilterType == -1;
}
}
- return true;
+ return false;
}
bool ConferenceInfoProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
diff --git a/linphone-app/src/components/contact/ContactModel.cpp b/linphone-app/src/components/contact/ContactModel.cpp
index ddfa6cc25..7d85c58d3 100644
--- a/linphone-app/src/components/contact/ContactModel.cpp
+++ b/linphone-app/src/components/contact/ContactModel.cpp
@@ -215,3 +215,7 @@ Presence::PresenceLevel ContactModel::getPresenceLevel () const {
bool ContactModel::hasCapability(const LinphoneEnums::FriendCapability& capability){
return mLinphoneFriend->hasCapability(LinphoneEnums::toLinphone(capability));
}
+
+std::shared_ptr ContactModel::getFriend() const{
+ return mLinphoneFriend;
+}
\ No newline at end of file
diff --git a/linphone-app/src/components/contact/ContactModel.hpp b/linphone-app/src/components/contact/ContactModel.hpp
index c59eb01dd..e482b8d88 100644
--- a/linphone-app/src/components/contact/ContactModel.hpp
+++ b/linphone-app/src/components/contact/ContactModel.hpp
@@ -57,6 +57,8 @@ public:
Q_INVOKABLE VcardModel *cloneVcardModel () const;
Presence::PresenceLevel getPresenceLevel () const;
Q_INVOKABLE bool hasCapability(const LinphoneEnums::FriendCapability& capability);
+
+ std::shared_ptr getFriend() const;
signals:
void contactUpdated ();
diff --git a/linphone-app/src/components/contact/VcardModel.cpp b/linphone-app/src/components/contact/VcardModel.cpp
index 9f44ba24e..f807d756e 100644
--- a/linphone-app/src/components/contact/VcardModel.cpp
+++ b/linphone-app/src/components/contact/VcardModel.cpp
@@ -460,9 +460,12 @@ QVariantList VcardModel::getUrls () const {
return list;
}
-bool VcardModel::addUrl (const QString &url) {
+bool VcardModel::addUrl (QString url) {
CHECK_VCARD_IS_WRITABLE(this);
-
+ QUrl urlParser(url);
+ if( urlParser.scheme() == ""){
+ url = "https://"+url;
+ }
shared_ptr belcard = mVcard->getVcard();
if (findBelCardValue(belcard->getURLs(), url))
return false;
diff --git a/linphone-app/src/components/contact/VcardModel.hpp b/linphone-app/src/components/contact/VcardModel.hpp
index bbf6f0ce4..b4828ee38 100644
--- a/linphone-app/src/components/contact/VcardModel.hpp
+++ b/linphone-app/src/components/contact/VcardModel.hpp
@@ -88,7 +88,7 @@ public:
Q_INVOKABLE void removeEmail (const QString &email);
Q_INVOKABLE bool updateEmail (const QString &oldEmail, const QString &email);
- Q_INVOKABLE bool addUrl (const QString &url);
+ Q_INVOKABLE bool addUrl (QString url);
Q_INVOKABLE void removeUrl (const QString &url);
Q_INVOKABLE bool updateUrl (const QString &oldUrl, const QString &url);
diff --git a/linphone-app/src/components/contacts/ContactsListModel.cpp b/linphone-app/src/components/contacts/ContactsListModel.cpp
index c2bf043b0..efb6522e2 100644
--- a/linphone-app/src/components/contacts/ContactsListModel.cpp
+++ b/linphone-app/src/components/contacts/ContactsListModel.cpp
@@ -24,40 +24,26 @@
#include "components/contact/ContactModel.hpp"
#include "components/contact/VcardModel.hpp"
#include "components/core/CoreManager.hpp"
+#include "components/friend/FriendListListener.hpp"
#include "ContactsListModel.hpp"
+// =============================================================================
+void ContactsListModel::connectTo(FriendListListener * listener){
+ connect(listener, &FriendListListener::contactCreated, this, &ContactsListModel::onContactCreated);
+ connect(listener, &FriendListListener::contactDeleted, this, &ContactsListModel::onContactDeleted);
+ connect(listener, &FriendListListener::contactUpdated, this, &ContactsListModel::onContactUpdated);
+ connect(listener, &FriendListListener::syncStatusChanged, this, &ContactsListModel::onSyncStatusChanged);
+ connect(listener, &FriendListListener::presenceReceived, this, &ContactsListModel::onPresenceReceived);
+}
// =============================================================================
using namespace std;
ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent) {
- mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists().front();
- // Clean friends.
- {
- list> toRemove;
- for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) {
- if (!linphoneFriend->getVcard())
- toRemove.push_back(linphoneFriend);
- }
-
- for (const auto &linphoneFriend : toRemove) {
- qWarning() << QStringLiteral("Remove one friend without vcard.");
- mLinphoneFriends->removeFriend(linphoneFriend);
- }
- }
-
- // Init contacts with linphone friends list.
- QQmlEngine *engine = App::getInstance()->getEngine();
- for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) {
- auto contact = QSharedPointer::create(linphoneFriend);
-
- // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
- // The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
- engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
-
- addContact(contact);
- }
+ mFriendListListener = std::make_shared();
+ connectTo(mFriendListListener.get());
+ update();
}
ContactsListModel::~ContactsListModel(){
@@ -65,7 +51,7 @@ ContactsListModel::~ContactsListModel(){
beginResetModel();
mOptimizedSearch.clear();
mList.clear();
- mLinphoneFriends = nullptr;
+ mLinphoneFriends.clear();
endResetModel();
}
}
@@ -75,7 +61,9 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren
if (row < 0 || count < 0 || limit >= mList.count())
return false;
-
+
+ auto friendsList = CoreManager::getInstance()->getCore()->getFriendsLists();
+
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i) {
@@ -84,7 +72,8 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren
mOptimizedSearch.remove(address.toString());
}
- mLinphoneFriends->removeFriend(contact->mLinphoneFriend);
+ for(auto l : friendsList)
+ l->removeFriend(contact->mLinphoneFriend);
emit contactRemoved(contact);
}
@@ -111,6 +100,10 @@ QSharedPointer ContactsListModel::findContactModelFromUsername (co
}
// -----------------------------------------------------------------------------
+ContactModel *ContactsListModel::getContactModelFromAddress (const QString& address) const{
+ auto contact = findContactModelFromSipAddress(address);
+ return contact.get();
+}
ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
// Try to merge vcardModel to an existing contact.
@@ -123,7 +116,16 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
contact = QSharedPointer::create(vcardModel);
App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
- if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
+ if( mLinphoneFriends.size() == 0){
+ update();// Friends were not loaded correctly. Update them.
+ }
+ auto friendsList = CoreManager::getInstance()->getCore()->getDefaultFriendList();
+ if( !friendsList){
+ qWarning() << "There is no friends list available, cannot add a contact" ;
+ return nullptr;
+ }
+
+ if (friendsList->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel;
return nullptr;
}
@@ -131,9 +133,8 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
qInfo() << QStringLiteral("Add contact from vcard:") << contact.get() << vcardModel;
// Make sure new subscribe is issued.
- mLinphoneFriends->updateSubscriptions();
+ friendsList->updateSubscriptions();
- addContact(contact);
emit layoutChanged();
emit contactAdded(contact);
@@ -177,3 +178,47 @@ void ContactsListModel::addContact (QSharedPointer contact) {
mOptimizedSearch[address.toString()] = contact;
}
}
+
+void ContactsListModel::update(){
+ beginResetModel();
+ for(auto l : mLinphoneFriends)
+ l->removeListener(mFriendListListener);
+ mLinphoneFriends.clear();
+ mOptimizedSearch.clear();
+ mList.clear();
+ endResetModel();
+
+ mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists();
+
+ for(auto l : mLinphoneFriends){
+ l->addListener(mFriendListListener);
+ for (const auto &linphoneFriend : l->getFriends()) {
+ onContactCreated(linphoneFriend);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+
+void ContactsListModel::onContactCreated(const std::shared_ptr & linphoneFriend){
+ QQmlEngine *engine = App::getInstance()->getEngine();
+ auto haveContact = std::find_if(mList.begin(), mList.end(), [linphoneFriend] (const QSharedPointer& item){
+ return item.objectCast()->getFriend() == linphoneFriend;
+ });
+ if(haveContact == mList.end()) {
+ auto contact = QSharedPointer::create(linphoneFriend);
+ // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
+ // The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
+ engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
+ addContact(contact);
+ }
+}
+void ContactsListModel::onContactDeleted(const std::shared_ptr & linphoneFriend){
+}
+void ContactsListModel::onContactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend){
+}
+void ContactsListModel::onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message){
+}
+void ContactsListModel::onPresenceReceived(const std::list> & friends){
+}
+
diff --git a/linphone-app/src/components/contacts/ContactsListModel.hpp b/linphone-app/src/components/contacts/ContactsListModel.hpp
index f6ea3b627..93768a758 100644
--- a/linphone-app/src/components/contacts/ContactsListModel.hpp
+++ b/linphone-app/src/components/contacts/ContactsListModel.hpp
@@ -33,6 +33,7 @@ namespace linphone {
class ContactModel;
class VcardModel;
+class FriendListListener;
class ContactsListModel : public ProxyListModel {
friend class SipAddressesModel;
@@ -48,10 +49,21 @@ public:
QSharedPointer findContactModelFromSipAddress (const QString &sipAddress) const;
QSharedPointer findContactModelFromUsername (const QString &username) const;
+ Q_INVOKABLE ContactModel *getContactModelFromAddress (const QString& address) const;
Q_INVOKABLE ContactModel *addContact (VcardModel *vcardModel);
Q_INVOKABLE void removeContact (ContactModel *contact);
Q_INVOKABLE void cleanAvatars ();
+ Q_INVOKABLE void update ();
+
+ void connectTo(FriendListListener * listener);
+
+public slots:
+ void onContactCreated(const std::shared_ptr & linphoneFriend);
+ void onContactDeleted(const std::shared_ptr & linphoneFriend);
+ void onContactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend);
+ void onSyncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message);
+ void onPresenceReceived(const std::list> & friends);
signals:
void contactAdded (QSharedPointer);
@@ -65,7 +77,8 @@ private:
void addContact (QSharedPointer contact);
QMap> mOptimizedSearch;
- std::shared_ptr mLinphoneFriends;
+ std::list> mLinphoneFriends;
+ std::shared_ptr mFriendListListener;
};
#endif // CONTACTS_LIST_MODEL_H_
diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp
index 01aca27c0..c4c013123 100644
--- a/linphone-app/src/components/core/CoreManager.cpp
+++ b/linphone-app/src/components/core/CoreManager.cpp
@@ -260,6 +260,7 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
Paths::getFactoryConfigFilePath(),
nullptr
);
+ setDatabasesPaths();
// Enable LIME on your core to use encryption.
mCore->enableLimeX3Dh(mCore->limeX3DhAvailable());
// Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room
@@ -279,12 +280,13 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
QString userAgent = Utils::computeUserAgent(config);
mCore->setUserAgent(Utils::appStringToCoreString(userAgent), mCore->getVersion());
mCore->start();
- setDatabasesPaths();
setOtherPaths();
mCore->enableFriendListSubscription(true);
mCore->enableRecordAware(true);
if(mCore->getAccountCreatorUrl() == "")
mCore->setAccountCreatorUrl(Constants::DefaultFlexiAPIURL);
+ if( mCore->getAccountList().size() == 0)
+ mCore->setLogCollectionUploadServerUrl(Constants::DefaultUploadLogsServer);
}
void CoreManager::updateUserAgent(){
diff --git a/linphone-app/src/components/friend/FriendListListener.cpp b/linphone-app/src/components/friend/FriendListListener.cpp
new file mode 100644
index 000000000..12d976792
--- /dev/null
+++ b/linphone-app/src/components/friend/FriendListListener.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 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 .
+ */
+
+#include "FriendListListener.hpp"
+#include "../../utils/Utils.hpp"
+
+#include
+
+// =============================================================================
+
+FriendListListener::FriendListListener(QObject *parent) : QObject(parent) {
+}
+
+//--------------------------------------------------------------------
+void FriendListListener::onContactCreated(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) {
+ qDebug() << "onContactCreated: " << Utils::coreStringToAppString(linphoneFriend->getName());
+ emit contactCreated(linphoneFriend);
+}
+void FriendListListener::onContactDeleted(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) {
+ qDebug() << "onContactDeleted: " << Utils::coreStringToAppString(linphoneFriend->getName());
+ emit contactDeleted(linphoneFriend);
+}
+void FriendListListener::onContactUpdated(const std::shared_ptr & friendList, const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend) {
+ qDebug() << "onContactUpdated: " << Utils::coreStringToAppString(newFriend->getName());
+ emit contactUpdated(newFriend, oldFriend);
+}
+void FriendListListener::onSyncStatusChanged(const std::shared_ptr & friendList, linphone::FriendList::SyncStatus status, const std::string & message) {
+ qDebug() << "onSyncStatusChanged: [" << (int)status<<"] " << Utils::coreStringToAppString(message);
+ emit syncStatusChanged(status, message);
+}
+void FriendListListener::onPresenceReceived(const std::shared_ptr & friendList, const std::list> & friends) {
+ qDebug() << "onPresenceReceived: " <.
+ */
+
+#ifndef FRIEND_LIST_LISTENER_H_
+#define FRIEND_LIST_LISTENER_H_
+
+
+#include
+
+#include
+
+// =============================================================================
+
+class FriendListListener : public QObject, public linphone::FriendListListener {
+ Q_OBJECT
+
+public:
+ FriendListListener (QObject *parent = nullptr);
+ virtual void onContactCreated(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) override;
+ virtual void onContactDeleted(const std::shared_ptr & friendList, const std::shared_ptr & linphoneFriend) override;
+ virtual void onContactUpdated(const std::shared_ptr & friendList, const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend) override;
+ virtual void onSyncStatusChanged(const std::shared_ptr & friendList, linphone::FriendList::SyncStatus status, const std::string & message) override;
+ virtual void onPresenceReceived(const std::shared_ptr & friendList, const std::list> & friends) override;
+
+signals:
+ void contactCreated(const std::shared_ptr & linphoneFriend);
+ void contactDeleted(const std::shared_ptr & linphoneFriend);
+ void contactUpdated(const std::shared_ptr & newFriend, const std::shared_ptr & oldFriend);
+ void syncStatusChanged(linphone::FriendList::SyncStatus status, const std::string & message);
+ void presenceReceived(const std::list> & friends);
+};
+
+#endif
diff --git a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp
index 0d837c0a9..514a7f031 100644
--- a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp
+++ b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp
@@ -27,6 +27,7 @@
// -----------------------------------------------------------------------------
TimeZoneProxyModel::TimeZoneProxyModel (QObject *parent) : SortFilterProxyModel(parent) {
+ mDeleteSourceModel = true;
setSourceModel(new TimeZoneListModel(parent));
sort(0);
}
diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp
index 05f132cd9..ea2e9b6c8 100644
--- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp
+++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp
@@ -58,6 +58,7 @@ void ParticipantDeviceListModel::initConferenceModel(){
updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false);
qDebug() << "Conference have " << mList.size() << " devices";
+ connect(conferenceModel.get(), &ConferenceModel::activeSpeakerParticipantDevice, this, &ParticipantDeviceListModel::onActiveSpeakerParticipantDevice);
connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded);
connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded);
@@ -98,6 +99,8 @@ void ParticipantDeviceListModel::updateDevices(const std::list deviceToAdd){
+ auto deviceToAddAddr = deviceToAdd->getAddress();
+ int row = 0;
qDebug() << "Adding device " << deviceToAdd->getAddress()->asString().c_str();
for(auto item : mList) {
auto deviceModel = item.objectCast();
@@ -105,7 +108,12 @@ bool ParticipantDeviceListModel::add(std::shared_ptrupdateVideoEnabled();
return false;
+ }else if(deviceToAddAddr->equal(deviceModel->getDevice()->getAddress())){// Address is the same (same device) but the model is using another linphone object. Replace it.
+ deviceModel->updateVideoEnabled();
+ removeRow(row);
+ break;
}
+ ++row;
}
bool addMe = isMe(deviceToAdd);
auto deviceModel = ParticipantDeviceModel::create(mCallModel, deviceToAdd, addMe);
@@ -113,9 +121,18 @@ bool ParticipantDeviceListModel::add(std::shared_ptr(deviceModel);
qDebug() << "Device added. Count=" << mList.count();
+ QStringList debugDevices;
+ for(auto i : mList){
+ auto item = i.objectCast();
+ debugDevices.push_back( item->getAddress());
+ }
+ qDebug() << debugDevices.join("\n");
if( addMe){
qDebug() << "Added a me device";
emit meChanged();
+ }else if(mList.size() == 1 || (mList.size() == 2 && isMe(mList.front().objectCast()->getDevice()))){
+ mActiveSpeaker = mList.back().objectCast();
+ emit activeSpeakerChanged();
}
return true;
}
@@ -126,7 +143,6 @@ bool ParticipantDeviceListModel::remove(std::shared_ptr();
if( device->getDevice() == deviceToRemove){
device->updateVideoEnabled();
- mActiveSpeakers.removeAll(device.get());
removeRow(row);
return true;
}else
@@ -163,14 +179,8 @@ QSharedPointer ParticipantDeviceListModel::getMe(int * i
return nullptr;
}
-ParticipantDeviceModel* ParticipantDeviceListModel::getLastActiveSpeaking() const{
- if( mActiveSpeakers.size() == 0){
- if( mList.size() == 0)
- return getMe().get();
- else
- return mList.back().objectCast().get();
- }else
- return mActiveSpeakers.first();
+ParticipantDeviceModel* ParticipantDeviceListModel::getActiveSpeakerModel() const{
+ return mActiveSpeaker.get();
}
bool ParticipantDeviceListModel::isMe(std::shared_ptr deviceToCheck)const{
@@ -280,6 +290,13 @@ void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(con
else
onParticipantDeviceAdded(participantDevice);
}
+void ParticipantDeviceListModel::onActiveSpeakerParticipantDevice(const std::shared_ptr& participantDevice){
+ auto device = get(participantDevice);
+ if( device){
+ mActiveSpeaker = device;
+ emit activeSpeakerChanged();
+ }
+}
void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking){
auto device = get(participantDevice);
@@ -288,14 +305,5 @@ void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std:
}
void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){
- auto deviceModel = qobject_cast(sender());
- bool changed = false;
- // Me should not be in the list.
- if( !deviceModel->isMe() && (mActiveSpeakers.size() == 0 || deviceModel->getIsSpeaking())) {// Ensure to have at least one last active speaker
- changed = mActiveSpeakers.removeAll(deviceModel) > 0;
- mActiveSpeakers.push_front(deviceModel);
- changed = true;
- }
- if(changed)
- emit participantSpeaking(deviceModel);
+
}
diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp
index 318e46730..ed5edc3c1 100644
--- a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp
+++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp
@@ -47,12 +47,13 @@ public:
bool remove(std::shared_ptr deviceToAdd);
QSharedPointer get(std::shared_ptr deviceToGet, int * index = nullptr);
QSharedPointer getMe(int * index = nullptr)const;
- ParticipantDeviceModel* getLastActiveSpeaking() const;
+ ParticipantDeviceModel* getActiveSpeakerModel() const;
bool isMe(std::shared_ptr device)const;
bool isMeAlone() const;
public slots:
+ void onActiveSpeakerParticipantDevice(const std::shared_ptr& participantDevice);
void onConferenceModelChanged ();
void onSecurityLevelChanged(std::shared_ptr device);
void onParticipantAdded(const std::shared_ptr & participant);
@@ -66,6 +67,7 @@ public slots:
void onParticipantDeviceSpeaking();
signals:
+ void activeSpeakerChanged();
void securityLevelChanged(std::shared_ptr device);
void participantSpeaking(ParticipantDeviceModel *speakingDevice);
void conferenceCreated();
@@ -73,7 +75,8 @@ signals:
private:
CallModel * mCallModel = nullptr;
- QList mActiveSpeakers;// First item is last speaker
+ QSharedPointer mActiveSpeaker;
+ //QList mActiveSpeakers;// First item is last speaker
bool mInitialized = false;
};
diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp
index b05c9129d..b29b4c6bd 100644
--- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp
+++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp
@@ -31,6 +31,10 @@
// =============================================================================
ParticipantDeviceProxyModel::ParticipantDeviceProxyModel (QObject *parent) : SortFilterProxyModel(parent){
+ mDeleteSourceModel = true;
+}
+
+ParticipantDeviceProxyModel::~ParticipantDeviceProxyModel(){
}
bool ParticipantDeviceProxyModel::filterAcceptsRow (
@@ -57,9 +61,9 @@ ParticipantDeviceModel *ParticipantDeviceProxyModel::getAt(int row){
return sourceModel()->data(sourceIndex).value();
}
-ParticipantDeviceModel* ParticipantDeviceProxyModel::getLastActiveSpeaking(){
+ParticipantDeviceModel* ParticipantDeviceProxyModel::getActiveSpeakerModel(){
auto listModel = qobject_cast(sourceModel());
- return listModel ? listModel->getLastActiveSpeaking() : nullptr;
+ return listModel ? listModel->getActiveSpeakerModel() : nullptr;
}
CallModel * ParticipantDeviceProxyModel::getCallModel() const{
@@ -74,28 +78,31 @@ ParticipantDeviceModel * ParticipantDeviceProxyModel::getMe() const{
bool ParticipantDeviceProxyModel::isShowMe() const{
return mShowMe;
}
-
+
+void ParticipantDeviceProxyModel::connectTo(ParticipantDeviceListModel* model){
+ connect(model, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged);
+ connect(model, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking);
+ connect(model, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated);
+ connect(model, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged);
+ connect(model, &ParticipantDeviceListModel::activeSpeakerChanged, this, &ParticipantDeviceProxyModel::activeSpeakerChanged);
+}
void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){
setFilterType(1);
mCallModel = callModel;
- auto sourceModel = new ParticipantDeviceListModel(mCallModel);
- connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged);
- connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking);
- connect(sourceModel, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated);
- connect(sourceModel, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged);
- setSourceModel(sourceModel);
+ deleteSourceModel();
+ auto newSourceModel = new ParticipantDeviceListModel(mCallModel);
+ connectTo(newSourceModel);
+ setSourceModel(newSourceModel);
emit countChanged();
emit meChanged();
}
void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant){
setFilterType(0);
- auto sourceModel = participant->getParticipantDevices().get();
- connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged);
- connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking);
- connect(sourceModel, &ParticipantDeviceListModel::conferenceCreated, this, &ParticipantDeviceProxyModel::conferenceCreated);
- connect(sourceModel, &ParticipantDeviceListModel::meChanged, this, &ParticipantDeviceProxyModel::meChanged);
- setSourceModel(sourceModel);
+ deleteSourceModel();
+ auto newSourceModel = participant->getParticipantDevices().get();
+ connectTo(newSourceModel);
+ setSourceModel(newSourceModel);
emit countChanged();
emit meChanged();
}
diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp
index ecdedfd02..dfa0b885f 100644
--- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp
+++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp
@@ -42,12 +42,15 @@ public:
Q_PROPERTY(CallModel * callModel READ getCallModel WRITE setCallModel NOTIFY callModelChanged)
Q_PROPERTY(bool showMe READ isShowMe WRITE setShowMe NOTIFY showMeChanged)
Q_PROPERTY(ParticipantDeviceModel * me READ getMe NOTIFY meChanged)
+ Q_PROPERTY(ParticipantDeviceModel* activeSpeaker READ getActiveSpeakerModel NOTIFY activeSpeakerChanged)
ParticipantDeviceProxyModel (QObject *parent = nullptr);
+ ~ParticipantDeviceProxyModel();
Q_INVOKABLE ParticipantDeviceModel* getAt(int row);
- Q_INVOKABLE ParticipantDeviceModel* getLastActiveSpeaking();
- ParticipantDeviceModel * getMe() const;
+ ParticipantDeviceModel* getActiveSpeakerModel();
+ ParticipantDeviceModel* getMe() const;
+
CallModel * getCallModel() const;
bool isShowMe() const;
@@ -56,11 +59,14 @@ public:
void setParticipant(ParticipantModel * participant);
void setShowMe(const bool& show);
+ void connectTo(ParticipantDeviceListModel* model);
+
public slots:
void onCountChanged();
void onParticipantSpeaking(ParticipantDeviceModel * speakingDevice);
signals:
+ void activeSpeakerChanged();
void callModelChanged();
void showMeChanged();
void meChanged();
@@ -71,7 +77,6 @@ protected:
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
virtual bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
- QSharedPointer mDevices;
CallModel * mCallModel;
bool mShowMe = true;
};
diff --git a/linphone-app/src/components/participant/ParticipantProxyModel.cpp b/linphone-app/src/components/participant/ParticipantProxyModel.cpp
index 6abab1acd..5e32d4729 100644
--- a/linphone-app/src/components/participant/ParticipantProxyModel.cpp
+++ b/linphone-app/src/components/participant/ParticipantProxyModel.cpp
@@ -92,8 +92,11 @@ void ParticipantProxyModel::setChatRoomModel(ChatRoomModel * chatRoomModel){
connect(participants, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged);
setSourceModel(participants);
emit participantListModelChanged();
- for(int i = 0 ; i < participants->getCount() ; ++i)
- emit addressAdded(participants->getAt(i)->getSipAddress());
+ for(int i = 0 ; i < participants->getCount() ; ++i) {
+ auto participant = participants->getAt(i);
+ connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel);
+ emit addressAdded(participant->getSipAddress());
+ }
}else if(!sourceModel()){
auto model = new ParticipantListModel((ChatRoomModel*)nullptr, this);
connect(model, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged);
@@ -113,8 +116,11 @@ void ParticipantProxyModel::setConferenceModel(ConferenceModel * conferenceModel
connect(participants, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged);
setSourceModel(participants);
emit participantListModelChanged();
- for(int i = 0 ; i < participants->getCount() ; ++i)
- emit addressAdded(participants->getAt(i)->getSipAddress());
+ for(int i = 0 ; i < participants->getCount() ; ++i) {
+ auto participant = participants->getAt(i);
+ connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel);
+ emit addressAdded(participant->getSipAddress());
+ }
}else if(!sourceModel()){
auto model = new ParticipantListModel((ConferenceModel*)nullptr, this);
connect(model, &ParticipantListModel::countChanged, this, &ParticipantProxyModel::countChanged);
@@ -144,12 +150,12 @@ void ParticipantProxyModel::addAddress(const QString& address){
ParticipantListModel * participantsModel = qobject_cast(sourceModel());
if(!participantsModel->contains(address)){
QSharedPointer participant = QSharedPointer::create(nullptr);
+ connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel);
participant->setSipAddress(address);
participantsModel->add(participant);
if(mChatRoomModel && mChatRoomModel->getChatRoom()){// Invite and wait for its creation
- mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address));
- connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel);
participant->startInvitation();
+ mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address));
}
if( mConferenceModel && mConferenceModel->getConference()){
auto addressToInvite = Utils::interpretUrl(address);
@@ -158,23 +164,18 @@ void ParticipantProxyModel::addAddress(const QString& address){
auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(), [addressToInvite](const std::shared_ptr& call){
return call->getRemoteAddress()->weakEqual(addressToInvite);
});
+ participant->startInvitation();
if( haveCall == currentCalls.end())
mConferenceModel->getConference()->addParticipant(addressToInvite);
else{
runningCallsToAdd.push_back(*haveCall);
mConferenceModel->getConference()->addParticipants(runningCallsToAdd);
}
-
-
/*
std::list> addressesToInvite;
addressesToInvite.push_back(addressToInvite);
auto callParameters = CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall());
- mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/
-
- connect(participant.get(), &ParticipantModel::invitationTimeout, this, &ParticipantProxyModel::removeModel);
- participant->startInvitation();
-
+ mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/
}
emit countChanged();
emit addressAdded(address);
diff --git a/linphone-app/src/components/settings/AccountSettingsModel.cpp b/linphone-app/src/components/settings/AccountSettingsModel.cpp
index e0b73b2a0..44d1a447e 100644
--- a/linphone-app/src/components/settings/AccountSettingsModel.cpp
+++ b/linphone-app/src/components/settings/AccountSettingsModel.cpp
@@ -507,7 +507,11 @@ QString AccountSettingsModel::getPrimarySipAddress () const {
}
QString AccountSettingsModel::getDefaultAccountDomain() const{
- return Utils::coreStringToAppString(CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getDomain());
+ auto account = CoreManager::getInstance()->getCore()->getDefaultAccount();
+ if(account)
+ return Utils::coreStringToAppString(account->getParams()->getDomain());
+ else
+ return "";
}
// -----------------------------------------------------------------------------
diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp
index ce815e893..c599ebad6 100644
--- a/linphone-app/src/components/settings/SettingsModel.cpp
+++ b/linphone-app/src/components/settings/SettingsModel.cpp
@@ -69,7 +69,6 @@ SettingsModel::SettingsModel (QObject *parent) : QObject(parent) {
connect(coreManager->getAccountSettingsModel(), &AccountSettingsModel::accountSettingsUpdated, this, &SettingsModel::videoConferenceEnabledChanged);
connect(coreManager->getAccountSettingsModel(), &AccountSettingsModel::accountSettingsUpdated, this, &SettingsModel::secureChatEnabledChanged);
-
configureRlsUri();
}
@@ -548,12 +547,9 @@ static inline QVariantMap createMapFromVideoDefinition (const shared_ptrgetCore()->videoSupported());
-
map["name"] = QStringLiteral("Bad EGG");
map["width"] = QStringLiteral("?????");
map["height"] = QStringLiteral("?????");
-
return map;
}
@@ -987,9 +983,6 @@ void SettingsModel::setMediaEncryption (MediaEncryption encryption) {
if (encryption == getMediaEncryption())
return;
- if (encryption != SettingsModel::MediaEncryptionZrtp)
- setLimeState(false);
-
CoreManager::getInstance()->getCore()->setMediaEncryption(
static_cast(encryption)
);
@@ -1032,10 +1025,7 @@ void SettingsModel::setLimeState (const bool& state) {
if (state == getLimeState())
return;
- if (state)
- setMediaEncryption(SettingsModel::MediaEncryptionZrtp);
-
- CoreManager::getInstance()->getCore()->enableLimeX3Dh(!state);
+ CoreManager::getInstance()->getCore()->enableLimeX3Dh(state);
emit limeStateChanged(state);
}
diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp
index a76cf3d1b..b4b17cc7e 100644
--- a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp
+++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp
@@ -455,8 +455,10 @@ void SipAddressesModel::handleMessageCountReset (ChatRoomModel *chatRoomModel) {
}
void SipAddressesModel::handleMessageSent (const shared_ptr &message) {
- const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly()));
- addOrUpdateSipAddress(peerAddress, message);
+ if(message->getChatRoom() && message->getChatRoom()->getPeerAddress()){
+ const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly()));
+ addOrUpdateSipAddress(peerAddress, message);
+ }
}
void SipAddressesModel::handleIsComposingChanged (const shared_ptr &chatRoom) {
diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp
index c9a4f521d..c181d7452 100644
--- a/linphone-app/src/components/timeline/TimelineListModel.cpp
+++ b/linphone-app/src/components/timeline/TimelineListModel.cpp
@@ -71,7 +71,6 @@ TimelineListModel::TimelineListModel(const TimelineListModel* model){
auto newItem = qobject_cast(item)->clone();
connect(newItem.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool)));
connect(newItem.get(), &TimelineModel::chatRoomDeleted, this, &TimelineListModel::onChatRoomDeleted);
- connect(newItem->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel);
mList << newItem;
}
}
@@ -141,7 +140,6 @@ QSharedPointer TimelineListModel::getTimeline(std::shared_ptr model = TimelineModel::create(this, chatRoom);
if(model){
connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool)));
- connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel);
add(model);
return model;
}
@@ -189,7 +187,6 @@ QSharedPointer TimelineListModel::getChatRoomModel(std::shared_pt
QSharedPointer model = TimelineModel::create(this, chatRoom);
if(model){
connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool)));
- connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel);
add(model);
return model->mChatRoomModel;
}
@@ -249,7 +246,17 @@ void TimelineListModel::updateTimelines () {
allChatRooms.remove_if([](std::shared_ptr chatRoom){
if( ChatRoomModel::isTerminated(chatRoom) && chatRoom->getUnreadMessagesCount() > 0)
chatRoom->markAsRead();
- return !chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic) && chatRoom->getConferenceAddress() && chatRoom->getHistoryEventsSize() == 0;
+ if(chatRoom->getState() == linphone::ChatRoom::State::Deleted)
+ return true;
+ if(!chatRoom->hasCapability((int)linphone::ChatRoomCapabilities::Basic)){
+ auto conferenceAddress = chatRoom->getConferenceAddress();
+ if( conferenceAddress && conferenceAddress->getDomain() == Constants::LinphoneDomain) {
+ QString conferenceAddressStr = Utils::coreStringToAppString(conferenceAddress->asStringUriOnly());
+ if( conferenceAddressStr.contains("conf-id"))
+ return true;
+ }
+ }
+ return false;
});
//Remove no more chat rooms
@@ -294,7 +301,6 @@ void TimelineListModel::updateTimelines () {
QSharedPointer model = TimelineModel::create(this, dbChatRoom, callLogs);
if( model){
connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool)));
- connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel);
add(model);
}
}
@@ -306,12 +312,10 @@ void TimelineListModel::add (QSharedPointer timeline){
auto chatRoomModel = timeline->getChatRoomModel();
auto chatRoom = chatRoomModel->getChatRoom();
connect(timeline.get(), &TimelineModel::chatRoomDeleted, this, &TimelineListModel::onChatRoomDeleted);
- if( !chatRoomModel->haveConferenceAddress() || chatRoom->getHistoryEventsSize() != 0) {
- connect(chatRoomModel, &ChatRoomModel::lastUpdateTimeChanged, this, &TimelineListModel::updated);
- ProxyListModel::add(timeline);
- emit layoutChanged();
- emit countChanged();
- }
+ connect(chatRoomModel, &ChatRoomModel::lastUpdateTimeChanged, this, &TimelineListModel::updated);
+ ProxyListModel::add(timeline);
+ emit layoutChanged();
+ emit countChanged();
}
void TimelineListModel::removeChatRoomModel(QSharedPointer model){
@@ -334,7 +338,10 @@ void TimelineListModel::select(ChatRoomModel * chatRoomModel){
if(chatRoomModel) {
auto timeline = getTimeline(chatRoomModel->getChatRoom(), false);
if(timeline){
- timeline->setSelected(true);
+ if(timeline->isUpdating())
+ timeline->delaySelected();
+ else
+ timeline->setSelected(true);
}
}
}
@@ -356,7 +363,6 @@ void TimelineListModel::onChatRoomStateChanged(const std::shared_ptr model = TimelineModel::create(this, chatRoom);
if(model){
connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool)));
- connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel);
add(model);
}
}else if(state == linphone::ChatRoom::State::Deleted || state == linphone::ChatRoom::State::Terminated){
@@ -368,6 +374,11 @@ void TimelineListModel::onChatRoomStateChanged(const std::shared_ptr chatRoom, cons
QObject::connect(this, &TimelineModel::selectedChanged, this, &TimelineModel::updateUnreadCount);
QObject::connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, this, &TimelineModel::onDefaultAccountChanged);
QObject::connect(mChatRoomModel.get(), &ChatRoomModel::chatRoomDeleted, this, &TimelineModel::onChatRoomDeleted);
+ QObject::connect(mChatRoomModel.get(), &ChatRoomModel::updatingChanged, this, &TimelineModel::updatingChanged);
+ QObject::connect(mChatRoomModel.get(), &ChatRoomModel::stateChanged, this, &TimelineModel::onChatRoomStateChanged);
}
if(chatRoom){
mChatRoomListener = std::make_shared();
@@ -103,6 +105,8 @@ TimelineModel::TimelineModel(const TimelineModel * model){
QObject::connect(this, &TimelineModel::selectedChanged, this, &TimelineModel::updateUnreadCount);
QObject::connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, this, &TimelineModel::onDefaultAccountChanged);
QObject::connect(mChatRoomModel.get(), &ChatRoomModel::chatRoomDeleted, this, &TimelineModel::onChatRoomDeleted);
+ QObject::connect(mChatRoomModel.get(), &ChatRoomModel::updatingChanged, this, &TimelineModel::updatingChanged);
+ QObject::connect(mChatRoomModel.get(), &ChatRoomModel::stateChanged, this, &TimelineModel::onChatRoomStateChanged);
}
if(mChatRoomModel->getChatRoom()){
mChatRoomListener = model->mChatRoomListener;
@@ -141,6 +145,10 @@ int TimelineModel::getPresenceStatus() const{
return 0;
}
+bool TimelineModel::isUpdating() const{
+ return !mChatRoomModel || mChatRoomModel->isUpdating();
+}
+
ChatRoomModel *TimelineModel::getChatRoomModel() const{
return mChatRoomModel.get();
}
@@ -165,6 +173,15 @@ void TimelineModel::setSelected(const bool& selected){
}
}
+void TimelineModel::delaySelected(){
+ if( mChatRoomModel->getState() == LinphoneEnums::ChatRoomStateCreated){
+ QTimer::singleShot(200, [&](){// Delay process in order to let GUI time for Timeline building/linking before doing actions
+ setSelected(true);
+ });
+ }else
+ mDelaySelection = true;
+}
+
void TimelineModel::updateUnreadCount(){
if(!mSelected){// updateUnreadCount is called when selected has changed;: So if mSelected is false then we are going out of it.
mChatRoomModel->resetMessageCount();// The reset will appear when the chat room has "mark as read enabled", that means that we should have read messages when going out.
@@ -230,4 +247,11 @@ void TimelineModel::onChatMessageParticipantImdnStateChanged(const std::shared_p
void TimelineModel::onChatRoomDeleted(){
emit chatRoomDeleted();
+}
+
+void TimelineModel::onChatRoomStateChanged(){
+ if(mDelaySelection && mChatRoomModel->getState() == LinphoneEnums::ChatRoomStateCreated){
+ mDelaySelection = false;
+ setSelected(true);
+ }
}
\ No newline at end of file
diff --git a/linphone-app/src/components/timeline/TimelineModel.hpp b/linphone-app/src/components/timeline/TimelineModel.hpp
index 1c33560e1..34cc2a044 100644
--- a/linphone-app/src/components/timeline/TimelineModel.hpp
+++ b/linphone-app/src/components/timeline/TimelineModel.hpp
@@ -52,6 +52,7 @@ public:
Q_PROPERTY(ChatRoomModel* chatRoomModel READ getChatRoomModel CONSTANT)
Q_PROPERTY(bool selected MEMBER mSelected WRITE setSelected NOTIFY selectedChanged)
+ Q_PROPERTY(bool updating READ isUpdating NOTIFY updatingChanged)
QString getFullPeerAddress() const;
@@ -61,7 +62,10 @@ public:
QString getAvatar() const;
int getPresenceStatus() const;
+ bool isUpdating() const;
+
void setSelected(const bool& selected);
+ void delaySelected();
Q_INVOKABLE ChatRoomModel* getChatRoomModel() const;
@@ -102,6 +106,7 @@ public slots:
void updateUnreadCount();
void onDefaultAccountChanged();
void onChatRoomDeleted();
+ void onChatRoomStateChanged();
signals:
void fullPeerAddressChanged();
@@ -112,9 +117,12 @@ signals:
void selectedChanged(bool selected);
void conferenceLeft();
void chatRoomDeleted();
+ void updatingChanged();
private:
+ bool mDelaySelection = false;
+
void connectTo(ChatRoomListener * listener);
std::shared_ptr mChatRoomListener;
diff --git a/linphone-app/src/utils/Constants.cpp b/linphone-app/src/utils/Constants.cpp
index 8e4483ab2..1d6191af5 100644
--- a/linphone-app/src/utils/Constants.cpp
+++ b/linphone-app/src/utils/Constants.cpp
@@ -65,6 +65,7 @@ constexpr int Constants::ThumbnailImageFileHeight;
constexpr qint64 Constants::FileSizeLimit;
constexpr char Constants::DefaultXmlrpcUri[];
+constexpr char Constants::DefaultUploadLogsServer[];
constexpr char Constants::DefaultConferenceURI[];
constexpr char Constants::DefaultVideoConferenceURI[];
constexpr char Constants::DefaultLimeServerURL[];
diff --git a/linphone-app/src/utils/Constants.hpp b/linphone-app/src/utils/Constants.hpp
index 4d490992b..2140a8a52 100644
--- a/linphone-app/src/utils/Constants.hpp
+++ b/linphone-app/src/utils/Constants.hpp
@@ -36,21 +36,17 @@ public:
//----------------------------------------------------------------------------------
- static constexpr char WindowIconPath[] = ":/assets/images/linphone_logo.svg";
static constexpr char DefaultLocale[] = "en";
-
- static constexpr char ApplicationMinimalQtVersion[] = "5.10.0";
static constexpr char DefaultFont[] = "Noto Sans";
static constexpr size_t MaxLogsCollectionSize = 10485760*5; // 50MB.
-
#ifdef ENABLE_UPDATE_CHECK
static constexpr int VersionUpdateCheckInterval = 86400000; // 24 hours in milliseconds.
#endif // ifdef ENABLE_UPDATE_CHECK
static constexpr char DefaultXmlrpcUri[] = "https://subscribe.linphone.org:444/wizard.php";
- static constexpr char LinphoneDomain[] = "sip.linphone.org";
+ static constexpr char DefaultUploadLogsServer[] = "https://www.linphone.org:444/lft.php";
static constexpr char DefaultContactParameters[] = "message-expires=604800";
static constexpr char DefaultContactParametersOnRemove[] = "message-expires=0";
static constexpr int DefaultExpires = 3600;
@@ -69,9 +65,6 @@ public:
static constexpr char LinphoneBZip2_dll[] = "https://www.linphone.org/releases/windows/tools/bzip2/bzip2.dll";
static constexpr char DefaultRlsUri[] = "sips:rls@sip.linphone.org";
static constexpr char DefaultLogsEmail[] = "linphone-desktop@belledonne-communications.com";
- static constexpr char DefaultConferenceURI[] = "sip:conference-factory@sip.linphone.org";
- static constexpr char DefaultVideoConferenceURI[] = "sip:videoconference-factory@sip.linphone.org";
- static constexpr char DefaultLimeServerURL[] = "https://lime.linphone.org/lime-server/lime-server.php";
static constexpr char DefaultFlexiAPIURL[] = "http://fs-test-sandbox.linphone.org/flexiapi/api/";// Need "/" at the end
static constexpr char RemoteProvisioningURL[] = "http://fs-test-sandbox.linphone.org/flexiapi/provisioning";
@@ -94,7 +87,18 @@ public:
static constexpr qint64 FileSizeLimit = 524288000;// In Bytes.
static constexpr int ThumbnailImageFileWidth = 100;
static constexpr int ThumbnailImageFileHeight = 100;
+
+//--------------------------------------------------------------------------------
+// LINPHONE
+//--------------------------------------------------------------------------------
+ static constexpr char LinphoneDomain[] = "sip.linphone.org"; // Use for checking if config are a Linphone
+ static constexpr char WindowIconPath[] = ":/assets/images/linphone_logo.svg";
+ static constexpr char ApplicationMinimalQtVersion[] = "5.10.0";
+ static constexpr char DefaultConferenceURI[] = "sip:conference-factory@sip.linphone.org"; // Default for a Linphone account
+ static constexpr char DefaultVideoConferenceURI[] = "sip:videoconference-factory@sip.linphone.org"; // Default for a Linphone account
+ static constexpr char DefaultLimeServerURL[] = "https://lime.linphone.org/lime-server/lime-server.php"; // Default for a Linphone account
+
static constexpr char PathAssistantConfig[] = "/" EXECUTABLE_NAME "/assistant/";
static constexpr char PathAvatars[] = "/avatars/";
static constexpr char PathCaptures[] = "/" EXECUTABLE_NAME "/captures/";
@@ -146,8 +150,6 @@ public:
// 3 = CPIM on basic chat rooms
// 4 = RTP bundle mode
// 5 = Video Conference URI
-
-
//--------------------------------------------------------------------------------
// CISCO
//--------------------------------------------------------------------------------
diff --git a/linphone-app/src/utils/LinphoneEnums.cpp b/linphone-app/src/utils/LinphoneEnums.cpp
index 90026d573..5b8aa6a7a 100644
--- a/linphone-app/src/utils/LinphoneEnums.cpp
+++ b/linphone-app/src/utils/LinphoneEnums.cpp
@@ -25,14 +25,19 @@
// =============================================================================
void LinphoneEnums::registerMetaTypes(){
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
- qRegisterMetaType();
qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
qRegisterMetaType();
- qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
}
linphone::MediaEncryption LinphoneEnums::toLinphone(const LinphoneEnums::MediaEncryption& data){
@@ -63,6 +68,14 @@ LinphoneEnums::ChatMessageState LinphoneEnums::fromLinphone(const linphone::Chat
return static_cast(data);
}
+linphone::ChatRoom::State LinphoneEnums::toLinphone(const LinphoneEnums::ChatRoomState& data){
+ return static_cast