diff --git a/src/conversationpopupmenu.cpp b/src/conversationpopupmenu.cpp
index 1a232e923cb1caa8d851b499415c3afeb9f8d358..082f01d78c9b924ddfbf8cb3cdce29231eb21665 100644
--- a/src/conversationpopupmenu.cpp
+++ b/src/conversationpopupmenu.cpp
@@ -33,6 +33,10 @@
 // Qt
 #include <QItemSelectionModel>
 
+namespace { namespace details {
+class CppImpl;
+}}
+
 struct _ConversationPopupMenu
 {
     GtkMenu parent;
@@ -50,18 +54,30 @@ struct _ConversationPopupMenuPrivate
     GtkTreeView *treeview;
 
     AccountInfoPointer const *accountInfo_;
-    int row_;
+    details::CppImpl* cpp {nullptr};
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE(ConversationPopupMenu, conversation_popup_menu, GTK_TYPE_MENU);
 
 #define CONVERSATION_POPUP_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CONVERSATION_POPUP_MENU_TYPE, ConversationPopupMenuPrivate))
 
+namespace { namespace details {
+class CppImpl
+{
+public:
+    explicit CppImpl();
+    QString uid_;
+};
+CppImpl::CppImpl()
+    : uid_("")
+{}
+}}
+
 static void
 show_profile(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* priv)
 {
-    if (!priv) return;
-    auto *profile = profile_view_new(*priv->accountInfo_, priv->row_);
+    if (!priv or !priv->cpp) return;
+    auto *profile = profile_view_new(*priv->accountInfo_, priv->cpp->uid_);
     if (profile) gtk_widget_show_all(GTK_WIDGET(profile));
 }
 
@@ -70,12 +86,13 @@ remove_history_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenu
 {
     try
     {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
+        if (!priv->cpp) return;
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(priv->cpp->uid_);
         (*priv->accountInfo_)->conversationModel->clearHistory(conversation.uid);
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -84,12 +101,12 @@ remove_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate*
 {
     try
     {
-        auto conversationUid = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_).uid;
-        (*priv->accountInfo_)->conversationModel->removeConversation(conversationUid);
+        if (!priv->cpp) return;
+        (*priv->accountInfo_)->conversationModel->removeConversation(priv->cpp->uid_);
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -98,7 +115,8 @@ unblock_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate
 {
     try
     {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
+        if (!priv->cpp) return;
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(priv->cpp->uid_);
         auto uri = conversation.participants[0];
 
         auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(uri);
@@ -112,7 +130,7 @@ unblock_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -121,12 +139,12 @@ block_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate*
 {
     try
     {
-        auto conversationUid = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_).uid;
-        (*priv->accountInfo_)->conversationModel->removeConversation(conversationUid, true);
+        if (!priv->cpp) return;
+        (*priv->accountInfo_)->conversationModel->removeConversation(priv->cpp->uid_, true);
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -135,12 +153,12 @@ add_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr
 {
     try
     {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
-        (*priv->accountInfo_)->conversationModel->makePermanent(conversation.uid);
+        if (!priv->cpp) return;
+        (*priv->accountInfo_)->conversationModel->makePermanent(priv->cpp->uid_);
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -149,10 +167,11 @@ place_video_call(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr
 {
     try
     {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
+        if (!priv->cpp) return;
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(priv->cpp->uid_);
         (*priv->accountInfo_)->conversationModel->placeCall(conversation.uid);
     } catch (...) {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -161,10 +180,11 @@ place_audio_call(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr
 {
     try
     {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
+        if (!priv->cpp) return;
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(priv->cpp->uid_);
         (*priv->accountInfo_)->conversationModel->placeAudioOnlyCall(conversation.uid);
     } catch (...) {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
     }
 }
 
@@ -182,13 +202,24 @@ update(GtkTreeSelection *selection, ConversationPopupMenu *self)
     GtkTreeIter iter;
     GtkTreeModel *model;
     if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return;
-    auto path = gtk_tree_model_get_path(model, &iter);
-    auto idx = gtk_tree_path_get_indices(path);
-    auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(idx[0]);
-    priv->row_ = idx[0];
+
+    gchar *uid;
+    gtk_tree_model_get (model, &iter,
+                        0 /* col# */, &uid /* data */,
+                        -1);
+
+    auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(uid);
+    if (priv->cpp) priv->cpp->uid_ = uid;
     try {
+        if (conversation.participants.isEmpty()) {
+            g_free(uid);
+            return;
+        }
         auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(conversation.participants.front());
-        if (contactInfo.profileInfo.uri.isEmpty()) return;
+        if (contactInfo.profileInfo.uri.isEmpty()) {
+            g_free(uid);
+            return;
+        }
 
         // we always build a menu, however in some cases some or all of the conversations will be deactivated
         // we prefer this to having an empty menu because GTK+ behaves weird in the empty menu case
@@ -248,11 +279,16 @@ update(GtkTreeSelection *selection, ConversationPopupMenu *self)
     } catch (const std::out_of_range&) {
         // ContactModel::getContact() exception
     }
+
+    g_free(uid);
 }
 
 static void
 conversation_popup_menu_dispose(GObject *object)
 {
+    auto* priv = CONVERSATION_POPUP_MENU_GET_PRIVATE(object);
+    delete priv->cpp;
+    priv->cpp = nullptr;
     G_OBJECT_CLASS(conversation_popup_menu_parent_class)->dispose(object);
 }
 
@@ -284,6 +320,7 @@ conversation_popup_menu_new (GtkTreeView *treeview, AccountInfoPointer const & a
     priv->accountInfo_ = &accountInfo;
 
     priv->treeview = treeview;
+    priv->cpp = new details::CppImpl();
     GtkTreeSelection *selection = gtk_tree_view_get_selection(priv->treeview);
 
     // build the menu for the first time
diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp
index ee1d97f072af4d0b9561fff31527e65824972590..4e02566173361193cb7f58c2c1e75a0870659cfa 100644
--- a/src/conversationsview.cpp
+++ b/src/conversationsview.cpp
@@ -57,6 +57,10 @@ struct _ConversationsViewClass
 
 typedef struct _ConversationsViewPrivate ConversationsViewPrivate;
 
+namespace { namespace details {
+class CppImpl;
+}}
+
 struct _ConversationsViewPrivate
 {
     AccountInfoPointer const *accountInfo_;
@@ -64,10 +68,13 @@ struct _ConversationsViewPrivate
     GtkWidget* popupMenu_;
 
     bool useDarkTheme {false};
+    details::CppImpl* cpp {nullptr};
 
     QMetaObject::Connection selection_updated;
     QMetaObject::Connection layout_changed;
     QMetaObject::Connection modelSortedConnection_;
+    QMetaObject::Connection searchChangedConnection_;
+    QMetaObject::Connection searchStatusChangedConnection_;
     QMetaObject::Connection conversationUpdatedConnection_;
     QMetaObject::Connection filterChangedConnection_;
     QMetaObject::Connection callChangedConnection_;
@@ -77,6 +84,22 @@ G_DEFINE_TYPE_WITH_PRIVATE(ConversationsView, conversations_view, GTK_TYPE_TREE_
 
 #define CONVERSATIONS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CONVERSATIONS_VIEW_TYPE, ConversationsViewPrivate))
 
+namespace { namespace details {
+
+class CppImpl
+{
+public:
+    explicit CppImpl();
+
+    QString status;
+};
+
+CppImpl::CppImpl()
+    : status("")
+{}
+
+}}
+
 static void
 render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
                      GtkCellRenderer *cell,
@@ -90,18 +113,30 @@ render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     if (row == -1) return;
     auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(self);
     if (!priv) return;
+    gchar *uid;
+
+    gtk_tree_model_get (model, iter,
+                        0 /* col# */, &uid /* data */,
+                        -1);
+
     try
     {
         // Draw first contact.
         // NOTE: We just draw the first contact, must change this for conferences when they will have their own object
-        auto conversationInfo = (*priv->accountInfo_)->conversationModel->filteredConversation(row);
-        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(conversationInfo.participants.front());
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(uid);
+        auto isPresent = false;
+        auto isBanned = false;
+        if (not conversation.participants.empty()) {
+            auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(conversation.participants.front());
+            isPresent = contactInfo.isPresent;
+            isBanned = contactInfo.isBanned;
+        }
         std::shared_ptr<GdkPixbuf> image;
         auto var_photo = GlobalInstances::pixmapManipulator().conversationPhoto(
-            conversationInfo,
+            conversation,
             **(priv->accountInfo_),
             QSize(50, 50),
-            contactInfo.isPresent
+            isPresent
         );
         image = var_photo.value<std::shared_ptr<GdkPixbuf>>();
 
@@ -111,12 +146,14 @@ render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
         g_object_set(G_OBJECT(cell), "pixbuf", image.get(), NULL);
 
         // Banned contacts should be displayed with grey bg
-        g_object_set(G_OBJECT(cell), "cell-background", contactInfo.isBanned ? "#BDBDBD" : NULL, NULL);
+        g_object_set(G_OBJECT(cell), "cell-background", isBanned ? "#BDBDBD" : NULL, NULL);
     }
     catch (const std::exception&)
     {
         g_warning("Can't get conversation at row %i", row);
     }
+
+    g_free(uid);
 }
 
 static void
@@ -141,10 +178,6 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(treeview);
     if (!priv) return;
 
-    auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row);
-    auto contactUri = conversation.participants.front();
-    auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
-
     auto grey = priv->useDarkTheme? "#bbb" : "#666";
 
     gtk_tree_model_get (model, iter,
@@ -156,7 +189,16 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
                         -1);
 
     auto bestId = std::string(registeredName).empty() ? uri: registeredName;
-    if (contactInfo.isBanned) {
+
+    auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(uid);
+    auto isBanned = false;
+    if (not conversation.participants.empty()) {
+        auto contactUri = conversation.participants.front();
+        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
+        isBanned = contactInfo.isBanned;
+    }
+
+    if (isBanned) {
         // Contact is banned, display it clearly
         text = g_markup_printf_escaped(
             "<span font_weight=\"bold\">%s</span>\n<span size=\"smaller\" font_weight=\"bold\">Banned contact</span>",
@@ -191,7 +233,7 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     }
 
     // Banned contacts should be displayed with grey bg
-    g_object_set(G_OBJECT(cell), "cell-background", contactInfo.isBanned ? "#BDBDBD" : NULL, NULL);
+    g_object_set(G_OBJECT(cell), "cell-background", isBanned ? "#BDBDBD" : NULL, NULL);
 
     g_object_set(G_OBJECT(cell), "markup", text, NULL);
     g_free(text);
@@ -216,9 +258,23 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     auto path = gtk_tree_model_get_path(model, iter);
     auto row = std::atoi(gtk_tree_path_to_string(path));
     g_return_if_fail(row != -1);
+    gchar *uid;
 
-    try {
-        auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row);
+    gtk_tree_model_get (model, iter,
+                        0 /* col# */, &uid /* data */,
+                        -1);
+    if (g_strcmp0(uid, "") == 0) {
+        g_object_set(G_OBJECT(cell), "markup", "", NULL);
+        g_free(uid);
+        return;
+    }
+
+    try
+    {
+        // Draw first contact.
+        // NOTE: We just draw the first contact, must change this for conferences when they will have their own object
+        auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(uid);
+        if (conversation.participants.empty()) return;
         auto contactUri = conversation.participants.front();
         auto& contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
 
@@ -230,6 +286,7 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
             auto call = (*priv->accountInfo_)->callModel->getCall(callId);
             if (call.status != lrc::api::call::Status::ENDED) {
                 g_object_set(G_OBJECT(cell), "markup", qUtf8Printable(lrc::api::call::to_string(call.status)), NULL);
+                g_free(uid);
                 return;
             }
         }
@@ -249,12 +306,14 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
             g_object_set(G_OBJECT(cell), "markup", text, NULL);
 
             g_free(text);
+            g_free(uid);
             return;
         }
     } catch (const std::exception&) {
         g_warning("Can't get conversation at row %i", row);
     }
 
+    g_free(uid);
     g_object_set(G_OBJECT(cell), "markup", "", NULL);
 }
 
@@ -321,33 +380,51 @@ create_and_fill_model(ConversationsView *self)
     if(!priv) GTK_TREE_MODEL (store);
     GtkTreeIter iter;
 
-    for (auto conversation : (*priv->accountInfo_)->conversationModel->allFilteredConversations()) {
-        if (conversation.participants.empty()) {
-            g_debug("Found conversation with empty list of participants - most likely the result of earlier bug.");
-            break;
-        }
+    if (priv->cpp && !priv->cpp->status.isEmpty()) {
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            0 /* col # */ , "" /* celldata */,
+                            1 /* col # */ , qUtf8Printable(priv->cpp->status) /* celldata */,
+                            2 /* col # */ , "" /* celldata */,
+                            3 /* col # */ , "" /* celldata */,
+                            4 /* col # */ , "" /* celldata */,
+                            5 /* col # */ , "" /* celldata */,
+                            -1 /* end */);
+    }
 
-        auto contactUri = conversation.participants.front();
-        try {
-            auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
-            auto lastMessage = conversation.interactions.empty() ? "" :
-                conversation.interactions.at(conversation.lastMessageUid).body;
-            std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' ');
-            gtk_list_store_append (store, &iter);
-            auto alias = contactInfo.profileInfo.alias;
-            alias.remove('\r');
-            gtk_list_store_set (store, &iter,
-                                0 /* col # */ , qUtf8Printable(conversation.uid) /* celldata */,
-                                1 /* col # */ , qUtf8Printable(alias) /* celldata */,
-                                2 /* col # */ , qUtf8Printable(contactInfo.profileInfo.uri) /* celldata */,
-                                3 /* col # */ , qUtf8Printable(contactInfo.registeredName) /* celldata */,
-                                4 /* col # */ , qUtf8Printable(contactInfo.profileInfo.avatar) /* celldata */,
-                                5 /* col # */ , qUtf8Printable(lastMessage) /* celldata */,
-                                -1 /* end */);
-        } catch (const std::out_of_range&) {
-            // ContactModel::getContact() exception
+
+    auto fillModelLambda = [&](const auto& queue) {
+        for (auto conversation : queue) {
+            if (conversation.participants.empty()) {
+                g_debug("Found conversation with empty list of participants - most likely the result of earlier bug.");
+                break;
+            }
+
+            auto contactUri = conversation.participants.front();
+            try {
+                auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
+                auto lastMessage = conversation.interactions.empty() ? "" :
+                    conversation.interactions.at(conversation.lastMessageUid).body;
+                std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' ');
+                gtk_list_store_append (store, &iter);
+                auto alias = contactInfo.profileInfo.alias;
+                alias.remove('\r');
+                gtk_list_store_set (store, &iter,
+                                    0 /* col # */ , qUtf8Printable(conversation.uid) /* celldata */,
+                                    1 /* col # */ , qUtf8Printable(alias) /* celldata */,
+                                    2 /* col # */ , qUtf8Printable(contactInfo.profileInfo.uri) /* celldata */,
+                                    3 /* col # */ , qUtf8Printable(contactInfo.registeredName) /* celldata */,
+                                    4 /* col # */ , qUtf8Printable(contactInfo.profileInfo.avatar) /* celldata */,
+                                    5 /* col # */ , qUtf8Printable(lastMessage) /* celldata */,
+                                    -1 /* end */);
+            } catch (const std::out_of_range&) {
+                // ContactModel::getContact() exception
+            }
         }
-    }
+    };
+
+    fillModelLambda((*priv->accountInfo_)->conversationModel->getAllSearchResults());
+    fillModelLambda((*priv->accountInfo_)->conversationModel->allFilteredConversations());
 
     return GTK_TREE_MODEL (store);
 }
@@ -568,7 +645,7 @@ on_drag_data_received(GtkWidget        *treeview,
 static void
 build_conversations_view(ConversationsView *self)
 {
-    auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(self);
+    auto* priv = CONVERSATIONS_VIEW_GET_PRIVATE(self);
     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(self), FALSE);
 
     auto model = create_and_fill_model(self);
@@ -629,6 +706,60 @@ build_conversations_view(ConversationsView *self)
         gtk_tree_view_set_model(GTK_TREE_VIEW(self),
                                 GTK_TREE_MODEL(model));
     });
+
+
+    priv->searchChangedConnection_ = QObject::connect(
+    &*(*priv->accountInfo_)->conversationModel,
+    &lrc::api::ConversationModel::searchResultUpdated,
+    [self] () {
+        auto model = create_and_fill_model(self);
+
+        gtk_tree_view_set_model(GTK_TREE_VIEW(self),
+                                GTK_TREE_MODEL(model));
+    });
+    priv->searchStatusChangedConnection_ = QObject::connect(
+    &*(*priv->accountInfo_)->conversationModel,
+    &lrc::api::ConversationModel::searchStatusChanged,
+    [self] (const QString& status) {
+        auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(self);
+        if (!priv or !priv->cpp) return;
+        priv->cpp->status = status;
+        if (status.isEmpty()) return;
+
+        auto model = gtk_tree_view_get_model(GTK_TREE_VIEW(self));
+        GtkTreeIter iter;
+
+        auto addItem = true;
+        if (gtk_tree_model_iter_children(model, &iter, nullptr)) {
+            gchar *conversationUid = nullptr;
+            gtk_tree_model_get(model, &iter, 0, &conversationUid, -1);
+            if (g_strcmp0(conversationUid, "") == 0) {
+                addItem = false;
+                gtk_list_store_set (GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(self))), &iter,
+                                    0 /* col # */ , "" /* celldata */,
+                                    1 /* col # */ , qUtf8Printable(status) /* celldata */,
+                                    2 /* col # */ , "" /* celldata */,
+                                    3 /* col # */ , "" /* celldata */,
+                                    4 /* col # */ , "" /* celldata */,
+                                    5 /* col # */ , "" /* celldata */,
+                                    -1 /* end */);
+            }
+            g_free(conversationUid);
+        }
+
+        if (addItem) {
+            gtk_list_store_append (GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(self))), &iter);
+            gtk_list_store_set (GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(self))), &iter,
+                                0 /* col # */ , "" /* celldata */,
+                                1 /* col # */ , qUtf8Printable(status) /* celldata */,
+                                2 /* col # */ , "" /* celldata */,
+                                3 /* col # */ , "" /* celldata */,
+                                4 /* col # */ , "" /* celldata */,
+                                5 /* col # */ , "" /* celldata */,
+                                -1 /* end */);
+        }
+
+    });
     priv->conversationUpdatedConnection_ = QObject::connect(
     &*(*priv->accountInfo_)->conversationModel,
     &lrc::api::ConversationModel::conversationUpdated,
@@ -665,6 +796,8 @@ build_conversations_view(ConversationsView *self)
 
         // make sure conversation remains selected
         conversations_view_select_conversation(self, conversationUid);
+
+        g_free(conversationUid);
     });
 
     gtk_widget_show_all(GTK_WIDGET(self));
@@ -694,6 +827,8 @@ build_conversations_view(ConversationsView *self)
     g_signal_connect(self, "drag-drop", G_CALLBACK(on_drag_drop), nullptr);
     g_signal_connect(self, "drag-motion", G_CALLBACK(on_drag_motion), nullptr);
     g_signal_connect(self, "drag_data_received", G_CALLBACK(on_drag_data_received), nullptr);
+
+    priv->cpp = new details::CppImpl();
 }
 
 static void
