anastasis-gtk

Demonstrator GUI for Anastasis
Log | Files | Refs | README | LICENSE

anastasis-gtk_handle-policy-meta.c (10260B)


      1 /*
      2      This file is part of anastasis-gtk.
      3      Copyright (C) 2021 Anastasis SARL
      4 
      5      Anastasis is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      Anastasis is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with Anastasis; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 
     21 /**
     22  * @file src/anastasis/anastasis-gtk_handle-policy-meta.c
     23  * @brief Handle right-click context menu in policy review
     24  * @author Christian Grothoff
     25  */
     26 #include <gnunet/gnunet_util_lib.h>
     27 #include "anastasis-gtk_action.h"
     28 #include "anastasis-gtk_helper.h"
     29 #include "anastasis-gtk_pe.h"
     30 #include <jansson.h>
     31 
     32 
     33 /**
     34  * Context for menu callbacks.
     35  */
     36 struct MenuContext
     37 {
     38   /**
     39    * Reference to the row that the user right-clicked.
     40    */
     41   GtkTreeRowReference *rr;
     42 
     43 };
     44 
     45 
     46 /**
     47  * The user selected the 'add policy' menu.
     48  *
     49  * @param menuitem the selected menu
     50  * @param user_data a `struct MenuContext`
     51  */
     52 static void
     53 add_from_ctx_menu (GtkMenuItem *menuitem,
     54                    gpointer user_data)
     55 {
     56   (void) user_data;
     57   (void) menuitem;
     58   AG_add_policy ();
     59 }
     60 
     61 
     62 /**
     63  * The user selected the 'delete challenge' menu item.
     64  *
     65  * @param menuitem the selected menu
     66  * @param user_data a `struct MenuContext`
     67  */
     68 static void
     69 delete_challenge_from_ctx_menu (GtkMenuItem *menuitem,
     70                                 gpointer user_data)
     71 {
     72   struct MenuContext *ctx = user_data;
     73   GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr);
     74   GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr);
     75   GtkTreeIter iter;
     76   guint pindex;
     77   gboolean is_challenge;
     78   guint mindex;
     79 
     80   if (NULL == path)
     81     return;
     82   if (! gtk_tree_model_get_iter (tm,
     83                                  &iter,
     84                                  path))
     85   {
     86     GNUNET_break (0);
     87     return;
     88   }
     89   gtk_tree_path_free (path);
     90   gtk_tree_model_get (tm,
     91                       &iter,
     92                       AG_PRMC_POLICY_INDEX,
     93                       &pindex,
     94                       AG_PRMC_IS_CHALLENGE,
     95                       &is_challenge,
     96                       AG_PRMC_METHOD_INDEX,
     97                       &mindex,
     98                       -1);
     99   if (! is_challenge)
    100   {
    101     GNUNET_break (0);
    102     return;
    103   }
    104   AG_delete_challenge (pindex,
    105                        mindex);
    106 }
    107 
    108 
    109 /**
    110  * The user selected the 'delete policy' menu item.
    111  *
    112  * @param menuitem the selected menu
    113  * @param user_data a `struct MenuContext`
    114  */
    115 static void
    116 delete_policy_from_ctx_menu (GtkMenuItem *menuitem,
    117                              gpointer user_data)
    118 {
    119   struct MenuContext *ctx = user_data;
    120   GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr);
    121   GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr);
    122   GtkTreeIter iter;
    123   guint pindex;
    124 
    125   if (NULL == path)
    126     return;
    127   if (! gtk_tree_model_get_iter (tm,
    128                                  &iter,
    129                                  path))
    130   {
    131     GNUNET_break (0);
    132     return;
    133   }
    134   gtk_tree_path_free (path);
    135   gtk_tree_model_get (tm,
    136                       &iter,
    137                       AG_PRMC_POLICY_INDEX,
    138                       &pindex,
    139                       -1);
    140   AG_delete_policy (pindex);
    141 }
    142 
    143 
    144 /**
    145  * The user selected the 'edit policy' menu.
    146  *
    147  * @param menuitem the selected menu
    148  * @param user_data a `struct MenuContext`
    149  */
    150 static void
    151 edit_from_ctx_menu (GtkMenuItem *menuitem,
    152                     gpointer user_data)
    153 {
    154   struct MenuContext *ctx = user_data;
    155   GtkTreePath *path = gtk_tree_row_reference_get_path (ctx->rr);
    156   GtkTreeModel *tm = gtk_tree_row_reference_get_model (ctx->rr);
    157   GtkTreeIter iter;
    158   guint pindex;
    159 
    160   if (NULL == path)
    161     return;
    162   if (! gtk_tree_model_get_iter (tm,
    163                                  &iter,
    164                                  path))
    165   {
    166     GNUNET_break (0);
    167     return;
    168   }
    169   gtk_tree_path_free (path);
    170   gtk_tree_model_get (tm,
    171                       &iter,
    172                       AG_PRMC_POLICY_INDEX,
    173                       &pindex,
    174                       -1);
    175   AG_edit_policy (pindex);
    176 }
    177 
    178 
    179 /**
    180  * An item was selected from the context menu; destroy the menu shell.
    181  *
    182  * @param menushell menu to destroy
    183  * @param user_data the 'struct MenuContext' of the menu
    184  */
    185 static void
    186 context_popup_selection_done (GtkMenuShell *menushell,
    187                               gpointer user_data)
    188 {
    189   struct MenuContext *ctx = user_data;
    190 
    191   gtk_widget_destroy (GTK_WIDGET (menushell));
    192   if (NULL != ctx->rr)
    193   {
    194     gtk_tree_row_reference_free (ctx->rr);
    195     ctx->rr = NULL;
    196   }
    197   GNUNET_free (ctx);
    198 }
    199 
    200 
    201 /**
    202  * Context menu was requested for the policy.  Compute which menu
    203  * items are applicable and display an appropriate menu.
    204  *
    205  * @param tm tree model underlying the tree view where the event happened
    206  * @param iter location in the tree model selected at the time
    207  * @return NULL if no menu could be created,
    208  *         otherwise the a pop-up menu
    209  */
    210 static GtkMenu *
    211 get_popup (GtkTreeModel *tm,
    212            GtkTreeIter *iter)
    213 {
    214   GtkMenu *menu;
    215   struct MenuContext *ctx;
    216 
    217   ctx = GNUNET_new (struct MenuContext);
    218   menu = GTK_MENU (gtk_menu_new ());
    219   if (NULL != iter)
    220   {
    221     gboolean is_challenge;
    222 
    223     {
    224       GtkTreePath *path;
    225 
    226       path = gtk_tree_model_get_path (tm,
    227                                       iter);
    228       ctx->rr = gtk_tree_row_reference_new (tm,
    229                                             path);
    230       gtk_tree_path_free (path);
    231     }
    232     gtk_tree_model_get (tm,
    233                         iter,
    234                         AG_PRMC_IS_CHALLENGE,
    235                         &is_challenge,
    236                         -1);
    237     if (! is_challenge)
    238     {
    239       GtkWidget *child;
    240 
    241       /* only show 'edit' entry for lines that
    242          are for an entire policy */
    243       child = gtk_menu_item_new_with_label (_ ("_Edit policy..."));
    244       g_signal_connect (child,
    245                         "activate",
    246                         G_CALLBACK (&edit_from_ctx_menu),
    247                         ctx);
    248       gtk_label_set_use_underline (GTK_LABEL (
    249                                      gtk_bin_get_child (GTK_BIN (child))),
    250                                    TRUE);
    251       gtk_widget_show (child);
    252       gtk_menu_shell_append (GTK_MENU_SHELL (menu),
    253                              child);
    254     }
    255     {
    256       GtkWidget *child;
    257       const char *label;
    258 
    259       if (is_challenge)
    260         label = _ ("Delete challenge");
    261       else
    262         label = _ ("Delete policy");
    263       child = gtk_menu_item_new_with_label (label);
    264       g_signal_connect (child,
    265                         "activate",
    266                         G_CALLBACK (is_challenge
    267                                     ? &delete_challenge_from_ctx_menu
    268                                     : &delete_policy_from_ctx_menu),
    269                         ctx);
    270       gtk_label_set_use_underline (GTK_LABEL (
    271                                      gtk_bin_get_child (GTK_BIN (child))),
    272                                    TRUE);
    273       gtk_widget_show (child);
    274       gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
    275     }
    276 
    277     {
    278       GtkWidget *child;
    279 
    280       /* Insert a separator */
    281       child = gtk_separator_menu_item_new ();
    282       gtk_widget_show (child);
    283       gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
    284     }
    285   }
    286 
    287   {
    288     GtkWidget *child;
    289 
    290     /* only show 'edit' entry for lines that
    291        are for an entire policy */
    292     child = gtk_menu_item_new_with_label (_ ("_Add policy..."));
    293     g_signal_connect (child,
    294                       "activate",
    295                       G_CALLBACK (&add_from_ctx_menu),
    296                       ctx);
    297     gtk_label_set_use_underline (GTK_LABEL (
    298                                    gtk_bin_get_child (GTK_BIN (child))),
    299                                  TRUE);
    300     gtk_widget_show (child);
    301     gtk_menu_shell_append (GTK_MENU_SHELL (menu),
    302                            child);
    303   }
    304 
    305   g_signal_connect (menu,
    306                     "selection-done",
    307                     G_CALLBACK (&context_popup_selection_done),
    308                     ctx);
    309   return menu;
    310 }
    311 
    312 
    313 /**
    314  * We got a button-click on the policy treeview.  If it was a
    315  * right-click, display the context menu.
    316  *
    317  * @param widget the GtkTreeView with the search result list
    318  * @param event the event, we only care about button events
    319  * @param user_data NULL
    320  * @return FALSE to propagate the event further,
    321  *         TRUE to stop the propagation
    322  */
    323 gboolean
    324 anastasis_gtk_review_policy_treeview_button_press_event_cb (GtkWidget *widget,
    325                                                             GdkEvent *event,
    326                                                             gpointer user_data)
    327 {
    328   GtkTreeView *tv = GTK_TREE_VIEW (widget);
    329   GdkEventButton *event_button = (GdkEventButton *) event;
    330   GtkTreeModel *tm;
    331   GtkTreePath *path;
    332   GtkTreeIter iter;
    333   GtkMenu *menu;
    334 
    335   if ((GDK_BUTTON_PRESS != event->type) ||
    336       (3 != event_button->button))
    337     return FALSE; /* not a right-click */
    338   if (! gtk_tree_view_get_path_at_pos (tv,
    339                                        event_button->x,
    340                                        event_button->y,
    341                                        &path,
    342                                        NULL,
    343                                        NULL,
    344                                        NULL))
    345   {
    346     menu = get_popup (NULL,
    347                       NULL);
    348   }
    349   else
    350   {
    351     tm = gtk_tree_view_get_model (tv);
    352     if (! gtk_tree_model_get_iter (tm,
    353                                    &iter,
    354                                    path))
    355     {
    356       /* not sure how we got a path but no iter... */
    357       GNUNET_break (0);
    358       return FALSE;
    359     }
    360     gtk_tree_path_free (path);
    361 
    362     menu = get_popup (tm,
    363                       &iter);
    364   }
    365   if (NULL == menu)
    366   {
    367     GNUNET_break (0);
    368     return FALSE;
    369   }
    370   gtk_menu_popup_at_pointer (menu,
    371                              event);
    372   return FALSE;
    373 }