mainwindow: add some accelerators

Add shortcuts to perform a lot of actions without the mouse. Also
add a Keyboard shortcuts window.

Change-Id: If3fe70a27696b03bf4a067d7bbf004116d4ed97c
parent 32f0efcd
......@@ -762,3 +762,22 @@ conversations_view_select_conversation(ConversationsView *self, const std::strin
idx++;
}
}
int
conversations_view_get_current_selected(ConversationsView *self)
{
g_return_val_if_fail(IS_CONVERSATIONS_VIEW(self), -1);
/* we always drag the selected row */
auto selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
GtkTreeModel *model = NULL;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
auto path = gtk_tree_model_get_path(model, &iter);
auto idx = gtk_tree_path_get_indices(path);
return idx[0];
}
return -1;
}
......@@ -38,5 +38,6 @@ typedef struct _ConversationsViewClass ConversationsViewClass;
GType conversations_view_get_type (void) G_GNUC_CONST;
GtkWidget *conversations_view_new (AccountInfoPointer const & accountInfo);
void conversations_view_select_conversation (ConversationsView *self, const std::string& uid);
int conversations_view_get_current_selected(ConversationsView *self);
G_END_DECLS
......@@ -128,7 +128,7 @@ map_boolean_to_orientation(GValue *value, GVariant *variant, G_GNUC_UNUSED gpoin
}
static void
reject_incoming_call(G_GNUC_UNUSED GtkWidget *widget, IncomingCallView *self)
reject_incoming_call(IncomingCallView *self)
{
g_return_if_fail(IS_INCOMING_CALL_VIEW(self));
auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(self);
......@@ -136,7 +136,7 @@ reject_incoming_call(G_GNUC_UNUSED GtkWidget *widget, IncomingCallView *self)
}
static void
accept_incoming_call(G_GNUC_UNUSED GtkWidget *widget, IncomingCallView *self)
accept_incoming_call(IncomingCallView *self)
{
g_return_if_fail(IS_INCOMING_CALL_VIEW(self));
auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(self);
......@@ -191,8 +191,8 @@ incoming_call_view_init(IncomingCallView *view)
map_boolean_to_orientation,
nullptr, nullptr, nullptr);
g_signal_connect(priv->button_reject_incoming, "clicked", G_CALLBACK(reject_incoming_call), view);
g_signal_connect(priv->button_accept_incoming, "clicked", G_CALLBACK(accept_incoming_call), view);
g_signal_connect_swapped(priv->button_reject_incoming, "clicked", G_CALLBACK(reject_incoming_call), view);
g_signal_connect_swapped(priv->button_accept_incoming, "clicked", G_CALLBACK(accept_incoming_call), view);
}
static void
......
......@@ -104,6 +104,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(RingClient, ring_client, GTK_TYPE_APPLICATION);
#define RING_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), RING_CLIENT_TYPE, RingClientPrivate))
static void
exception_dialog(const char* msg)
{
......@@ -123,10 +124,60 @@ static void
ring_accelerators(RingClient *client)
{
#if GTK_CHECK_VERSION(3,12,0)
const gchar *quit_accels[2] = { "<Ctrl>Q", NULL };
const gchar *quit_accels[2] = {"<Ctrl>Q", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.quit", quit_accels);
const gchar *accounts_accels[2] = {"<Ctrl>A", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.display_account_list", accounts_accels);
const gchar *search_accels[2] = {"<Ctrl>F", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.search", search_accels);
const gchar *conversations_list_accels[2] = {"<Ctrl>L", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.conversations_list", conversations_list_accels);
const gchar *requests_list_accels[2] = {"<Ctrl>R", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.requests_list", requests_list_accels);
const gchar *audio_call_accels[2] = {"<Ctrl><Shift>C", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.audio_call", audio_call_accels);
const gchar *clear_history_accels[2] = {"<Ctrl><Shift>L", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.clear_history", clear_history_accels);
const gchar *remove_conversation_accels[2] = {"<Ctrl><Shift>Delete", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.remove_conversation", remove_conversation_accels);
const gchar *block_contact_accels[2] = {"<Ctrl><Shift>B", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.block_contact", block_contact_accels);
const gchar *unblock_contact_accels[2] = {"<Ctrl><Shift>U", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.unblock_contact", unblock_contact_accels);
const gchar *copy_contact_accels[2] = {"<Ctrl><Shift>J", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.copy_contact", copy_contact_accels);
const gchar *add_contact_accels[2] = {"<Ctrl><Shift>A", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.add_contact", add_contact_accels);
const gchar *accept_call_accels[2] = {"<Ctrl>Y", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.accept_call", accept_call_accels);
const gchar *decline_call_accels[2] = {"<Ctrl>D", NULL};
gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.decline_call", decline_call_accels);
#else
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>Q", "app.quit", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>A", "app.display_account_list", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>F", "app.search", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>L", "app.conversations_list", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>R", "app.requests_list", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>C", "app.audio_call", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>L", "app.clear_history", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>Delete", "app.remove_conversation", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>B", "app.block_contact", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>U", "app.unblock_contact", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>J", "app.copy_contact", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control><Shift>A", "app.add_contact", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>Y", "app.accept_call", NULL);
gtk_application_add_accelerator(GTK_APPLICATION(client), "<Control>D", "app.decline_call", NULL);
#endif
}
......@@ -156,6 +207,50 @@ action_about(G_GNUC_UNUSED GSimpleAction *simple,
ring_about_dialog(priv->win);
}
static void
exec_action(GSimpleAction *simple,
G_GNUC_UNUSED GVariant *parameter,
gpointer user_data)
{
g_return_if_fail(G_IS_APPLICATION(user_data));
RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(user_data);
GValue value = G_VALUE_INIT;
g_value_init(&value, G_TYPE_STRING);
g_object_get_property(G_OBJECT(simple), "name", &value);
if (!g_value_get_string(&value)) return;
std::string name = g_value_get_string(&value);
if (name == "display_account_list")
ring_main_window_display_account_list(RING_MAIN_WINDOW(priv->win));
else if (name == "search")
ring_main_window_search(RING_MAIN_WINDOW(priv->win));
else if (name == "conversations_list")
ring_main_window_conversations_list(RING_MAIN_WINDOW(priv->win));
else if (name == "requests_list")
ring_main_window_requests_list(RING_MAIN_WINDOW(priv->win));
else if (name == "audio_call")
ring_main_window_audio_call(RING_MAIN_WINDOW(priv->win));
else if (name == "clear_history")
ring_main_window_clear_history(RING_MAIN_WINDOW(priv->win));
else if (name == "remove_conversation")
ring_main_window_remove_conversation(RING_MAIN_WINDOW(priv->win));
else if (name == "block_contact")
ring_main_window_block_contact(RING_MAIN_WINDOW(priv->win));
else if (name == "unblock_contact")
ring_main_window_unblock_contact(RING_MAIN_WINDOW(priv->win));
else if (name == "copy_contact")
ring_main_window_copy_contact(RING_MAIN_WINDOW(priv->win));
else if (name == "add_contact")
ring_main_window_add_contact(RING_MAIN_WINDOW(priv->win));
else if (name == "accept_call")
ring_main_window_accept_call(RING_MAIN_WINDOW(priv->win));
else if (name == "decline_call")
ring_main_window_decline_call(RING_MAIN_WINDOW(priv->win));
else
g_warning("Missing implementation for this action: %s", name.c_str());
}
static void
toggle_smartinfo(GSimpleAction *action, GVariant *parameter, gpointer)
{
......@@ -167,19 +262,45 @@ toggle_smartinfo(GSimpleAction *action, GVariant *parameter, gpointer)
}
}
static const GActionEntry ring_actions[] =
static void
action_show_shortcuts(G_GNUC_UNUSED GSimpleAction *action, G_GNUC_UNUSED GVariant *parameter, gpointer user_data)
{
{ "accept", NULL, NULL, NULL, NULL, {0} },
{ "hangup", NULL, NULL, NULL, NULL, {0} },
{ "hold", NULL, NULL, "false", NULL, {0} },
{ "quit", action_quit, NULL, NULL, NULL, {0} },
{ "about", action_about, NULL, NULL, NULL, {0} },
{ "mute_audio", NULL, NULL, "false", NULL, {0} },
{ "mute_video", NULL, NULL, "false", NULL, {0} },
{ "record", NULL, NULL, "false", NULL, {0} },
{ "display-smartinfo", NULL, NULL, "false", toggle_smartinfo, {0} },
/* TODO implement the other actions */
// { "transfer", NULL, NULL, "flase", NULL, {0} },
g_return_if_fail(G_IS_APPLICATION(user_data));
RingClientPrivate *priv = RING_CLIENT_GET_PRIVATE(user_data);
GtkBuilder *builder = gtk_builder_new_from_resource("/net/jami/JamiGnome/help-overlay.ui");
GtkWidget *overlay = GTK_WIDGET(gtk_builder_get_object (builder, "help_overlay"));
gtk_window_set_transient_for(GTK_WINDOW(overlay), GTK_WINDOW(priv->win));
gtk_widget_show(overlay);
g_object_unref(builder);
}
static const GActionEntry ring_actions[] = {
{"accept", NULL, NULL, NULL, NULL, {0}},
{"hangup", NULL, NULL, NULL, NULL, {0}},
{"hold", NULL, NULL, "false", NULL, {0}},
{"quit", action_quit, NULL, NULL, NULL, {0}},
{"about", action_about, NULL, NULL, NULL, {0}},
{"mute_audio", NULL, NULL, "false", NULL, {0}},
{"mute_video", NULL, NULL, "false", NULL, {0}},
{"record", NULL, NULL, "false", NULL, {0}},
{"display-smartinfo", NULL, NULL, "false", toggle_smartinfo, {0}},
{"display_account_list", exec_action, NULL, NULL, NULL, {0}},
{"search", exec_action, NULL, NULL, NULL, {0}},
{"conversations_list", exec_action, NULL, NULL, NULL, {0}},
{"requests_list", exec_action, NULL, NULL, NULL, {0}},
{"audio_call", exec_action, NULL, NULL, NULL, {0}},
{"clear_history", exec_action, NULL, NULL, NULL, {0}},
{"remove_conversation", exec_action, NULL, NULL, NULL, {0}},
{"block_contact", exec_action, NULL, NULL, NULL, {0}},
{"unblock_contact", exec_action, NULL, NULL, NULL, {0}},
{"copy_contact", exec_action, NULL, NULL, NULL, {0}},
{"add_contact", exec_action, NULL, NULL, NULL, {0}},
{"accept_call", exec_action, NULL, NULL, NULL, {0}},
{"decline_call", exec_action, NULL, NULL, NULL, {0}},
{"show_shortcuts", action_show_shortcuts, NULL, NULL, NULL, {0}},
};
static void
......
......@@ -315,6 +315,10 @@ public:
void enterSettingsView();
void leaveSettingsView();
int getCurrentUid();
void forCurrentConversation(const std::function<void(const lrc::api::conversation::Info&)>& func);
bool showOkCancelDialog(const std::string& title, const std::string& text);
lrc::api::conversation::Info getCurrentConversation(GtkWidget* frame_call);
void showAccountSelectorWidget(bool show = true);
......@@ -1621,6 +1625,48 @@ CppImpl::leaveSettingsView()
}
}
int
CppImpl::getCurrentUid()
{
const auto &treeview = gtk_notebook_get_current_page(
GTK_NOTEBOOK(widgets->notebook_contacts)) == contactRequestsPageNum
? widgets->treeview_contact_requests
: widgets->treeview_conversations;
return conversations_view_get_current_selected(CONVERSATIONS_VIEW(treeview));
}
void
CppImpl::forCurrentConversation(const std::function<void(const lrc::api::conversation::Info&)>& func)
{
const auto current = getCurrentUid();
if (current == -1) return;
try {
auto conversation = accountInfo_->conversationModel->filteredConversation(current);
if (conversation.participants.empty()) return;
func(conversation);
} catch (...) {
g_warning("Can't retrieve conversation %d", current);
}
}
bool
CppImpl::showOkCancelDialog(const std::string &title, const std::string &text)
{
auto *confirm_dialog = gtk_message_dialog_new(
GTK_WINDOW(self), GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
"%s", text.c_str());
gtk_window_set_title(GTK_WINDOW(confirm_dialog), title.c_str());
gtk_dialog_set_default_response(GTK_DIALOG(confirm_dialog),
GTK_RESPONSE_CANCEL);
gtk_widget_show_all(confirm_dialog);
auto res = gtk_dialog_run(GTK_DIALOG(confirm_dialog));
gtk_widget_destroy(confirm_dialog);
return res == GTK_RESPONSE_OK;
}
void
CppImpl::updateLrc(const std::string& id, const std::string& accountIdToFlagFreeable)
{
......@@ -2244,25 +2290,196 @@ ring_main_window_can_close(RingMainWindow* self)
{
g_return_val_if_fail(IS_RING_MAIN_WINDOW(self), true);
auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self));
if (priv->cpp && !lrc::api::Lrc::activeCalls().empty()) {
auto* close_dialog = gtk_message_dialog_new(GTK_WINDOW(self),
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
if (!lrc::api::Lrc::activeCalls().empty()) {
auto res = priv->cpp->showOkCancelDialog(
_("Stop current call?"),
_("A call is currently ongoing. Do you want to close the window and stop all current calls?"));
gtk_window_set_title(GTK_WINDOW(close_dialog), _("Stop current call?"));
gtk_dialog_set_default_response(GTK_DIALOG(close_dialog), GTK_RESPONSE_CANCEL);
gtk_widget_show_all(close_dialog);
if (res) lrc::api::NewCallModel::hangupCallsAndConferences();
return res;
}
return true;
}
auto res = gtk_dialog_run(GTK_DIALOG(close_dialog));
void
ring_main_window_display_account_list(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
gtk_combo_box_popup(GTK_COMBO_BOX(priv->combobox_account_selector));
}
gtk_widget_destroy(close_dialog);
if (res == GTK_RESPONSE_OK) {
lrc::api::NewCallModel::hangupCallsAndConferences();
return true;
} else {
return false;
}
void
ring_main_window_search(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
gtk_widget_grab_focus(GTK_WIDGET(priv->search_entry));
}
void
ring_main_window_conversations_list(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
auto smartViewPageNum = gtk_notebook_page_num(GTK_NOTEBOOK(priv->notebook_contacts),
priv->scrolled_window_smartview);
gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook_contacts), smartViewPageNum);
gtk_widget_grab_focus(GTK_WIDGET(priv->treeview_conversations));
}
void
ring_main_window_requests_list(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
if (!priv->cpp->accountInfo_->contactModel->hasPendingRequests()) return;
auto contactRequestsPageNum = gtk_notebook_page_num(GTK_NOTEBOOK(priv->notebook_contacts),
priv->scrolled_window_contact_requests);
gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook_contacts), contactRequestsPageNum);
gtk_widget_grab_focus(GTK_WIDGET(priv->treeview_contact_requests));
}
void
ring_main_window_audio_call(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp);
priv->cpp->forCurrentConversation([&](const auto& conversation){
priv->cpp->accountInfo_->conversationModel->placeAudioOnlyCall(conversation.uid);
});
}
void
ring_main_window_clear_history(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
priv->cpp->forCurrentConversation([&](const auto &conversation) {
auto res = priv->cpp->showOkCancelDialog(
_("Clear history"),
_("Do you really want to clear the history of this conversation?"));
if (!res) return;
priv->cpp->accountInfo_->conversationModel->clearHistory(conversation.uid);
});
}
void
ring_main_window_remove_conversation(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
priv->cpp->forCurrentConversation([&](const auto& conversation){
auto res = priv->cpp->showOkCancelDialog(
_("Remove conversation"),
_("Do you really want to remove this conversation?"));
if (!res) return;
priv->cpp->accountInfo_->conversationModel->removeConversation(conversation.uid);
});
}
void
ring_main_window_block_contact(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
priv->cpp->forCurrentConversation([&](const auto& conversation){
auto res = priv->cpp->showOkCancelDialog(
_("Block contact"),
_("Do you really want to block this contact?"));
if (!res) return;
priv->cpp->accountInfo_->conversationModel->removeConversation(conversation.uid, true);
});
}
void
ring_main_window_unblock_contact(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
priv->cpp->forCurrentConversation([&](const auto& conversation){
auto& uri = conversation.participants[0];
auto contactInfo = priv->cpp->accountInfo_->contactModel->getContact(uri);
if (!contactInfo.isBanned) return;
priv->cpp->accountInfo_->contactModel->addContact(contactInfo);
});
}
void
ring_main_window_copy_contact(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
priv->cpp->forCurrentConversation([&](const auto& conversation){
auto& contact = priv->cpp->accountInfo_->contactModel->getContact(conversation.participants.front());
auto bestName = contact.registeredName.empty() ? contact.profileInfo.uri : contact.registeredName;
auto text = (gchar *)bestName.c_str();
GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text(clip, text, -1);
clip = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
gtk_clipboard_set_text(clip, text, -1);
});
}
void
ring_main_window_add_contact(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp);
priv->cpp->forCurrentConversation([&](const auto &conversation) {
priv->cpp->accountInfo_->conversationModel->makePermanent(conversation.uid);
});
}
void
ring_main_window_accept_call(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp && priv->cpp->accountInfo_);
// Select the first conversation of the list
auto current = priv->cpp->getCurrentUid();
if (current == -1) return;
try {
auto conversation = priv->cpp->accountInfo_->conversationModel->filteredConversation(current);
if (conversation.participants.empty()) return;
auto contactUri = conversation.participants.at(0);
auto contact = priv->cpp->accountInfo_->contactModel->getContact(contactUri);
// If the contact is pending, we should accept its request
if (contact.profileInfo.type == lrc::api::profile::Type::PENDING)
priv->cpp->accountInfo_->conversationModel->makePermanent(conversation.uid);
// Accept call
priv->cpp->accountInfo_->callModel->accept(conversation.callId);
} catch (...) {
g_warning("Can't retrieve conversation %d", current);
}
return true;
}
void
ring_main_window_decline_call(RingMainWindow *win)
{
g_return_if_fail(IS_RING_MAIN_WINDOW(win));
auto *priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(win));
g_return_if_fail(priv && priv->cpp);
priv->cpp->forCurrentConversation([&](const auto &conversation) {
priv->cpp->accountInfo_->callModel->hangUp(conversation.callId);
});
}
//==============================================================================
......
......@@ -39,6 +39,20 @@ GType ring_main_window_get_type (void) G_GNUC_CONST;
GtkWidget *ring_main_window_new (GtkApplication *app);
void ring_main_window_reset (RingMainWindow *win);
bool ring_main_window_can_close(RingMainWindow *win);
void ring_main_window_display_account_list(RingMainWindow *win);
void ring_main_window_search(RingMainWindow *win);
void ring_main_window_conversations_list(RingMainWindow *win);
void ring_main_window_requests_list(RingMainWindow *win);
void ring_main_window_audio_call(RingMainWindow *win);
void ring_main_window_clear_history(RingMainWindow *win);
void ring_main_window_remove_conversation(RingMainWindow *win);
void ring_main_window_block_contact(RingMainWindow *win);
void ring_main_window_unblock_contact(RingMainWindow *win);
void ring_main_window_copy_contact(RingMainWindow *win);
void ring_main_window_add_contact(RingMainWindow *win);
void ring_main_window_accept_call(RingMainWindow *win);
void ring_main_window_decline_call(RingMainWindow *win);
G_END_DECLS
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkShortcutsWindow" id="help_overlay">
<property name="modal">true</property>
<child>
<object class="GtkShortcutsSection">
<property name="visible">true</property>
<property name="section-name">shortcuts</property>
<property name="max-height">10</property>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">true</property>
<property name="title" translatable="yes" context="shortcut window">General</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">&lt;ctrl&gt;m</property>
<property name="title" translatable="yes" context="shortcut window">Open application menu</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">&lt;ctrl&gt;a</property>
<property name="title" translatable="yes" context="shortcut window">Open account list</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">&lt;ctrl&gt;f</property>
<property name="title" translatable="yes" context="shortcut window">Select search bar</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">&lt;ctrl&gt;l</property>
<property name="title" translatable="yes" context="shortcut window">Focus the list of conversations</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">&lt;ctrl&gt;r</property>
<property name="title" translatable="yes" context="shortcut window">Focus the list pending requests</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">true</property>
<property name="title" translatable="yes" context="shortcut window">Conversations</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">true</property>
<property name="accelerator">Return</property>
<property name="title" translatable="yes" context="shortcut window">Start a video call</property>