RingMainWindow : add notification to pending contact request tab

- at the application startup and when the user chooses another account,
we show notification on pending contact requests.

[guillaume: ci msg meaning change]
[guillaume: code cleanup for QA]

Change-Id: I549dd5f83783738ad5cd5fed5bf0740eb17b6544
Reviewed-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
diff --git a/pixmaps/ic_verified_user_black_24px_with_notification.svg b/pixmaps/ic_verified_user_black_24px_with_notification.svg
new file mode 100644
index 0000000..051e0fd
--- /dev/null
+++ b/pixmaps/ic_verified_user_black_24px_with_notification.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   fill="#000000"
+   height="24"
+   viewBox="0 0 24 24"
+   width="24"
+   version="1.1"
+   id="svg6"
+   sodipodi:docname="ic_verified_user_black_24px_with_notification.svg"
+   inkscape:version="0.92.1 r">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1600"
+     inkscape:window-height="842"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="-19.322034"
+     inkscape:cy="12"
+     inkscape:window-x="0"
+     inkscape:window-y="29"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg6" />
+  <path
+     d="M0 0h24v24H0z"
+     fill="none"
+     id="path2" />
+  <path
+     d="M 12 1 L 10.375 1.7226562 A 6.2377381 6.2377381 0 0 1 11.564453 5.3730469 A 6.2377381 6.2377381 0 0 1 5.3261719 11.611328 A 6.2377381 6.2377381 0 0 1 3.0078125 11.158203 C 3.0802611 16.64804 6.8893005 21.752038 12 23 C 17.16 21.74 21 16.55 21 11 L 21 5 L 12 1 z M 16.589844 7.5800781 L 18 9 L 10 17 L 6 13 L 7.4101562 11.589844 L 10 14.169922 L 16.589844 7.5800781 z "
+     id="path4" />
+  <circle
+     r="4.9901905"
+     cy="5.3728104"
+     cx="5.3271904"
+     style="fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2.43000579;stroke-opacity:1"
+     id="path12471-2-3-6" />
+</svg>
diff --git a/pixmaps/pixmaps.gresource.xml b/pixmaps/pixmaps.gresource.xml
index 84dd852..b69508c 100644
--- a/pixmaps/pixmaps.gresource.xml
+++ b/pixmaps/pixmaps.gresource.xml
@@ -23,5 +23,6 @@
 	<file alias="history_list">ic_history_black_24px.svg</file>
 	<file alias="block">ic_block_black_24px.svg</file>
 	<file alias="add">ic_add_black_24px.svg</file>
+	<file alias="contact_requests_list_with_notification">ic_verified_user_black_24px_with_notification.svg</file>
   </gresource>
 </gresources>
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index 976901a..201f536 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -47,6 +47,7 @@
 #include <phonedirectorymodel.h>
 #include <availableaccountmodel.h>
 #include <contactrequest.h>
+#include <pendingcontactrequestmodel.h>
 
 // Ring client
 #include "models/gtkqtreemodel.h"
@@ -133,6 +134,7 @@
     GtkWidget *treeview_contact_requests;
     GtkWidget *scrolled_window_contact_requests;
     GtkWidget *contact_request_view;
+    GtkWidget *image_contact_requests_list;
 
     /* Pending ring usernames lookup for the search entry */
     QMetaObject::Connection username_lookup;
@@ -142,6 +144,10 @@
 
     QMetaObject::Connection selected_item_changed;
     QMetaObject::Connection selected_call_over;
+    QMetaObject::Connection account_request_added;
+    QMetaObject::Connection account_request_accepted;
+    QMetaObject::Connection account_request_discarded;
+    QMetaObject::Connection account_request_;
 
     gboolean   show_settings;
 
@@ -211,6 +217,22 @@
 }
 
 static void
