From 8c6b1956485cc12449825e614561b067638d5f22 Mon Sep 17 00:00:00 2001
From: Ming Rui Zhang <mingrui.zhang@savoirfairelinux.com>
Date: Tue, 18 May 2021 16:09:42 -0400
Subject: [PATCH] newcallmodel: pending conferencees reimplementation

1. Change the container structure
2. Notify when the data is changed

Change-Id: Ia791a58cdc2020ceeff9a311bc2a923e1c638b5c
---
 src/api/newcallmodel.h | 35 +++++++++++++++++++++++-
 src/newcallmodel.cpp   | 60 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index 4f163f28..8c5c3d81 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -44,7 +44,14 @@ struct Info;
 }
 namespace call {
 struct Info;
-}
+
+struct PendingConferenceeInfo
+{
+    QString uri;
+    QString callId;
+    QString callIdToJoin;
+};
+} // namespace call
 class NewAccountModel;
 
 /**
@@ -277,6 +284,12 @@ public:
      */
     bool isConferenceHost(const QString& callId);
 
+    /**
+     * Get the list of lists of pending conferencees callId , contact uri, and join callId
+     * @return pending conferencees
+     */
+    const QList<call::PendingConferenceeInfo>& getPendingConferencees();
+
 Q_SIGNALS:
     /**
      * Emitted when a call state changes
@@ -337,6 +350,26 @@ Q_SIGNALS:
                                 const QSet<QString>& peerRec,
                                 bool state) const;
 
+    /*!
+     * Emitted before new pending conferences are inserted into the underlying list
+     * @param position The starting row of the insertion
+     * @param rows The number of items inserted
+     */
+    void beginInsertPendingConferenceesRows(int position, int rows = 1) const;
+
+    //! Emitted once the insertion of new pending conferences is complete
+    void endInsertPendingConferenceesRows() const;
+
+    /*!
+     * Emitted before new pending conferences are removed from the underlying list
+     * @param position The starting row of the removal
+     * @param rows The number of items removed
+     */
+    void beginRemovePendingConferenceesRows(int position, int rows = 1) const;
+
+    //! Emitted once the removal of new pending conferences is complete
+    void endRemovePendingConferenceesRows() const;
+
 private:
     std::unique_ptr<NewCallModelPimpl> pimpl_;
 };
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index c578e5bd..44b16883 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -149,7 +149,7 @@ public:
     bool manageCurrentCall_ {true};
     QString currentCall_ {};
 