@@ -705,11 +840,15 @@ conversations_view_dispose(GObject *object)
     QObject::disconnect(priv->selection_updated);
     QObject::disconnect(priv->layout_changed);
     QObject::disconnect(priv->modelSortedConnection_);
+    QObject::disconnect(priv->searchChangedConnection_);
+    QObject::disconnect(priv->searchStatusChangedConnection_);
     QObject::disconnect(priv->conversationUpdatedConnection_);
     QObject::disconnect(priv->filterChangedConnection_);
     QObject::disconnect(priv->callChangedConnection_);
 
     gtk_widget_destroy(priv->popupMenu_);
+    delete priv->cpp;
+    priv->cpp = nullptr;
 
     G_OBJECT_CLASS(conversations_view_parent_class)->dispose(object);
 }
@@ -780,7 +919,6 @@ conversations_view_select_conversation(ConversationsView *self, const std::strin
 int
 conversations_view_get_current_selected(ConversationsView *self)
 {
-
     g_return_val_if_fail(IS_CONVERSATIONS_VIEW(self), -1);
 
     /* we always drag the selected row */
diff --git a/src/native/pixbufmanipulator.cpp b/src/native/pixbufmanipulator.cpp
index 8421fd57c4f3a954e353aa28418b7cf8233fcd37..f1d9188db4555d2da59d0c9bceeaf6fa0333f4fb 100644
--- a/src/native/pixbufmanipulator.cpp
+++ b/src/native/pixbufmanipulator.cpp
@@ -220,7 +220,7 @@ PixbufManipulator::conversationPhoto(const lrc::api::conversation::Info& convers
             }
         } catch (...) {}
     }