+set_pending_contact_request_tab_icon(const Account* account, RingMainWindow* self)
+{
+    if (not account or not self) {
+        g_warning("null pointer ?\naccount (%p), self (%p)", account, self);
+        return;
+    }
+
+    auto priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
+
+    gtk_image_set_from_resource(GTK_IMAGE(priv->image_contact_requests_list),
+        (account->pendingContactRequestModel()->rowCount())
+        ? "/cx/ring/RingGnome/contact_requests_list_with_notification"
+        : "/cx/ring/RingGnome/contact_requests_list");
+};
+
+static void
 hide_view_clicked(RingMainWindow *self)
 {
     auto priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
@@ -507,6 +529,9 @@
             change_view(win, old_view, nullptr, RING_WELCOME_VIEW_TYPE);
     }
 
+    /* we force to check the pending contact request status */
+    set_pending_contact_request_tab_icon(get_active_ring_account(), win);
+
     return G_SOURCE_REMOVE;
 }
 
@@ -1240,6 +1265,30 @@
 }
 
 static void
+current_account_changed(RingMainWindow* self, Account* account)
+{
+    auto priv = RING_MAIN_WINDOW_GET_PRIVATE(self);
+
+    set_pending_contact_request_tab_icon(account, self);
+
+    /* disconnect previous PendingContactRequestModel */
+    QObject::disconnect(priv->account_request_added);
+    QObject::disconnect(priv->account_request_accepted);
+    QObject::disconnect(priv->account_request_discarded);
+
+    auto model = account->pendingContactRequestModel();
+    auto action = [self, account](ContactRequest* r) {
+        (void) r; // UNUSED
+        set_pending_contact_request_tab_icon(account, self);
+    };
+
+    /* connect current PendingContactRequestModel */
+    priv->account_request_added = QObject::connect(model, &PendingContactRequestModel::requestAdded, action);
+    priv->account_request_accepted = QObject::connect(model, &PendingContactRequestModel::requestAccepted, action);
+    priv->account_request_discarded = QObject::connect(model, &PendingContactRequestModel::requestDiscarded, action);
+}
+
+static void
 ring_main_window_init(RingMainWindow *win)
 {
     RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(win);
@@ -1326,8 +1375,14 @@
         if (gtk_widget_get_visible(priv->ring_settings))
             show_combobox_account_selector(win, TRUE);
     };
+
     QObject::connect(&AvailableAccountModel::instance(), &QAbstractItemModel::rowsRemoved, available_accounts_changed);
     QObject::connect(&AvailableAccountModel::instance(), &QAbstractItemModel::rowsInserted, available_accounts_changed);
+    QObject::connect(AvailableAccountModel::instance().selectionModel(), &QItemSelectionModel::currentChanged,
+    [win] (const QModelIndex& current, const QModelIndex& previous) {
+        auto account = current.data(static_cast<int>(Account::Role::Object)).value<Account*>();
+        current_account_changed(win, account);
+    });
 
     priv->treeview_contact_requests = pending_contact_requests_view_new();
     gtk_container_add(GTK_CONTAINER(priv->scrolled_window_contact_requests), priv->treeview_contact_requests);
@@ -1419,6 +1474,9 @@
 
     // we closing any view opened to avoid confusion (especially between SIP and Ring protocols).
     g_signal_connect_swapped(priv->combobox_account_selector, "changed", G_CALLBACK(hide_view_clicked), win);
+
+    // initialize the pending contact request icon.
+    current_account_changed(win, get_active_ring_account());
 }
 
 static void
@@ -1430,6 +1488,10 @@
     QObject::disconnect(priv->selected_item_changed);
     QObject::disconnect(priv->selected_call_over);
     QObject::disconnect(priv->username_lookup);
+    QObject::disconnect(priv->account_request_added);
+    QObject::disconnect(priv->account_request_accepted);
+    QObject::disconnect(priv->account_request_discarded);
+    QObject::disconnect(priv->account_request_);
 
     g_clear_object(&priv->welcome_view);
     g_clear_object(&priv->webkit_chat_container);
@@ -1477,6 +1539,7 @@
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, spinner_lookup);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, combobox_account_selector);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, scrolled_window_contact_requests);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, image_contact_requests_list);
 }
 
 GtkWidget *