-    std::map<QString, QString> pendingConferences_;
+    QList<call::PendingConferenceeInfo> pendingConferencees_;
 public Q_SLOTS:
     /**
      * Listen from CallbacksHandler when a call is incoming
@@ -270,7 +270,7 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly)
     auto callId = isAudioOnly
                       ? CallManager::instance().placeCall(owner.id, uri, {{"AUDIO_ONLY", "true"}})
                       : CallManager::instance().placeCall(owner.id, uri);
-#else  // dbus
+#else // dbus
     // do not use auto here (QDBusPendingReply<QString>)
     QString callId = isAudioOnly
                          ? CallManager::instance().placeCallWithDetails(owner.id,
@@ -492,7 +492,14 @@ NewCallModel::joinCalls(const QString& callIdA, const QString& callIdB) const
             emit callAddedToConference(call, conf);
 
         // Remove from pendingConferences_
-        pimpl_->pendingConferences_.erase(call);
+        for (int i = 0; i < pimpl_->pendingConferencees_.size(); ++i) {
+            if (pimpl_->pendingConferencees_.at(i).callId == call) {
+                Q_EMIT beginRemovePendingConferenceesRows(i);
+                pimpl_->pendingConferencees_.removeAt(i);
+                Q_EMIT endRemovePendingConferenceesRows();
+                break;
+            }
+        }
     } else {
         CallManager::instance().joinParticipant(callIdA, callIdB);
         // NOTE: This will trigger slotConferenceCreated.
@@ -503,7 +510,9 @@ QString
 NewCallModel::callAndAddParticipant(const QString uri, const QString& callId, bool audioOnly)
 {
     auto newCallId = createCall(uri, audioOnly);
-    pimpl_->pendingConferences_.insert({newCallId, callId});
+    Q_EMIT beginInsertPendingConferenceesRows(0);
+    pimpl_->pendingConferencees_.prepend({uri, newCallId, callId});
+    Q_EMIT endInsertPendingConferenceesRows();
     return newCallId;
 }
 
@@ -548,6 +557,12 @@ NewCallModel::getSIPCallStatusString(const short& statusCode)
     return "";
 }
 
+const QList<call::PendingConferenceeInfo>&
+NewCallModel::getPendingConferencees()
+{
+    return pimpl_->pendingConferencees_;
+}
+
 NewCallModelPimpl::NewCallModelPimpl(const NewCallModel& linked,
                                      const CallbacksHandler& callbacksHandler,
                                      const BehaviorController& behaviorController)
@@ -666,10 +681,15 @@ NewCallModel::setCurrentCall(const QString& callId) const
 {
     if (!pimpl_->manageCurrentCall_)
         return;
-    auto it = pimpl_->pendingConferences_.find(callId);
+    auto it = std::find_if(pimpl_->pendingConferencees_.begin(),
+                           pimpl_->pendingConferencees_.end(),
+                           [callId](const lrc::api::call::PendingConferenceeInfo& info) -> bool {
+                               return info.callId == callId;
+                           });
+
     // Set current call only if not adding this call
     // to a current conference
-    if (it != pimpl_->pendingConferences_.end())
+    if (it != pimpl_->pendingConferencees_.end())
         return;
     if (!hasCall(callId))
         return;
@@ -905,6 +925,16 @@ NewCallModelPimpl::slotCallStateChanged(const QString& callId, const QString& st
 
     if (call->status == call::Status::ENDED) {
         emit linked.callEnded(callId);
+
+        // Remove from pendingConferences_
+        for (int i = 0; i < pendingConferencees_.size(); ++i) {
+            if (pendingConferencees_.at(i).callId == callId) {
+                Q_EMIT linked.beginRemovePendingConferenceesRows(i);
+                pendingConferencees_.removeAt(i);
+                Q_EMIT linked.endRemovePendingConferenceesRows();
+                break;
+            }
+        }
     } else if (call->status == call::Status::IN_PROGRESS) {
         if (previousStatus == call::Status::INCOMING_RINGING
             || previousStatus == call::Status::OUTGOING_RINGING) {
@@ -919,9 +949,12 @@ NewCallModelPimpl::slotCallStateChanged(const QString& callId, const QString& st
             sendProfile(callId);
         }
         // Add to calls if in pendingConferences_
-        auto it = pendingConferences_.find(callId);
-        if (it != pendingConferences_.end()) {
-            linked.joinCalls(it->second, it->first);
+        for (int i = 0; i < pendingConferencees_.size(); ++i) {
+            if (pendingConferencees_.at(i).callId == callId) {
+                linked.joinCalls(pendingConferencees_.at(i).callIdToJoin,
+                                 pendingConferencees_.at(i).callId);
+                break;
+            }
         }
     } else if (call->status == call::Status::PAUSED) {
         currentCall_ = "";
@@ -1042,7 +1075,14 @@ NewCallModelPimpl::slotConferenceCreated(const QString& confId)
     foreach (const auto& call, callList) {
         emit linked.callAddedToConference(call, confId);
         // Remove call from pendingConferences_
-        pendingConferences_.erase(call);
+        for (int i = 0; i < pendingConferencees_.size(); ++i) {
+            if (pendingConferencees_.at(i).callId == call) {
+                Q_EMIT linked.beginRemovePendingConferenceesRows(i);
+                pendingConferencees_.removeAt(i);
+                Q_EMIT linked.endRemovePendingConferenceesRows();
+                break;
+            }
+        }
     }
 }
 
-- 
GitLab