[ekiga] CallHistoryBookViewGtk: Fixed infinite loop when call is cleared.



commit 7efde8e5c1e5e3405ec04e862f732d6747fbd352
Author: Damien Sandras <dsandras seconix com>
Date:   Sat Dec 27 12:08:30 2014 +0100

    CallHistoryBookViewGtk: Fixed infinite loop when call is cleared.
    
    The code was optimized to react differently when a call is added to the
    history and when the entirer history is reset. Formerly, the entire call
    history was cleared then rebuilt when a new call was added. This was not
    efficient.

 .../gui/gtk-frontend/call-history-view-gtk.cpp     |   99 +++++++++++++-------
 1 files changed, 66 insertions(+), 33 deletions(-)
---
diff --git a/lib/engine/gui/gtk-frontend/call-history-view-gtk.cpp 
b/lib/engine/gui/gtk-frontend/call-history-view-gtk.cpp
index ecea07e..0431ba7 100644
--- a/lib/engine/gui/gtk-frontend/call-history-view-gtk.cpp
+++ b/lib/engine/gui/gtk-frontend/call-history-view-gtk.cpp
@@ -45,6 +45,7 @@
 #include "menu-builder-gtk.h"
 #include "gm-cell-renderer-bitext.h"
 #include "gactor-menu.h"
+#include "scoped-connections.h"
 
 
 struct null_deleter
@@ -67,9 +68,10 @@ struct _CallHistoryViewGtkPrivate
   Ekiga::GActorMenuPtr contact_menu;
 
   GtkTreeView* tree;
-  boost::signals2::scoped_connection connection;
+  Ekiga::scoped_connections conns;
 };
 
+
 /* this is what we put in the view */
 enum {
   COLUMN_CONTACT,
@@ -150,6 +152,34 @@ on_contact_added (Ekiga::ContactPtr contact,
                      -1);
 }
 
+
+static void
+on_selection_changed (G_GNUC_UNUSED GtkTreeSelection* selection,
+                     gpointer data)
+{
+  CallHistoryViewGtk* self = NULL;
+  History::Contact *contact = NULL;
+
+  self = CALL_HISTORY_VIEW_GTK (data);
+
+  /* Reset old data. This also ensures GIO actions are
+   * properly removed before adding new ones.
+   */
+  self->priv->contact_menu.reset ();
+
+  /* Set or reset ContactActor data */
+  call_history_view_gtk_get_selected (self, &contact);
+
+  if (contact != NULL) {
+    self->priv->contact_menu = Ekiga::GActorMenuPtr (new Ekiga::GActorMenu (*contact));
+    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0,
+                   self->priv->contact_menu->get_model (boost::assign::list_of (self->priv->menu)));
+  }
+  else
+    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0, NULL);
+}
+
+
 static bool
 on_visit_contacts (Ekiga::ContactPtr contact,
                   GtkListStore *store)
@@ -158,15 +188,42 @@ on_visit_contacts (Ekiga::ContactPtr contact,
   return true;
 }
 
+
 static void
-on_book_updated (CallHistoryViewGtk* self)
+on_book_contact_added (Ekiga::ContactPtr contact,
+                       CallHistoryViewGtk* self)
 {
-  GtkTreeModel* store = gtk_tree_view_get_model (self->priv->tree);
+  GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (self->priv->tree));
 
-  gtk_list_store_clear (GTK_LIST_STORE (store));
-  self->priv->book->visit_contacts (boost::bind (&on_visit_contacts, _1, GTK_LIST_STORE (store)));
+  on_contact_added (contact, store);
 }
 
+
+static void
+on_book_cleared (CallHistoryViewGtk* data)
+{
+  GtkListStore *store = NULL;
+  GtkTreeSelection *selection = NULL;
+
+  g_return_if_fail (IS_CALL_HISTORY_VIEW_GTK (data));
+  CallHistoryViewGtk *self = CALL_HISTORY_VIEW_GTK (data);
+
+  store = GTK_LIST_STORE (gtk_tree_view_get_model (self->priv->tree));
+  selection = gtk_tree_view_get_selection (self->priv->tree);
+
+  /* Reset old data. This also ensures GIO actions are
+   * properly removed before adding new ones.
+   */
+  self->priv->contact_menu.reset ();
+
+  if (selection)
+    g_signal_handlers_block_by_func (selection, (gpointer) on_selection_changed, self);
+  gtk_list_store_clear (store);
+  if (selection)
+    g_signal_handlers_unblock_by_func (selection, (gpointer) on_selection_changed, self);
+}
+
+
 /* react to user clicks */
 static gint
 on_clicked (G_GNUC_UNUSED GtkWidget *tree,
@@ -187,31 +244,6 @@ on_clicked (G_GNUC_UNUSED GtkWidget *tree,
   return TRUE;
 }
 
-static void
-on_selection_changed (G_GNUC_UNUSED GtkTreeSelection* selection,
-                     gpointer data)
-{
-  CallHistoryViewGtk* self = NULL;
-  History::Contact *contact = NULL;
-
-  self = CALL_HISTORY_VIEW_GTK (data);
-
-  /* Reset old data. This also ensures GIO actions are
-   * properly removed before adding new ones.
-   */
-  self->priv->contact_menu.reset ();
-
-  /* Set or reset ContactActor data */
-  call_history_view_gtk_get_selected (self, &contact);
-
-  if (contact != NULL) {
-    self->priv->contact_menu = Ekiga::GActorMenuPtr (new Ekiga::GActorMenu (*contact));
-    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0,
-                   self->priv->contact_menu->get_model (boost::assign::list_of (self->priv->menu)));
-  }
-  else
-    g_signal_emit (self, signals[ACTIONS_CHANGED_SIGNAL], 0, NULL);
-}
 
 static void
 on_map_cb (G_GNUC_UNUSED GtkWidget *widget,
@@ -336,11 +368,12 @@ call_history_view_gtk_new (boost::shared_ptr<History::Book> book,
   g_signal_connect (GTK_WIDGET (self), "map",
                     G_CALLBACK (on_map_cb), self);
 
-  /* connect to the signal */
-  self->priv->connection = book->updated.connect (boost::bind (&on_book_updated, self));
+  /* connect to the signals */
+  self->priv->conns.add (book->contact_added.connect (boost::bind (&on_book_contact_added, _1, self)));
+  self->priv->conns.add (book->cleared.connect (boost::bind (&on_book_cleared, self)));
 
   /* initial populate */
-  on_book_updated(self);
+  self->priv->book->visit_contacts (boost::bind (&on_visit_contacts, _1, GTK_LIST_STORE (store)));
 
   /* register book actions */
   self->priv->menu = Ekiga::GActorMenuPtr (new Ekiga::GActorMenu (*book));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]