From e23740acb29b87d0dbac51c30497f2d4bf46f7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= Date: Mon, 29 Apr 2019 10:31:14 -0400 Subject: [PATCH] mainwindow: add some accelerators Add shortcuts to perform a lot of actions without the mouse. Also add a Keyboard shortcuts window. Change-Id: If3fe70a27696b03bf4a067d7bbf004116d4ed97c --- src/conversationsview.cpp | 19 +++ src/conversationsview.h | 1 + src/incomingcallview.cpp | 8 +- src/ring_client.cpp | 147 +++++++++++++++++++++-- src/ringmainwindow.cpp | 247 +++++++++++++++++++++++++++++++++++--- src/ringmainwindow.h | 14 +++ ui/help-overlay.ui | 191 +++++++++++++++++++++++++++++ ui/incomingcallview.ui | 2 - ui/ringgearsmenu.ui | 6 +- ui/ringmainwindow.ui | 5 + ui/ui.gresource.xml | 1 + 11 files changed, 603 insertions(+), 38 deletions(-) create mode 100644 ui/help-overlay.ui diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp index 2f8ef16a..7cffdafa 100644 --- a/src/conversationsview.cpp +++ b/src/conversationsview.cpp @@ -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; +} diff --git a/src/conversationsview.h b/src/conversationsview.h index 24db86a2..1cecda7d 100644 --- a/src/conversationsview.h +++ b/src/conversationsview.h @@ -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 diff --git a/src/incomingcallview.cpp b/src/incomingcallview.cpp index 9b7b318b..c60e45b4 100644 --- a/src/incomingcallview.cpp +++ b/src/incomingcallview.cpp @@ -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 diff --git a/src/ring_client.cpp b/src/ring_client.cpp index 04089bc6..e8fab5a3 100644 --- a/src/ring_client.cpp +++ b/src/ring_client.cpp @@ -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] = { "Q", NULL }; + const gchar *quit_accels[2] = {"Q", NULL}; gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.quit", quit_accels); + + const gchar *accounts_accels[2] = {"A", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.display_account_list", accounts_accels); + + const gchar *search_accels[2] = {"F", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.search", search_accels); + + const gchar *conversations_list_accels[2] = {"L", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.conversations_list", conversations_list_accels); + const gchar *requests_list_accels[2] = {"R", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.requests_list", requests_list_accels); + + const gchar *audio_call_accels[2] = {"C", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.audio_call", audio_call_accels); + const gchar *clear_history_accels[2] = {"L", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.clear_history", clear_history_accels); + const gchar *remove_conversation_accels[2] = {"Delete", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.remove_conversation", remove_conversation_accels); + const gchar *block_contact_accels[2] = {"B", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.block_contact", block_contact_accels); + const gchar *unblock_contact_accels[2] = {"U", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.unblock_contact", unblock_contact_accels); + const gchar *copy_contact_accels[2] = {"J", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.copy_contact", copy_contact_accels); + const gchar *add_contact_accels[2] = {"A", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.add_contact", add_contact_accels); + + const gchar *accept_call_accels[2] = {"Y", NULL}; + gtk_application_set_accels_for_action(GTK_APPLICATION(client), "app.accept_call", accept_call_accels); + const gchar *decline_call_accels[2] = {"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), "Q", "app.quit", NULL); + + gtk_application_add_accelerator(GTK_APPLICATION(client), "A", "app.display_account_list", NULL); + + gtk_application_add_accelerator(GTK_APPLICATION(client), "F", "app.search", NULL); + + gtk_application_add_accelerator(GTK_APPLICATION(client), "L", "app.conversations_list", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "R", "app.requests_list", NULL); + + gtk_application_add_accelerator(GTK_APPLICATION(client), "C", "app.audio_call", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "L", "app.clear_history", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "Delete", "app.remove_conversation", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "B", "app.block_contact", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "U", "app.unblock_contact", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "J", "app.copy_contact", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "A", "app.add_contact", NULL); + + gtk_application_add_accelerator(GTK_APPLICATION(client), "Y", "app.accept_call", NULL); + gtk_application_add_accelerator(GTK_APPLICATION(client), "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 diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp index ea38fbea..b39530c0 100644 --- a/src/ringmainwindow.cpp +++ b/src/ringmainwindow.cpp @@ -315,6 +315,10 @@ public: void enterSettingsView(); void leaveSettingsView(); + int getCurrentUid(); + void forCurrentConversation(const std::function& 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& 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); + }); } //============================================================================== diff --git a/src/ringmainwindow.h b/src/ringmainwindow.h index 994abd50..ec5fd300 100644 --- a/src/ringmainwindow.h +++ b/src/ringmainwindow.h @@ -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 diff --git a/ui/help-overlay.ui b/ui/help-overlay.ui new file mode 100644 index 00000000..f4163d08 --- /dev/null +++ b/ui/help-overlay.ui @@ -0,0 +1,191 @@ + + + + true + + + true + shortcuts + 10 + + + true + General + + + true + <ctrl>m + Open application menu + + + + + true + <ctrl>a + Open account list + + + + + true + <ctrl>f + Select search bar + + + + + true + <ctrl>l + Focus the list of conversations + + + + + true + <ctrl>r + Focus the list pending requests + + + + + + + + + true + Conversations + + + true + Return + Start a video call + + + + + true + <ctrl><shift>c + Start an audio call + + + + + true + <ctrl><shift>l + Clear history + + + + + true + <ctrl><shift>a + Add conversation + + + + + true + <ctrl><shift>Delete + Remove conversation + + + + + true + <ctrl><shift>b + Block contact + + + + + true + <ctrl><shift>u + Unblock contact + + + + + true + <ctrl><shift>j + Copy contact name + + + + + + + + + true + Call + + + true + <ctrl>y + Accept call + + + + + true + <ctrl>d + Decline call + + + + + + + + true + Settings + + + true + <ctrl>s + Open/Close settings page + + + + + true + <ctrl>g + Open general settings + + + + + true + <ctrl>m + Open media settings + + + + + true + <ctrl>a + Open account settings + + + + + + + + + true + Chat view + + + true + <shift>Return + Write on a new line + + + + + + + + + diff --git a/ui/incomingcallview.ui b/ui/incomingcallview.ui index dd7ed18c..4fb1072c 100644 --- a/ui/incomingcallview.ui +++ b/ui/incomingcallview.ui @@ -151,7 +151,6 @@ True Accept image_accept - app.accept True @@ -173,7 +172,6 @@ Reject True image_reject - app.hangup True diff --git a/ui/ringgearsmenu.ui b/ui/ringgearsmenu.ui index 4b9c4e67..b0b1b485 100644 --- a/ui/ringgearsmenu.ui +++ b/ui/ringgearsmenu.ui @@ -3,12 +3,10 @@
- _About app.about diff --git a/ui/ringmainwindow.ui b/ui/ringmainwindow.ui index 436790bf..9d755705 100644 --- a/ui/ringmainwindow.ui +++ b/ui/ringmainwindow.ui @@ -56,6 +56,7 @@ False Menu none + True @@ -82,6 +83,7 @@ False image_general_settings False + False @@ -98,6 +100,7 @@ image_media_settings False radiobutton_general_settings + False @@ -114,6 +117,7 @@ image_account_settings False radiobutton_general_settings + False @@ -144,6 +148,7 @@ False False Settings + True diff --git a/ui/ui.gresource.xml b/ui/ui.gresource.xml index 5a519b84..2b7a446d 100644 --- a/ui/ui.gresource.xml +++ b/ui/ui.gresource.xml @@ -15,5 +15,6 @@ avatarmanipulation.ui webkitchatcontainer.ui usernameregistrationbox.ui + help-overlay.ui -- GitLab