gnome: incoming call view
Can now accept or reject incoming calls.
Refs #66962
Refs #67159
Change-Id: Ia68a37efdd71735623e7ef013092450102426d68
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b637138..1416929 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,6 +110,8 @@
src/ring_client_options.c
src/ringmainwindow.h
src/ringmainwindow.cpp
+ src/incomingcallview.h
+ src/incomingcallview.cpp
src/models/gtkaccessproxymodel.h
src/models/gtkaccessproxymodel.cpp
src/models/gtkqtreemodel.h
diff --git a/pixmaps/accept.svg b/pixmaps/accept.svg
new file mode 100644
index 0000000..7790f84
--- /dev/null
+++ b/pixmaps/accept.svg
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="24"
+ height="24"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.4 r9939"
+ version="1.0"
+ sodipodi:docname="accept.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <title
+ id="title2999">accept.svg</title>
+ <defs
+ id="defs4">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2433">
+ <stop
+ style="stop-color:#008000;stop-opacity:1;"
+ offset="0"
+ id="stop2435" />
+ <stop
+ style="stop-color:#008000;stop-opacity:0;"
+ offset="1"
+ id="stop2437" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 12 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="24 : 12 : 1"
+ inkscape:persp3d-origin="12 : 8 : 1"
+ id="perspective32" />
+ <linearGradient
+ id="linearGradient4269">
+ <stop
+ style="stop-color:#26b000;stop-opacity:1;"
+ offset="0"
+ id="stop4271" />
+ <stop
+ style="stop-color:#26b000;stop-opacity:0;"
+ offset="1"
+ id="stop4273" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4183">
+ <stop
+ id="stop4185"
+ offset="0"
+ style="stop-color:#26b000;stop-opacity:1;" />
+ <stop
+ id="stop4187"
+ offset="1"
+ style="stop-color:#145f00;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4167">
+ <stop
+ style="stop-color:#80000e;stop-opacity:1;"
+ offset="0"
+ id="stop4169" />
+ <stop
+ style="stop-color:#b00014;stop-opacity:0;"
+ offset="1"
+ id="stop4171" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2433"
+ id="linearGradient2439"
+ x1="2.965755"
+ y1="-0.80084854"
+ x2="32.578228"
+ y2="16.739393"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="-323.94939"
+ inkscape:cy="14.660114"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="32px"
+ height="32px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1313"
+ inkscape:window-height="744"
+ inkscape:window-x="337"
+ inkscape:window-y="1224"
+ showgrid="false"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <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>accept.svg</dc:title>
+ <dc:date>2014/06/24</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Gabrielle Maheux-Leclerc <gabrielle.maheux@savoirfairelinux.com></dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Savoir-faire Linux Inc.</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Savoir-faire Linux Inc.</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:source>http://sflphone.org/download/source-code</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>gnome</rdf:li>
+ <rdf:li>voip</rdf:li>
+ <rdf:li>sip</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:coverage>SFLphone project</dc:coverage>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="color:#bebebe;fill:none;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect44095-0-2"
+ width="27.25"
+ height="27.25"
+ x="-25.687498"
+ y="-27.12499"
+ inkscape:label="a"
+ transform="scale(-1,-1)" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path44097-5-4"
+ d="m 4.0259017,14.342141 c -2.0472755,0.490329 -3.3943792,1.870525 -3.72558592,4.151367 -0.0912875,0.958519 -0.47690906,2.290397 0.42578125,2.927246 1.20610207,0.720797 2.68102527,0.602259 3.99169917,0.372559 0.9560833,-0.25271 1.3652761,-0.344883 2.1289063,-1.064453 0,0 -0.088222,-1.823128 0.3193359,-2.820801 3.2887346,-1.380775 6.4890596,-1.278434 9.6865236,0 0.40749,0.997673 0.319336,2.820801 0.319336,2.820801 0.76363,0.71957 1.172823,0.811743 2.128906,1.064453 1.310674,0.2297 2.785597,0.348238 3.991699,-0.372559 0.902691,-0.636849 0.516984,-1.968727 0.425782,-2.927246 -0.331207,-2.280842 -1.678311,-3.661038 -3.725586,-4.151367 -5.3441,-1.006581 -10.6893238,-1.233489 -15.9667973,0 z"
+ style="fill:#545454;fill-opacity:1;stroke:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#bebebe;fill:#1aac36;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ d="m 6.9531478,8.3906045 1.703142,0 C 9.0938056,8.3905875 9.5563062,8.1694878 9.8804109,7.8583609 L 12.062523,5.6762491 14.244652,7.858378 c 0.323662,0.3115526 0.786605,0.5322265 1.224172,0.5321414 l 1.703125,0 1.7e-5,-1.703125 c 0,-0.5270321 -0.153792,-0.940653 -0.479089,-1.2773097 L 12.062489,0.88615891 7.4321347,5.4100847 C 7.106957,5.7468266 6.9531137,6.1604134 6.9531137,6.6874284 l 0,1.703125 z"
+ id="rect3217-6-2-2-4-2-3-8"
+ sodipodi:nodetypes="ccccccccccccc" />
+ </g>
+</svg>
diff --git a/pixmaps/hang_up.svg b/pixmaps/hang_up.svg
new file mode 100644
index 0000000..de1cb7e
--- /dev/null
+++ b/pixmaps/hang_up.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="24"
+ height="24"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.4 r9939"
+ version="1.0"
+ sodipodi:docname="hang_up.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <title
+ id="title3000">hang_up.svg</title>
+ <defs
+ id="defs4">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2433">
+ <stop
+ style="stop-color:#008000;stop-opacity:1;"
+ offset="0"
+ id="stop2435" />
+ <stop
+ style="stop-color:#008000;stop-opacity:0;"
+ offset="1"
+ id="stop2437" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 12 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="24 : 12 : 1"
+ inkscape:persp3d-origin="12 : 8 : 1"
+ id="perspective32" />
+ <linearGradient
+ id="linearGradient4269">
+ <stop
+ style="stop-color:#26b000;stop-opacity:1;"
+ offset="0"
+ id="stop4271" />
+ <stop
+ style="stop-color:#26b000;stop-opacity:0;"
+ offset="1"
+ id="stop4273" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4183">
+ <stop
+ id="stop4185"
+ offset="0"
+ style="stop-color:#26b000;stop-opacity:1;" />
+ <stop
+ id="stop4187"
+ offset="1"
+ style="stop-color:#145f00;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4167">
+ <stop
+ style="stop-color:#80000e;stop-opacity:1;"
+ offset="0"
+ id="stop4169" />
+ <stop
+ style="stop-color:#b00014;stop-opacity:0;"
+ offset="1"
+ id="stop4171" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2433"
+ id="linearGradient2439"
+ x1="2.965755"
+ y1="-0.80084854"
+ x2="32.578228"
+ y2="16.739393"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="22.627417"
+ inkscape:cx="-0.67971919"
+ inkscape:cy="10.25077"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="32px"
+ height="32px"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1313"
+ inkscape:window-height="744"
+ inkscape:window-x="337"
+ inkscape:window-y="1224"
+ showgrid="false"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <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>hang_up.svg</dc:title>
+ <dc:date>2014/06/24</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Gabrielle Maheux-Leclerc <gabrielle.maheux@savoirfairelinux.com></dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Savoir-faire Linux Inc.</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Savoir-faire Linux Inc.</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:source>http://sflphone.org/download/source-code</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>gnome</rdf:li>
+ <rdf:li>voip</rdf:li>
+ <rdf:li>sip</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:coverage>SFLphone project</dc:coverage>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="color:#bebebe;fill:none;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect44095-0-2"
+ width="27.25"
+ height="27.25"
+ x="-25.687498"
+ y="-27.12499"
+ inkscape:label="a"
+ transform="scale(-1,-1)" />
+ <rect
+ style="color:#bebebe;fill:none;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect44095-0"
+ width="27.357903"
+ height="27.357903"
+ x="-1.6802465"
+ y="-4.3527112"
+ inkscape:label="a" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path44097-5"
+ d="M 4.0371417,1.6680854 C 1.9817596,2.1603396 0.62932169,3.5460173 0.29680348,5.8358908 0.20515451,6.798188 -0.18199401,8.1353567 0.72427071,8.774728 1.9351486,9.4983787 3.4159121,9.3793548 4.7317759,9.1487618 5.691645,8.8950515 6.1024581,8.8025134 6.8691121,8.0800938 c 0,0 -0.088571,-1.8303634 0.3206004,-2.8319704 3.3017565,-1.386242 6.5147545,-1.283496 9.7248795,0 0.409103,1.001607 0.3206,2.8319704 0.3206,2.8319704 0.766654,0.7224196 1.177467,0.8149577 2.137336,1.068668 1.315864,0.230593 2.796628,0.3496169 4.007506,-0.3740338 0.906264,-0.6393713 0.51903,-1.97654 0.427467,-2.9388372 -0.332518,-2.2898735 -1.684956,-3.6755512 -3.740338,-4.1678054 -5.365261,-1.01058382 -10.7316505,-1.23837255 -16.0300213,0 z"
+ style="fill:#545454;fill-opacity:1;stroke:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#bebebe;fill:#de2c2c;fill-opacity:0.98431373;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ d="m 17.128291,14.455802 -1.709886,0 c -0.439248,1.7e-5 -0.90358,0.222009 -1.228968,0.534351 l -2.190752,2.190752 -2.19077,-2.190769 C 9.4829716,14.677349 9.018195,14.455802 8.5788955,14.455887 l -1.7098689,0 -1.71e-5,1.709869 c 0,0.529119 0.1544011,0.944378 0.4810032,1.282368 l 4.6487063,4.541839 4.648689,-4.541839 c 0.326465,-0.338076 0.480917,-0.7533 0.480917,-1.282402 l 0,-1.709869 z"
+ id="rect3217-6-2-2-4-2-3"
+ sodipodi:nodetypes="ccccccccccccc" />
+ </g>
+</svg>
diff --git a/pixmaps/pixmaps.gresource.xml b/pixmaps/pixmaps.gresource.xml
index 3926806..8bd974a 100644
--- a/pixmaps/pixmaps.gresource.xml
+++ b/pixmaps/pixmaps.gresource.xml
@@ -9,5 +9,7 @@
<file alias="dial">dial.svg</file>
<file alias="call">call.svg</file>
<file alias="contact">contact.svg</file>
+ <file alias="accept">accept.svg</file>
+ <file alias="reject">hang_up.svg</file>
</gresource>
</gresources>
\ No newline at end of file
diff --git a/src/incomingcallview.cpp b/src/incomingcallview.cpp
new file mode 100644
index 0000000..ac64b84
--- /dev/null
+++ b/src/incomingcallview.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015 Savoir-Faire Linux Inc.
+ * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this program, or any covered work, by linking or
+ * combining it with the OpenSSL project's OpenSSL library (or a
+ * modified version of that library), containing parts covered by the
+ * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ * grants you additional permission to convey the resulting work.
+ * Corresponding Source for a non-source form of such a combination
+ * shall include the source code for the parts of OpenSSL used as well
+ * as that of the covered work.
+ */
+
+#include "incomingcallview.h"
+
+#include <gtk/gtk.h>
+#include <math.h>
+#include <call.h>
+
+struct _IncomingCallView
+{
+ GtkBox parent;
+};
+
+struct _IncomingCallViewClass
+{
+ GtkBoxClass parent_class;
+};
+
+typedef struct _IncomingCallViewPrivate IncomingCallViewPrivate;
+
+struct _IncomingCallViewPrivate
+{
+ GtkWidget *image_incoming;
+ GtkWidget *label_identity;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(IncomingCallView, incoming_call_view, GTK_TYPE_BOX);
+
+#define INCOMING_CALL_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), INCOMING_CALL_VIEW_TYPE, IncomingCallViewPrivate))
+
+static void
+incoming_call_view_init(IncomingCallView *view)
+{
+ gtk_widget_init_template(GTK_WIDGET(view));
+}
+
+static void
+incoming_call_view_class_init(IncomingCallViewClass *klass)
+{
+ gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
+ "/cx/ring/RingGnome/incomingcallview.ui");
+
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, image_incoming);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, label_identity);
+}
+
+static GdkPixbuf *
+draw_fallback_avatar(int size) {
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size, size);
+ cr = cairo_create(surface);
+
+ cairo_pattern_t *linpat = cairo_pattern_create_linear(0, 0, 0, size);
+ cairo_pattern_add_color_stop_rgb(linpat, 0, 0.937, 0.937, 0.937);
+ cairo_pattern_add_color_stop_rgb(linpat, 1, 0.969, 0.969, 0.969);
+
+ cairo_set_source(cr, linpat);
+ cairo_paint(cr);
+
+ int avatar_size = size * 0.3;
+ GtkIconInfo *icon_info = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), "avatar-default-symbolic",
+ avatar_size, GTK_ICON_LOOKUP_GENERIC_FALLBACK);
+ GdkPixbuf *pixbuf_icon = gtk_icon_info_load_icon(icon_info, NULL);
+ g_object_unref(icon_info);
+
+ if (pixbuf_icon != NULL) {
+ gdk_cairo_set_source_pixbuf(cr, pixbuf_icon, (size - avatar_size) / 2, (size - avatar_size) / 2);
+ g_object_unref(pixbuf_icon);
+ cairo_rectangle(cr, (size - avatar_size) / 2, (size - avatar_size) / 2, avatar_size, avatar_size);
+ cairo_fill(cr);
+ }
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, size, size);
+
+ /* free resources */
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ return pixbuf;
+}
+
+static GdkPixbuf *
+frame_avatar(GdkPixbuf *avatar) {
+ int extra_space = 10;
+ int offset = extra_space/2;
+ int w = gdk_pixbuf_get_width(avatar);
+ int h = gdk_pixbuf_get_height(avatar);
+ int w_surface = w + extra_space;
+ int h_surface = h + extra_space;
+ cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w_surface, h_surface);
+ cairo_t *cr = cairo_create(surface);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 0);
+ cairo_rectangle(cr, 0, 0, w_surface, h_surface);
+ cairo_fill(cr);
+
+ gdk_cairo_set_source_pixbuf(cr, avatar, offset, offset);
+
+ double aspect = (double)w/(double)h;
+ double corner_radius = 5;
+ double radius = corner_radius/aspect;
+ double degrees = M_PI / 180.0;
+
+ cairo_new_sub_path (cr);
+ cairo_arc (cr, offset + w - radius, offset + radius, radius, -90 * degrees, 0 * degrees);
+ cairo_arc (cr, offset + w - radius, offset + h - radius, radius, 0 * degrees, 90 * degrees);
+ cairo_arc (cr, offset + radius, offset + h - radius, radius, 90 * degrees, 180 * degrees);
+ cairo_arc (cr, offset + radius, offset + radius, radius, 180 * degrees, 270 * degrees);
+ cairo_close_path (cr);
+
+ cairo_fill_preserve(cr);
+
+ cairo_set_source_rgba (cr, 58.0/256.0, 191/256.0, 210/256.0, 1.0);
+ cairo_set_line_width (cr, 2.0);
+ cairo_stroke (cr);
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, w_surface, h_surface);
+
+ /* free resources */
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ return pixbuf;
+}
+
+GtkWidget *
+incoming_call_view_new(void)
+{
+ return (GtkWidget *)g_object_new(INCOMING_CALL_VIEW_TYPE, NULL);
+}
+
+void
+incoming_call_view_set_call_info(IncomingCallView *view, const QModelIndex& idx) {
+ IncomingCallViewPrivate *priv = INCOMING_CALL_VIEW_GET_PRIVATE(view);
+
+ QVariant var = idx.model()->data(idx, Call::Role::Name);
+ QByteArray ba_name = var.toString().toLocal8Bit();
+
+ /* get image and frame it */
+ GdkPixbuf *avatar = draw_fallback_avatar(100);
+ GdkPixbuf *framed_avatar = frame_avatar(avatar);
+ g_object_unref(avatar);
+
+ gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_incoming), framed_avatar);
+ g_object_unref(framed_avatar);
+
+ gtk_label_set_text(GTK_LABEL(priv->label_identity), ba_name.data());
+}
diff --git a/src/incomingcallview.h b/src/incomingcallview.h
new file mode 100644
index 0000000..1a25c72
--- /dev/null
+++ b/src/incomingcallview.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Savoir-Faire Linux Inc.
+ * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this program, or any covered work, by linking or
+ * combining it with the OpenSSL project's OpenSSL library (or a
+ * modified version of that library), containing parts covered by the
+ * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ * grants you additional permission to convey the resulting work.
+ * Corresponding Source for a non-source form of such a combination
+ * shall include the source code for the parts of OpenSSL used as well
+ * as that of the covered work.
+ */
+
+#ifndef _INCOMINGCALLVIEW_H
+#define _INCOMINGCALLVIEW_H
+
+#include <gtk/gtk.h>
+#include <call.h>
+
+G_BEGIN_DECLS
+
+#define INCOMING_CALL_VIEW_TYPE (incoming_call_view_get_type ())
+#define INCOMING_CALL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INCOMING_CALL_VIEW_TYPE, IncomingCallView))
+#define INCOMING_CALL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INCOMING_CALL_VIEW_TYPE, IncomingCallViewClass))
+#define IS_INCOMING_CALL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INCOMING_CALL_VIEW_TYPE))
+#define IS_INCOMING_CALL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INCOMING_CALL_VIEW_TYPE))
+
+typedef struct _IncomingCallView IncomingCallView;
+typedef struct _IncomingCallViewClass IncomingCallViewClass;
+
+
+GType incoming_call_view_get_type (void) G_GNUC_CONST;
+GtkWidget *incoming_call_view_new (void);
+void incoming_call_view_set_call_info (IncomingCallView *view, const QModelIndex& idx);
+
+G_END_DECLS
+
+#endif /* _INCOMINGCALLVIEW_H */
\ No newline at end of file
diff --git a/src/models/gtkqtreemodel.cpp b/src/models/gtkqtreemodel.cpp
index 3324a2b..e84f55d 100644
--- a/src/models/gtkqtreemodel.cpp
+++ b/src/models/gtkqtreemodel.cpp
@@ -197,10 +197,9 @@
QModelIndex proxy_idx = proxy_model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
if (proxy_idx.isValid()) {
/* we have the proxy model idx, now get the actual idx so we can get the call object */
- g_debug("got valid model index");
return proxy_model->mapToSource(proxy_idx);
} else {
- g_debug("returning invlaid model index");
+ g_warning("could not get valid QModelIndex from given GtkTreeIter");
return QModelIndex();
}
}
@@ -214,15 +213,14 @@
{
GtkQTreeModelPrivate *priv = GTK_Q_TREEMODEL_GET_PRIVATE(q_tree_model);
- /* make sure its an iter from the right model */
- g_return_val_if_fail(idx.model() == priv->model->sourceModel(), FALSE);
+ /* the the proxy_idx from the source idx */
+ QModelIndex proxy_idx = priv->model->mapFromSource(idx);
+ if (!proxy_idx.isValid())
+ return FALSE;
/* make sure iter is valid */
iter->stamp = priv->stamp;
- /* the the proxy_idx from the source idx */
- QModelIndex proxy_idx = priv->model->mapFromSource(idx);
-
/* map the proxy idx to iter */
Q_ITER(iter)->row.value = proxy_idx.row();
Q_ITER(iter)->column.value = proxy_idx.row();
@@ -303,8 +301,8 @@
QObject::connect(
model,
&QAbstractItemModel::rowsAboutToBeMoved,
- [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, G_GNUC_UNUSED const QModelIndex & destinationParent, int destinationRow) {
- g_debug("rows about to be moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
+ [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd,
+ G_GNUC_UNUSED const QModelIndex & destinationParent, G_GNUC_UNUSED int destinationRow) {
/* first remove the row from old location
* then insert them at the new location on the "rowsMoved signal */
for( int row = sourceStart; row <= sourceEnd; row++) {
@@ -320,8 +318,8 @@
QObject::connect(
model,
&QAbstractItemModel::rowsMoved,
- [=](G_GNUC_UNUSED const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
- g_debug("rows moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
+ [=](G_GNUC_UNUSED const QModelIndex & sourceParent, int sourceStart, int sourceEnd,
+ const QModelIndex & destinationParent, int destinationRow) {
/* these rows should have been removed in the "rowsAboutToBeMoved" handler
* now insert them in the new location */
for( int row = sourceStart; row <= sourceEnd; row++) {
@@ -354,7 +352,8 @@
QObject::connect(
model,
&QAbstractItemModel::dataChanged,
- [=](const QModelIndex & topLeft, const QModelIndex & bottomRight, G_GNUC_UNUSED const QVector<int> & roles = QVector<int> ()) {
+ [=](const QModelIndex & topLeft, const QModelIndex & bottomRight,
+ G_GNUC_UNUSED const QVector<int> & roles = QVector<int> ()) {
/* we have to assume only one column */
int first = topLeft.row();
int last = bottomRight.row();
@@ -662,8 +661,11 @@
// g_value_set_double (value, (gdouble) list->data.v_double);
// break;
case G_TYPE_STRING:
- g_value_set_string(value, (gchar *)var.toString().toLocal8Bit().data());
- break;
+ {
+ QByteArray ba = var.toString().toLocal8Bit();
+ g_value_set_string(value, (gchar *)ba.data());
+ }
+ break;
// case G_TYPE_POINTER:
// g_value_set_pointer (value, (gpointer) list->data.v_pointer);
// break;
@@ -863,4 +865,4 @@
return validate_index(priv->stamp, idx, iter);
}
-/* End Fulfill the GtkTreeModel requirements */
\ No newline at end of file
+/* End Fulfill the GtkTreeModel requirements */
diff --git a/src/ring_client.cpp b/src/ring_client.cpp
index d234b5b..92021ae 100644
--- a/src/ring_client.cpp
+++ b/src/ring_client.cpp
@@ -36,6 +36,7 @@
#include <QString>
#include <QByteArray>
#include <callmodel.h>
+#include <QItemSelectionModel>
#include "ring_client_options.h"
#include "ringmainwindow.h"
@@ -132,6 +133,57 @@
}
static void
+call_accept(G_GNUC_UNUSED GSimpleAction *action, G_GNUC_UNUSED GVariant *param, G_GNUC_UNUSED gpointer client)
+{
+ g_debug("call accpet action");
+
+ /* TODO: implement using UserActionModel once its fixed
+ * UserActionModel action_model = UserActionModel(CallModel::instance());
+ * if (action_model.isActionEnabled())
+ */
+
+ QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
+ if (idx.isValid()) {
+ Call *call = CallModel::instance()->getCall(idx);
+ call->performAction(Call::Action::ACCEPT);
+ }
+}
+
+static void
+call_hangup(G_GNUC_UNUSED GSimpleAction *action, G_GNUC_UNUSED GVariant *param, G_GNUC_UNUSED gpointer client)
+{
+ g_debug("call hangup action");
+
+ /* TODO: implement using UserActionModel once its fixed
+ * UserActionModel action_model = UserActionModel(CallModel::instance());
+ * if (action_model.isActionEnabled())
+ */
+
+ QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
+ if (idx.isValid()) {
+ Call *call = CallModel::instance()->getCall(idx);
+ call->performAction(Call::Action::REFUSE);
+ }
+}
+
+static const GActionEntry ring_actions[] =
+{
+ { "accept", call_accept, NULL, NULL, NULL, {0} },
+ { "reject", call_hangup, NULL, NULL, NULL, {0} }
+};
+
+static void
+ring_client_startup(GApplication *app)
+{
+ G_APPLICATION_CLASS(ring_client_parent_class)->startup(app);
+
+ RingClient *client = RING_CLIENT(app);
+
+ g_action_map_add_action_entries(
+ G_ACTION_MAP(app), ring_actions, G_N_ELEMENTS(ring_actions), client);
+}
+
+static void
ring_client_shutdown(GApplication *app)
{
RingClient *self = RING_CLIENT(app);
@@ -158,6 +210,7 @@
static void
ring_client_class_init(RingClientClass *klass)
{
+ G_APPLICATION_CLASS(klass)->startup = ring_client_startup;
G_APPLICATION_CLASS(klass)->command_line = ring_client_command_line;
G_APPLICATION_CLASS(klass)->shutdown = ring_client_shutdown;
}
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index f1f25e5..d4456ee 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -33,6 +33,11 @@
#include <gtk/gtk.h>
#include "models/gtkqtreemodel.h"
#include <callmodel.h>
+#include <call.h>
+#include <QItemSelectionModel>
+#include "incomingcallview.h"
+
+#define DEFAULT_VIEW_NAME "placeholder"
struct _RingMainWindow
{
@@ -52,12 +57,102 @@
GtkWidget *gears_image;
GtkWidget *treeview_call;
GtkWidget *search_entry;
+ GtkWidget *stack_main_view;
};
G_DEFINE_TYPE_WITH_PRIVATE(RingMainWindow, ring_main_window, GTK_TYPE_APPLICATION_WINDOW);
#define RING_MAIN_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), RING_MAIN_WINDOW_TYPE, RingMainWindowPrivate))
+static QModelIndex
+get_index_from_selection(GtkTreeSelection *selection)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = NULL;
+
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ return gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
+ } else {
+ return QModelIndex();
+ }
+}
+
+static void
+update_call_model_selection(GtkTreeSelection *selection, gpointer win)
+{
+ RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
+ GtkQTreeModel *call_model = GTK_Q_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_call)));
+ CallModel *call_qmodel = (CallModel *)gtk_q_tree_model_get_qmodel(call_model);
+ QModelIndex current = get_index_from_selection(selection);
+ if (current.isValid())
+ call_qmodel->selectionModel()->setCurrentIndex(current, QItemSelectionModel::ClearAndSelect);
+ else
+ call_qmodel->selectionModel()->clearCurrentIndex();
+}
+
+static void
+call_selection_changed(GtkTreeSelection *selection, gpointer win)
+{
+ RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
+
+ /* get the current visible stack child */
+ GtkWidget *child_old = gtk_stack_get_visible_child(GTK_STACK(priv->stack_main_view));
+
+ QModelIndex idx = get_index_from_selection(selection);
+ if (idx.isValid()) {
+ QVariant state = idx.model()->data(idx, Call::Role::CallState);
+
+ switch(state.value<Call::State>()) {
+ case Call::State::INCOMING:
+ {
+ QVariant name = idx.model()->data(idx, Call::Role::Name);
+ QByteArray ba_name = name.toString().toLocal8Bit();
+ GtkWidget *new_call_view = incoming_call_view_new();
+ incoming_call_view_set_call_info(INCOMING_CALL_VIEW(new_call_view), idx);
+ gtk_stack_add_named(GTK_STACK(priv->stack_main_view), new_call_view, ba_name.data());
+ gtk_stack_set_visible_child(GTK_STACK(priv->stack_main_view), new_call_view);
+ }
+ break;
+
+ /* TODO: implement view(s) for other call states */
+ case Call::State::RINGING:
+ case Call::State::CURRENT:
+ case Call::State::DIALING:
+ case Call::State::HOLD:
+ case Call::State::FAILURE:
+ case Call::State::BUSY:
+ case Call::State::TRANSFERRED:
+ case Call::State::TRANSF_HOLD:
+ case Call::State::OVER:
+ case Call::State::ERROR:
+ case Call::State::CONFERENCE:
+ case Call::State::CONFERENCE_HOLD:
+ case Call::State::INITIALIZATION:
+ case Call::State::COUNT__:
+ break;
+ }
+ } else {
+ /* nothing selected in the call model, so show the default screen */
+
+ /* TODO: replace stack paceholder view */
+ gtk_stack_set_transition_type(GTK_STACK(priv->stack_main_view), GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT);
+ gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_main_view), DEFAULT_VIEW_NAME);
+ gtk_stack_set_transition_type(GTK_STACK(priv->stack_main_view), GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT);
+
+ }
+
+ /* check if we changed the visible child */
+ GtkWidget *child_current = gtk_stack_get_visible_child(GTK_STACK(priv->stack_main_view));
+ if (child_current != child_old && child_old != NULL) {
+ /* if the previous child was an "incoming call", then remove it from
+ * the stack; removing it should destory it since there should not
+ * be any other references to it */
+ if (IS_INCOMING_CALL_VIEW(child_old)) {
+ gtk_container_remove(GTK_CONTAINER(priv->stack_main_view), child_old);
+ }
+ }
+}
+
static void
ring_main_window_init(RingMainWindow *win)
{
@@ -89,32 +184,67 @@
g_object_unref(builder);
/* call model */
- GtkQTreeModel *model;
+ GtkQTreeModel *call_model;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
- model = gtk_q_tree_model_new(CallModel::instance(), 4,
+ call_model = gtk_q_tree_model_new(CallModel::instance(), 4,
Call::Role::Name, G_TYPE_STRING,
Call::Role::Number, G_TYPE_STRING,
Call::Role::Length, G_TYPE_STRING,
Call::Role::CallState, G_TYPE_STRING);
- gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_call), GTK_TREE_MODEL(model) );
+ gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_call), GTK_TREE_MODEL(call_model));
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", 0, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW (priv->treeview_call), column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes("Number", renderer, "text", 1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_call), column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Duration", renderer, "text", 2, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_call), column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes("State", renderer, "text", 3, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_call), column);
+ /* connect signals to and from UserActionModel to sync selection betwee
+ * the QModel and the GtkTreeView */
+ CallModel *call_qmodel = (CallModel *)gtk_q_tree_model_get_qmodel(call_model);
+
+ QObject::connect(
+ call_qmodel->selectionModel(),
+ &QItemSelectionModel::currentChanged,
+ [=](const QModelIndex & current, const QModelIndex & previous) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_call));
+
+ /* first unselect the previous */
+ if (previous.isValid()) {
+ GtkTreeIter old_iter;
+ if (gtk_q_tree_model_source_index_to_iter(call_model, previous, &old_iter)) {
+ gtk_tree_selection_unselect_iter(selection, &old_iter);
+ } else {
+ g_warning("Trying to unselect invalid GtkTreeIter");
+ }
+ }
+
+ /* select the current */
+ if (current.isValid()) {
+ GtkTreeIter new_iter;
+ if (gtk_q_tree_model_source_index_to_iter(call_model, current, &new_iter)) {
+ gtk_tree_selection_select_iter(selection, &new_iter);
+ } else {
+ g_warning("SelectionModel of CallModel changed to invalid QModelIndex?");
+ }
+ }
+ }
+ );
+
+ GtkTreeSelection *call_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_call));
+ g_signal_connect(call_selection, "changed", G_CALLBACK(update_call_model_selection), win);
+
+ /* TODO: replace stack paceholder view */
+ GtkWidget *placeholder_view = gtk_tree_view_new();
+ gtk_widget_show(placeholder_view);
+ gtk_stack_add_named(GTK_STACK(priv->stack_main_view), placeholder_view, DEFAULT_VIEW_NAME);
+
+ /* connect signals */
+ g_signal_connect(call_selection, "changed", G_CALLBACK(call_selection_changed), win);
}
static void
@@ -127,6 +257,7 @@
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, gears);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, gears_image);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, search_entry);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, stack_main_view);
}
GtkWidget *
diff --git a/ui/incomingcallview.ui b/ui/incomingcallview.ui
new file mode 100644
index 0000000..2540bfd
--- /dev/null
+++ b/ui/incomingcallview.ui
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="IncomingCallView" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <!-- info scroll -->
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_incoming_info">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">none</property>
+ <property name="min-content-height">250</property>
+ <property name="hscrollbar_policy">never</property>
+ <!-- info viewport -->
+ <child>
+ <object class="GtkViewport" id="viewport_incoming_info">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <!-- info vbox -->
+ <child>
+ <object class="GtkBox" id="vbox_incoming_info">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="border_width">15</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">15</property>
+ <!-- image of contact -->
+ <child>
+ <object class="GtkImage" id="image_incoming">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="xpad">10</property>
+ <property name="ypad">10</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <!-- end image of contact -->
+ <!-- name or other identity of contact -->
+ <child>
+ <object class="GtkLabel" id="label_identity">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <attributes>
+ <attribute name="scale" value="1.5"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <!-- end name or other identity of contact -->
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <!-- end info vbox -->
+ </object>
+ </child>
+ <!-- end info viewport -->
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <!-- end info scroll -->
+ <!-- hbox action bar -->
+ <child>
+ <object class="GtkBox" id="hbox_action_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">20</property>
+ <property name="border_width">20</property>
+ <!-- <property name="margin_bottom">100</property> -->
+ <!-- accept button -->
+ <child>
+ <object class="GtkButton" id="button_accept_incoming">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes"> Accept</property>
+ <property name="image">image_accept</property>
+ <property name="action-name">app.accept</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <!-- end accept button -->
+ <!-- reject button -->
+ <child>
+ <object class="GtkButton" id="button_reject_incoming">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes"> Reject</property>
+ <property name="image">image_reject</property>
+ <property name="action-name">app.reject</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ <!-- end reject button -->
+ </object>
+ </child>
+ <!-- end hbox action bar -->
+ </template>
+ <object class="GtkImage" id="image_accept">
+ <property name="visible">True</property>
+ <property name="resource">/cx/ring/RingGnome/accept</property>
+ </object>
+ <object class="GtkImage" id="image_reject">
+ <property name="visible">True</property>
+ <property name="resource">/cx/ring/RingGnome/reject</property>
+ </object>
+</interface>
diff --git a/ui/ringmainwindow.ui b/ui/ringmainwindow.ui
index 5187a4d..070921f 100644
--- a/ui/ringmainwindow.ui
+++ b/ui/ringmainwindow.ui
@@ -19,7 +19,7 @@
<property name="visible">True</property>
<property name="direction">none</property>
<!-- <property name="use-popover">True</property> -->
- <property name="tooltip_text" translatable="yes">Menu`</property>
+ <property name="tooltip_text" translatable="yes">Menu</property>
<style>
<class name="image-button"/>
</style>
@@ -48,7 +48,7 @@
<object class="GtkSearchEntry" id="search_entry">
<property name="visible">True</property>
<property name="height-request">43</property>
- <property name="width-request">350</property>
+ <property name="width-request">400</property>
</object>
<packing>
<property name="expand">True</property>
@@ -96,7 +96,7 @@
<object class="GtkScrolledWindow" id="scrolledwindow_calls">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
+ <!-- <property name="hscrollbar_policy">never</property> -->
<!-- <property name="shadow_type">in</property> -->
<child>
<object class="GtkTreeView" id="treeview_call">
@@ -192,12 +192,10 @@
<property name="orientation">vertical</property>
<!-- main display object -->
<child>
- <object class="GtkTreeView" id="placeholder">
+ <object class="GtkStack" id="stack_main_view">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection2"/>
- </child>
+ <property name="transition-type">GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT</property>
+ <property name="transition-duration">300</property>
</object>
<packing>
<property name="expand">True</property>
diff --git a/ui/ui.gresource.xml b/ui/ui.gresource.xml
index b9f178c..db0fb89 100644
--- a/ui/ui.gresource.xml
+++ b/ui/ui.gresource.xml
@@ -3,5 +3,6 @@
<gresource prefix="/cx/ring/RingGnome">
<file preprocess="xml-stripblanks">ringmainwindow.ui</file>
<file preprocess="xml-stripblanks">ringgearsmenu.ui</file>
+ <file preprocess="xml-stripblanks">incomingcallview.ui</file>
</gresource>
</gresources>
\ No newline at end of file