-    return QVariant::fromValue(scaleAndFrame(generateAvatar("", "").get(), size, displayInformation));
+    return QVariant::fromValue(scaleAndFrame(temporaryItemAvatar().get(), size, displayInformation));
 
 }
 
diff --git a/src/profileview.cpp b/src/profileview.cpp
index 4b7c2b47d14d37990b38922b1ebd296b1abe27d8..31f299296d07a9964d1ceb360633919b039d314a 100644
--- a/src/profileview.cpp
+++ b/src/profileview.cpp
@@ -33,6 +33,10 @@
 #include <api/conversationmodel.h>
 #include <globalinstances.h>
 
+namespace { namespace details {
+class CppImpl;
+}}
+
 struct _ProfileView
 {
   GtkDialog parent;
@@ -43,7 +47,7 @@ typedef struct _ProfileViewPrivate ProfileViewPrivate;
 struct _ProfileViewPrivate
 {
     AccountInfoPointer const *accountInfo_ = nullptr;
-    int row_;
+    details::CppImpl* cpp {nullptr};
 
     GtkWidget* avatar;
 
@@ -57,6 +61,18 @@ struct _ProfileViewPrivate
 G_DEFINE_TYPE_WITH_PRIVATE(ProfileView, profile_view, GTK_TYPE_DIALOG)
 #define PROFILE_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PROFILE_VIEW_TYPE, _ProfileViewPrivate))
 
+namespace { namespace details {
+class CppImpl
+{
+public:
+    explicit CppImpl();
+    QString uid_;
+};
+CppImpl::CppImpl()
+    : uid_("")
+{}
+}}
+
 static void
 profile_view_init(ProfileView *prefs)
 {
@@ -66,6 +82,9 @@ profile_view_init(ProfileView *prefs)
 static void
 profile_view_dispose(GObject *object)
 {
+    auto* priv = PROFILE_VIEW_GET_PRIVATE(object);
+    delete priv->cpp;
+    priv->cpp = nullptr;
     G_OBJECT_CLASS(profile_view_parent_class)->dispose(object);
 }
 
@@ -93,7 +112,7 @@ build_view(ProfileView* view)
 
     try
     {
-        const auto& conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_);
+        const auto conversation = (*priv->accountInfo_)->conversationModel->getConversationForUID(priv->cpp->uid_);
         if (conversation.participants.empty()) return false;
         const auto& contact = (*priv->accountInfo_)->contactModel->getContact(conversation.participants.front());
 
@@ -143,19 +162,20 @@ build_view(ProfileView* view)
     }
     catch (...)
     {
-        g_warning("Can't get conversation at row %i", priv->row_);
+        g_warning("Can't get conversation %s", priv->cpp? priv->cpp->uid_.toStdString().c_str() : "");
         return false;
     }
     return true;
 }
 
 GtkWidget*
-profile_view_new(AccountInfoPointer const & accountInfo, int row)
+profile_view_new(AccountInfoPointer const & accountInfo, const QString& uid)
 {
     gpointer view = g_object_new(PROFILE_VIEW_TYPE, NULL);
     auto* priv = PROFILE_VIEW_GET_PRIVATE(view);
     priv->accountInfo_ = &accountInfo;
-    priv->row_ = row;
+    priv->cpp = new details::CppImpl();
+    priv->cpp->uid_ = uid;
     if (!build_view(PROFILE_VIEW(view))) return nullptr;
 
     auto provider = gtk_css_provider_new();
diff --git a/src/profileview.h b/src/profileview.h
index 0205f72277f2fcb47bc526393469f5782de66d4f..15fcf3afc84b1d024393374e8b7a0539f7c94495 100644
--- a/src/profileview.h
+++ b/src/profileview.h
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <gtk/gtk.h>
+#include <QString>
 
 #include "accountinfopointer.h"
 
@@ -29,4 +30,4 @@
 
 G_DECLARE_FINAL_TYPE (ProfileView, profile_view, PROFILE, VIEW, GtkDialog)
 
-GtkWidget*        profile_view_new(AccountInfoPointer const & accountInfo, int row_);
\ No newline at end of file
+GtkWidget*        profile_view_new(AccountInfoPointer const & accountInfo, const QString& uid);
\ No newline at end of file