diff --git a/src/api/conversationmodel.h b/src/api/conversationmodel.h
index a64f1461d457f9afc7e78fafa43c0b2e1fc5d33f..fe229198926fc4d1615f362925fc90ab8e2cdf37 100644
--- a/src/api/conversationmodel.h
+++ b/src/api/conversationmodel.h
@@ -111,21 +111,21 @@ public:
      * @param uid conversation uid
      * @return reference to conversation info with given uid
      */
-    OptRef<conversation::Info> getConversationForUid(const QString& uid);
+    OptRef<conversation::Info> getConversationForUid(const QString& uid) const;
 
     /**
      * Get conversation for a given peer uri
      * @param uri peer uri
      * @return reference to conversation info with given peer uri
      */
-    OptRef<conversation::Info> getConversationForPeerUri(const QString& uri);
+    OptRef<conversation::Info> getConversationForPeerUri(const QString& uri) const;
 
     /**
      * Get conversation for a given call id
      * @param callId call id
      * @return reference to conversation info with given call id
      */
-    OptRef<conversation::Info> getConversationForCallId(const QString& callId);
+    OptRef<conversation::Info> getConversationForCallId(const QString& callId) const;
 
     /**
      * Get conversations that could be added to conference
@@ -360,6 +360,15 @@ public:
     int pendingRequestCount() const;
     const VectorString peersForConversation(const QString& conversationId);
 
+    // Presentation
+
+    /**
+     * Get conversation title. This means the title to show in the smartlist
+     * @param conversationId
+     * @return the title to display
+     */
+    QString title(const QString& conversationId) const;
+
 Q_SIGNALS:
     /**
      * Emitted when a conversation receives a new interaction
diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp
index 347e9977c8cf98eb87b11852c5a9860e3e10ae35..d0a78f8a87e40f3bc8b4bd575aa662098a058f31 100644
--- a/src/contactmodel.cpp
+++ b/src/contactmodel.cpp
@@ -501,7 +501,7 @@ ContactModel::bestNameForContact(const QString& contactUri) const
         qDebug() << "ContactModel::bestNameForContact" << e.what();
     }
 
-    return {};
+    return contactUri;
 }
 
 const QString
@@ -518,7 +518,7 @@ ContactModel::bestIdForContact(const QString& contactUri) const
         qDebug() << "ContactModel::bestIdForContact" << e.what();
     }
 
-    return {};
+    return contactUri;
 }
 
 const QString
diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp
index 7f83b7c2af60f76424c4e0afef916d2e14d86709..2dd6647e335a2bab606797a21bb606ddf13c0418 100644
--- a/src/conversationmodel.cpp
+++ b/src/conversationmodel.cpp
@@ -87,7 +87,7 @@ public:
      * @return a reference to a conversation with given uid
      */
     std::reference_wrapper<conversation::Info> getConversation(
-        const FilterPredicate& pred, const bool searchResultIncluded = false);
+        const FilterPredicate& pred, const bool searchResultIncluded = false) const;
 
     /**
      * return a reference to a conversation with given uid.
@@ -96,7 +96,7 @@ public:
      * @return a reference to a conversation with the given uid.
      */
     std::reference_wrapper<conversation::Info> getConversationForUid(
-        const QString& uid, const bool searchResultIncluded = false);
+        const QString& uid, const bool searchResultIncluded = false) const;
 
     /**
      * return a reference to a conversation with participant.
@@ -107,7 +107,7 @@ public:
      * return an active one-to-one conversation.
      */
     std::reference_wrapper<conversation::Info> getConversationForPeerUri(
-        const QString& uri, const bool searchResultIncluded = false);
+        const QString& uri, const bool searchResultIncluded = false) const;
 
     /**
      * return a conversation index from conversations or -1 if no index is found.
@@ -627,7 +627,7 @@ ConversationModel::getFilteredConversations(const profile::Type& profileType,
 }
 
 OptRef<conversation::Info>
-ConversationModel::getConversationForUid(const QString& uid)
+ConversationModel::getConversationForUid(const QString& uid) const
 {
     try {
         return std::make_optional(pimpl_->getConversationForUid(uid, true));
@@ -637,7 +637,7 @@ ConversationModel::getConversationForUid(const QString& uid)
 }
 
 OptRef<conversation::Info>
-ConversationModel::getConversationForPeerUri(const QString& uri)
+ConversationModel::getConversationForPeerUri(const QString& uri) const
 {
     try {
         return std::make_optional(pimpl_->getConversation(
@@ -657,7 +657,7 @@ ConversationModel::getConversationForPeerUri(const QString& uri)
 }
 
 OptRef<conversation::Info>
-ConversationModel::getConversationForCallId(const QString& callId)
+ConversationModel::getConversationForCallId(const QString& callId) const
 {
     try {
         return std::make_optional(pimpl_->getConversation(
@@ -995,6 +995,36 @@ ConversationModel::pendingRequestCount() const
     return pendingRequestCount;
 }
 
+QString
+ConversationModel::title(const QString& conversationId) const
+{
+    auto conversationOpt = getConversationForUid(conversationId);
+    if (!conversationOpt.has_value()) {
+        return {};
+    }
+    auto& conversation = conversationOpt->get();
+    if (conversation.mode == conversation::Mode::NON_SWARM) {
+        // In this case, we can just display contact name
+        return owner.contactModel->bestNameForContact(conversation.participants.at(0));
+    }
+    // In this case, it depends if we have infos from daemon (TODO conferencesInfo() support)
+    // NOTE: Do not call any daemon method there as title() is called a lot for drawing
+    QString title;
+    auto idx = 0;
+    for (const auto& member : conversation.participants) {
+        if (member == owner.profileInfo.uri) {
+            title += owner.accountModel->bestNameForAccount(owner.id);
+        } else {
+            title += owner.contactModel->bestNameForContact(member);
+        }
+        idx += 1;
+        if (idx != conversation.participants.size()) {
+            title += ", ";
+        }
+    }
+    return title;
+}
+
 void
 ConversationModel::sendMessage(const QString& uid, const QString& body, const QString& parentId)
 {
@@ -2789,7 +2819,8 @@ ConversationModelPimpl::indexOf(const QString& uid) const
 }
 
 std::reference_wrapper<conversation::Info>
-ConversationModelPimpl::getConversation(const FilterPredicate& pred, const bool searchResultIncluded)
+ConversationModelPimpl::getConversation(const FilterPredicate& pred,
+                                        const bool searchResultIncluded) const
 {
     auto conv = std::find_if(conversations.cbegin(), conversations.cend(), pred);
     if (conv != conversations.cend()) {
@@ -2807,7 +2838,8 @@ ConversationModelPimpl::getConversation(const FilterPredicate& pred, const bool
 }
 
 std::reference_wrapper<conversation::Info>
-ConversationModelPimpl::getConversationForUid(const QString& uid, const bool searchResultIncluded)
+ConversationModelPimpl::getConversationForUid(const QString& uid,
+                                              const bool searchResultIncluded) const
 {
     return getConversation([uid](const conversation::Info& conv) -> bool { return uid == conv.uid; },
                            searchResultIncluded);
@@ -2815,7 +2847,7 @@ ConversationModelPimpl::getConversationForUid(const QString& uid, const bool sea
 
 std::reference_wrapper<conversation::Info>
 ConversationModelPimpl::getConversationForPeerUri(const QString& uri,
-                                                  const bool searchResultIncluded)
+                                                  const bool searchResultIncluded) const
 {
     return getConversation(
         [this, uri](const conversation::Info& conv) -> bool {