Commit 297b5d19 authored by Stepan Salenikovich's avatar Stepan Salenikovich

gnome: outgoing calls

Can now place outgoing calls. Can end outgoing
and in progress calls.

Refs #66962

Change-Id: Ic132533d120e9582e58954c947af4cafd793b6fa
parent 6977184b
......@@ -116,6 +116,8 @@ SET( SRC_FILES
src/models/gtkaccessproxymodel.cpp
src/models/gtkqtreemodel.h
src/models/gtkqtreemodel.cpp
src/utils/drawing.h
src/utils/drawing.c
)
# compile glib resource files to c code
......
......@@ -31,8 +31,9 @@
#include "incomingcallview.h"
#include <gtk/gtk.h>
#include <math.h>
#include <call.h>
#include "utils/drawing.h"
#include <callmodel.h>
struct _IncomingCallView
{
......@@ -50,12 +51,32 @@ struct _IncomingCallViewPrivate
{
GtkWidget *image_incoming;
GtkWidget *label_identity;
GtkWidget *label_status;
GtkWidget *button_accept_incoming;
GtkWidget *button_reject_incoming;
GtkWidget *button_end_call;
QMetaObject::Connection state_change_connection;
};
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_dispose(GObject *object)
{
IncomingCallView *view;
IncomingCallViewPrivate *priv;
view = INCOMING_CALL_VIEW(object);
priv = INCOMING_CALL_VIEW_GET_PRIVATE(view);
QObject::disconnect(priv->state_change_connection);
G_OBJECT_CLASS(incoming_call_view_parent_class)->dispose(object);
}
static void
incoming_call_view_init(IncomingCallView *view)
{
......@@ -65,92 +86,17 @@ incoming_call_view_init(IncomingCallView *view)
static void
incoming_call_view_class_init(IncomingCallViewClass *klass)
{
G_OBJECT_CLASS(klass)->dispose = incoming_call_dispose;
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;
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, label_status);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, button_accept_incoming);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, button_reject_incoming);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), IncomingCallView, button_end_call);
}
GtkWidget *
......@@ -159,6 +105,98 @@ incoming_call_view_new(void)
return (GtkWidget *)g_object_new(INCOMING_CALL_VIEW_TYPE, NULL);
}
static void
update_state(IncomingCallView *view, Call *call)
{
IncomingCallViewPrivate *priv = INCOMING_CALL_VIEW_GET_PRIVATE(view);
/* change state label */
Call::State state = call->state();
switch(state) {
case Call::State::INCOMING:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Incoming...");
break;
case Call::State::RINGING:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Ringing...");
break;
case Call::State::CURRENT:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "In progress.");
break;
case Call::State::DIALING:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Dialing...");
break;
case Call::State::HOLD:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "On hold.");
break;
case Call::State::FAILURE:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Failed.");
break;
case Call::State::BUSY:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Busy.");
break;
case Call::State::TRANSFERRED:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "Transfered.");
break;
case Call::State::TRANSF_HOLD:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "Transfer hold.");
break;
case Call::State::OVER:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "Over.");
break;
case Call::State::ERROR:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Error.");
break;
case Call::State::CONFERENCE:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "Conference.");
break;
case Call::State::CONFERENCE_HOLD:
/* note: shouldn't be displayed, as the view should change */
gtk_label_set_text(GTK_LABEL(priv->label_status), "Conference hold.");
break;
case Call::State::INITIALIZATION:
gtk_label_set_text(GTK_LABEL(priv->label_status), "Initialization...");
break;
case Call::State::COUNT__:
break;
}
/* change button(s) displayed */
gtk_widget_hide(priv->button_accept_incoming);
gtk_widget_hide(priv->button_reject_incoming);
gtk_widget_hide(priv->button_end_call);
switch(state) {
case Call::State::INCOMING:
gtk_widget_show(priv->button_accept_incoming);
gtk_widget_show(priv->button_reject_incoming);
break;
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:
gtk_widget_show(priv->button_end_call);
break;
case Call::State::COUNT__:
break;
}
}
void
incoming_call_view_set_call_info(IncomingCallView *view, const QModelIndex& idx) {
IncomingCallViewPrivate *priv = INCOMING_CALL_VIEW_GET_PRIVATE(view);
......@@ -167,12 +205,23 @@ incoming_call_view_set_call_info(IncomingCallView *view, const QModelIndex& idx)
QByteArray ba_name = var.toString().toLocal8Bit();
/* get image and frame it */
GdkPixbuf *avatar = draw_fallback_avatar(100);
GdkPixbuf *framed_avatar = frame_avatar(avatar);
GdkPixbuf *avatar = ring_draw_fallback_avatar(100);
GdkPixbuf *framed_avatar = ring_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());
/* change some things depending on call state */
Call *call = CallModel::instance()->getCall(idx);
update_state(view, call);
priv->state_change_connection = QObject::connect(
call,
&Call::stateChanged,
[=]() { update_state(view, call); }
);
}
......@@ -663,7 +663,7 @@ gtk_q_tree_model_get_value(GtkTreeModel *tree_model,
case G_TYPE_STRING:
{
QByteArray ba = var.toString().toLocal8Bit();
g_value_set_string(value, (gchar *)ba.data());
g_value_set_string(value, (gchar *)ba.constData());
}
break;
// case G_TYPE_POINTER:
......
......@@ -36,6 +36,7 @@
#include <call.h>
#include <QItemSelectionModel>
#include "incomingcallview.h"
#include <string.h>
#define DEFAULT_VIEW_NAME "placeholder"
......@@ -58,6 +59,7 @@ struct _RingMainWindowPrivate
GtkWidget *treeview_call;
GtkWidget *search_entry;
GtkWidget *stack_main_view;
GtkWidget *button_placecall;
};
G_DEFINE_TYPE_WITH_PRIVATE(RingMainWindow, ring_main_window, GTK_TYPE_APPLICATION_WINDOW);
......@@ -78,16 +80,13 @@ get_index_from_selection(GtkTreeSelection *selection)
}
static void
update_call_model_selection(GtkTreeSelection *selection, gpointer win)
update_call_model_selection(GtkTreeSelection *selection, G_GNUC_UNUSED gpointer user_data)
{
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);
CallModel::instance()->selectionModel()->setCurrentIndex(current, QItemSelectionModel::ClearAndSelect);
else
call_qmodel->selectionModel()->clearCurrentIndex();
CallModel::instance()->selectionModel()->clearCurrentIndex();
}
static void
......@@ -101,16 +100,15 @@ call_selection_changed(GtkTreeSelection *selection, gpointer win)
QModelIndex idx = get_index_from_selection(selection);
if (idx.isValid()) {
QVariant state = idx.model()->data(idx, Call::Role::CallState);
QVariant name = idx.model()->data(idx, Call::Role::Name);
QByteArray ba_name = name.toString().toLocal8Bit();
GtkWidget *new_call_view = NULL;
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();
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;
......@@ -129,8 +127,16 @@ call_selection_changed(GtkTreeSelection *selection, gpointer win)
case Call::State::CONFERENCE_HOLD:
case Call::State::INITIALIZATION:
case Call::State::COUNT__:
{
new_call_view = incoming_call_view_new();
incoming_call_view_set_call_info(INCOMING_CALL_VIEW(new_call_view), idx);
}
break;
}
gtk_stack_add_named(GTK_STACK(priv->stack_main_view), new_call_view, ba_name.constData());
gtk_stack_set_visible_child(GTK_STACK(priv->stack_main_view), new_call_view);
} else {
/* nothing selected in the call model, so show the default screen */
......@@ -153,6 +159,26 @@ call_selection_changed(GtkTreeSelection *selection, gpointer win)
}
}
static void
search_entry_placecall(G_GNUC_UNUSED GtkWidget *entry, gpointer win)
{
RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
const gchar *number = gtk_entry_get_text(GTK_ENTRY(priv->search_entry));
if (number && strlen(number) > 0) {
g_debug("dialing to number: %s", number);
Call *call = CallModel::instance()->dialingCall();
call->setDialNumber(number);
call->performAction(Call::Action::ACCEPT);
/* make this the currently selected call */
QModelIndex idx = CallModel::instance()->getIndex(call);
CallModel::instance()->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
}
}
static void
ring_main_window_init(RingMainWindow *win)
{
......@@ -205,10 +231,8 @@ ring_main_window_init(RingMainWindow *win)
/* 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(),
CallModel::instance()->selectionModel(),
&QItemSelectionModel::currentChanged,
[=](const QModelIndex & current, const QModelIndex & previous) {
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_call));
......@@ -236,7 +260,7 @@ ring_main_window_init(RingMainWindow *win)
);
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);
g_signal_connect(call_selection, "changed", G_CALLBACK(update_call_model_selection), NULL);
/* TODO: replace stack paceholder view */
GtkWidget *placeholder_view = gtk_tree_view_new();
......@@ -245,6 +269,11 @@ ring_main_window_init(RingMainWindow *win)
/* connect signals */
g_signal_connect(call_selection, "changed", G_CALLBACK(call_selection_changed), win);
g_signal_connect(priv->button_placecall, "clicked", G_CALLBACK(search_entry_placecall), win);
g_signal_connect(priv->search_entry, "activate", G_CALLBACK(search_entry_placecall), win);
/* style of search entry */
gtk_widget_override_font(priv->search_entry, pango_font_description_from_string("monospace 15"));
}
static void
......@@ -258,6 +287,7 @@ ring_main_window_class_init(RingMainWindowClass *klass)
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);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, button_placecall);
}
GtkWidget *
......
/*
* 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 "drawing.h"
#include <gtk/gtk.h>
#include <math.h>
GdkPixbuf *
ring_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;
}
GdkPixbuf *
ring_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;
}
\ No newline at end of file
/*
* 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 _DRAWING_H
#define _DRAWING_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
GdkPixbuf *ring_draw_fallback_avatar(int size);
GdkPixbuf *ring_frame_avatar(GdkPixbuf *avatar);
G_END_DECLS
#endif /* _DRAWING */
\ No newline at end of file
......@@ -12,7 +12,9 @@
<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="min-content-height">250</property> -->
<!-- for now, disable scrolling, display everything -->
<property name="vscrollbar_policy">never</property>
<property name="hscrollbar_policy">never</property>
<!-- info viewport -->
<child>
......@@ -59,8 +61,16 @@
</packing>
</child>
<!-- end name or other identity of contact -->
<!-- call state info -->
<child>
<placeholder/>
<object class="GtkLabel" id="label_status">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Incoming...</property>
<attributes>
<attribute name="foreground" value="#88888a8a8585"/>
</attributes>
</object>
</child>
</object>
</child>
......@@ -114,6 +124,21 @@
</packing>
</child>
<!-- end reject button -->
<!-- end button -->
<child>
<object class="GtkButton" id="button_end_call">
<property name="visible">False</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes"> Hang-up</property>
<property name="image">image_hangup</property>
<property name="action-name">app.reject</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<!-- end end button -->
</object>
</child>
<!-- end hbox action bar -->
......@@ -126,4 +151,8 @@
<property name="visible">True</property>
<property name="resource">/cx/ring/RingGnome/reject</property>
</object>
<object class="GtkImage" id="image_hangup">