main window: fix dataChanged inception

Because setData can be called inside of a Qt signal handler, a
dataChanged signal handler can then also be called as a result
(since connections made using lambdas are called directly, rather
than being scheduled on the main loop).

In this case it caused item_changed() to be called inside of
selection_changed() in certain cases resulting in 2 CurrentCallViews
to be constructed and one of them was never destroyed.

The fix is to place the handler on the main loop queue via a g_idle
call so that its not called inside of another handler.

Tuleap: #252
Change-Id: I4a091037075af3823fc74cfd80fd3ac5bd7b0926
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index c7ef228..acb05ab 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -261,21 +261,18 @@
     }
 }
 
-static void
-item_changed(const QModelIndex& recent_idx, RingMainWindow *win)
+static gboolean
+selected_item_changed(RingMainWindow *win)
 {
     // g_debug("item changed");
     RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
 
     /* if we're showing the settings, then nothing needs to be done as the call
        view is not shown */
-    if (priv->show_settings) return;
+    if (priv->show_settings) return G_SOURCE_REMOVE;
 
-    /* check if the item that changed is the same as the one selected / displayed */
     auto idx_selected = RecentModel::instance().selectionModel()->currentIndex();
 
-    if (idx_selected != recent_idx) return;
-
     /* we prioritize showing the call view; but if the call is over we go back to showing the chat view */
     if(auto call = RecentModel::instance().getActiveCall(idx_selected)) {
         /* check if we need to change the view */
@@ -341,6 +338,8 @@
             }
         }
     }
+
+    return G_SOURCE_REMOVE;
 }
 
 static void
@@ -951,7 +950,13 @@
         &RecentModel::instance(),
         &RecentModel::dataChanged,
         [win](const QModelIndex & topLeft, G_GNUC_UNUSED const QModelIndex & bottomRight, G_GNUC_UNUSED const QVector<int> & roles) {
-            item_changed(topLeft, win);
+            /* it is possible for dataChanged to be emitted inside of a dataChanged handler or
+             * some other signal; since the connection is via a lambda, Qt would cause the
+             * handler to be called directly. This is not behaviour we usually want, so we call our
+             * function via g_idle so that it gets called after the initial handler is done.
+             */
+            if (topLeft == RecentModel::instance().selectionModel()->currentIndex())
+                g_idle_add((GSourceFunc)selected_item_changed, win);
         }
     );