diff options
Diffstat (limited to 'src/anastasis/anastasis-gtk_handle-policy-meta.c')
-rw-r--r-- | src/anastasis/anastasis-gtk_handle-policy-meta.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/anastasis/anastasis-gtk_handle-policy-meta.c b/src/anastasis/anastasis-gtk_handle-policy-meta.c new file mode 100644 index 0000000..5ec16ed --- /dev/null +++ b/src/anastasis/anastasis-gtk_handle-policy-meta.c @@ -0,0 +1,374 @@ +/* + This file is part of anastasis-gtk. + Copyright (C) 2021 Anastasis SARL + + Anastasis 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, or (at your + option) any later version. + + Anastasis 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 Anastasis; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @file src/anastasis/anastasis-gtk_handle-policy-meta.c + * @brief Handle right-click context menu in policy review + * @author Christian Grothoff + */ +#include <gnunet/platform.h> +#include <gnunet/gnunet_util_lib.h> +#include "anastasis-gtk_action.h" +#include "anastasis-gtk_helper.h" +#include "anastasis-gtk_pe.h" +#include <jansson.h> + + +/** + * Context for menu callbacks. + */ +struct MenuContext +{ + /** + * Reference to the row that the user right-clicked. + */ + GtkTreeRowReference *rr; + +}; + + +/** + * The user selected the 'add policy' menu. + * + * @param menuitem the selected menu + * @param user_data a `struct MenuContext` + */ +static void +add_from_ctx_menu (GtkMenuItem *menuitem, + gpointer user_data) +{ + (void) user_data; + (void) menuitem; + AG_add_policy (); +} + + +/** + * The user selected the 'delete challenge' menu item. + * + * @param menuitem the selected menu + * @param user_data a `struct MenuContext` + */ +static void +delete_challenge_from_ctx_menu (GtkMenuItem *menuitem, + gpointer user_data) +{ + struct MenuContext *ctx = user_data; + GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr); + GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr); + GtkTreeIter iter; + guint pindex; + gboolean is_challenge; + guint mindex; + + if (NULL == path) + return; + if (! gtk_tree_model_get_iter (tm, + &iter, + path)) + { + GNUNET_break (0); + return; + } + gtk_tree_path_free (path); + gtk_tree_model_get (tm, + &iter, + AG_PRMC_POLICY_INDEX, + &pindex, + AG_PRMC_IS_CHALLENGE, + &is_challenge, + AG_PRMC_METHOD_INDEX, + &mindex, + -1); + if (! is_challenge) + { + GNUNET_break (0); + return; + } + AG_delete_challenge (pindex, + mindex); +} + + +/** + * The user selected the 'delete policy' menu item. + * + * @param menuitem the selected menu + * @param user_data a `struct MenuContext` + */ +static void +delete_policy_from_ctx_menu (GtkMenuItem *menuitem, + gpointer user_data) +{ + struct MenuContext *ctx = user_data; + GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr); + GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr); + GtkTreeIter iter; + guint pindex; + + if (NULL == path) + return; + if (! gtk_tree_model_get_iter (tm, + &iter, + path)) + { + GNUNET_break (0); + return; + } + gtk_tree_path_free (path); + gtk_tree_model_get (tm, + &iter, + AG_PRMC_POLICY_INDEX, + &pindex, + -1); + AG_delete_policy (pindex); +} + + +/** + * The user selected the 'edit policy' menu. + * + * @param menuitem the selected menu + * @param user_data a `struct MenuContext` + */ +static void +edit_from_ctx_menu (GtkMenuItem *menuitem, + gpointer user_data) +{ + struct MenuContext *ctx = user_data; + GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr); + GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr); + GtkTreeIter iter; + guint pindex; + + if (NULL == path) + return; + if (! gtk_tree_model_get_iter (tm, + &iter, + path)) + { + GNUNET_break (0); + return; + } + gtk_tree_path_free (path); + gtk_tree_model_get (tm, + &iter, + AG_PRMC_POLICY_INDEX, + &pindex, + -1); + AG_edit_policy (pindex); +} + + +/** + * An item was selected from the context menu; destroy the menu shell. + * + * @param menushell menu to destroy + * @param user_data the 'struct MenuContext' of the menu + */ +static void +context_popup_selection_done (GtkMenuShell *menushell, + gpointer user_data) +{ + struct MenuContext *ctx = user_data; + + gtk_widget_destroy (GTK_WIDGET (menushell)); + if (NULL != ctx->rr) + { + gtk_tree_row_reference_free (ctx->rr); + ctx->rr = NULL; + } + GNUNET_free (ctx); +} + + +/** + * Context menu was requested for the policy. Compute which menu + * items are applicable and display an appropriate menu. + * + * @param tm tree model underlying the tree view where the event happened + * @param iter location in the tree model selected at the time + * @return NULL if no menu could be created, + * otherwise the a pop-up menu + */ +static GtkMenu * +get_popup (GtkTreeModel *tm, + GtkTreeIter *iter) +{ + GtkMenu *menu; + struct MenuContext *ctx; + + ctx = GNUNET_new (struct MenuContext); + menu = GTK_MENU (gtk_menu_new ()); + if (NULL != iter) + { + gboolean is_challenge; + + { + GtkTreePath *path; + + path = gtk_tree_model_get_path (tm, + iter); + ctx->rr = gtk_tree_row_reference_new (tm, + path); + gtk_tree_path_free (path); + } + gtk_tree_model_get (tm, + iter, + AG_PRMC_IS_CHALLENGE, + &is_challenge, + -1); + if (! is_challenge) + { + GtkWidget *child; + + /* only show 'edit' entry for lines that + are for an entire policy */ + child = gtk_menu_item_new_with_label (_ ("_Edit policy...")); + g_signal_connect (child, + "activate", + G_CALLBACK (&edit_from_ctx_menu), + ctx); + gtk_label_set_use_underline (GTK_LABEL ( + gtk_bin_get_child (GTK_BIN (child))), + TRUE); + gtk_widget_show (child); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + child); + } + { + GtkWidget *child; + const char *label; + + if (is_challenge) + label = _ ("Delete challenge"); + else + label = _ ("Delete policy"); + child = gtk_menu_item_new_with_label (label); + g_signal_connect (child, + "activate", + G_CALLBACK (is_challenge + ? &delete_challenge_from_ctx_menu + : &delete_policy_from_ctx_menu), + ctx); + gtk_label_set_use_underline (GTK_LABEL ( + gtk_bin_get_child (GTK_BIN (child))), + TRUE); + gtk_widget_show (child); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), child); + } + + { + GtkWidget *child; + + /* Insert a separator */ + child = gtk_separator_menu_item_new (); + gtk_widget_show (child); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), child); + } + } + + { + GtkWidget *child; + + /* only show 'edit' entry for lines that + are for an entire policy */ + child = gtk_menu_item_new_with_label (_ ("_Add policy...")); + g_signal_connect (child, + "activate", + G_CALLBACK (&add_from_ctx_menu), + ctx); + gtk_label_set_use_underline (GTK_LABEL ( + gtk_bin_get_child (GTK_BIN (child))), + TRUE); + gtk_widget_show (child); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + child); + } + + g_signal_connect (menu, + "selection-done", + G_CALLBACK (&context_popup_selection_done), + ctx); + return menu; +} + + +/** + * We got a button-click on the policy treeview. If it was a + * right-click, display the context menu. + * + * @param widget the GtkTreeView with the search result list + * @param event the event, we only care about button events + * @param user_data NULL + * @return FALSE to propagate the event further, + * TRUE to stop the propagation + */ +gboolean +anastasis_gtk_review_policy_treeview_button_press_event_cb (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + GtkTreeView *tv = GTK_TREE_VIEW (widget); + GdkEventButton *event_button = (GdkEventButton *) event; + GtkTreeModel *tm; + GtkTreePath *path; + GtkTreeIter iter; + GtkMenu *menu; + + if ((GDK_BUTTON_PRESS != event->type) || + (3 != event_button->button)) + return FALSE; /* not a right-click */ + if (! gtk_tree_view_get_path_at_pos (tv, + event_button->x, + event_button->y, + &path, + NULL, + NULL, + NULL)) + { + menu = get_popup (NULL, + NULL); + } + else + { + tm = gtk_tree_view_get_model (tv); + if (! gtk_tree_model_get_iter (tm, + &iter, + path)) + { + /* not sure how we got a path but no iter... */ + GNUNET_break (0); + return FALSE; + } + gtk_tree_path_free (path); + + menu = get_popup (tm, + &iter); + } + if (NULL == menu) + { + GNUNET_break (0); + return FALSE; + } + gtk_menu_popup_at_pointer (menu, + event); + return FALSE; +} |