[evince] Allow adding Highlight annotations from text selection



commit fc0d21167185b34955f4996b35b0c479e0d482f3
Author: Nelson Benítez León <nbenitezl+gnome gmail com>
Date:   Fri Dec 8 16:31:36 2017 +0500

    Allow adding Highlight annotations from text selection
    
    As this is a natural, intuitive way to add text markup
    annotations to a document.
    
    The "Highlight Selected Text" action
    in the context menu
    will show if there is a selection. When
    the selection spreads over several pages,
    one annotation per page will be added accordingly
    to fulfill the user expectation of all selected text
    to be annotated.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763943

 libview/ev-view.c     |  107 ++++++++++++++++++++++++++++++++++++++++---------
 libview/ev-view.h     |    1 +
 shell/ev-window.c     |   30 ++++++++++++++
 shell/evince-menus.ui |    5 ++
 4 files changed, 124 insertions(+), 19 deletions(-)
---
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 0156c30..702fa83 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -163,6 +163,8 @@ static void          show_annotation_windows                 (EvView
                                                              gint                page);
 static void          hide_annotation_windows                 (EvView             *view,
                                                              gint                page);
+static void         ev_view_create_annotation_from_selection (EvView          *view,
+                                                              EvViewSelection *selection);
 /*** GtkWidget implementation ***/
 static void       ev_view_size_request_continuous_dual_page  (EvView             *view,
                                                              GtkRequisition     *requisition);
@@ -3325,33 +3327,18 @@ ev_view_handle_annotation (EvView       *view,
 }
 
 static void
-ev_view_create_annotation (EvView *view)
+ev_view_create_annotation_real (EvView *view,
+                               gint    annot_page,
+                               EvPoint start,
+                               EvPoint end)
 {
        EvAnnotation   *annot;
-       EvPoint         start;
-       EvPoint         end;
-       gint            annot_page;
-       gint            offset;
-       GdkRectangle    page_area;
-       GtkBorder       border;
        EvRectangle     doc_rect, popup_rect;
        EvPage         *page;
        GdkColor        color = { 0, 65535, 65535, 0 };
        GdkRectangle    view_rect;
        cairo_region_t *region;
 
-       find_page_at_location (view, view->adding_annot_info.start.x, view->adding_annot_info.start.y, 
&annot_page, &offset, &offset);
-       if (annot_page == -1) {
-               ev_view_cancel_add_annotation (view);
-               return;
-       }
-
-       ev_view_get_page_extents (view, annot_page, &page_area, &border);
-       _ev_view_transform_view_point_to_doc_point (view, &view->adding_annot_info.start, &page_area, &border,
-                                                   &start.x, &start.y);
-       _ev_view_transform_view_point_to_doc_point (view, &view->adding_annot_info.stop, &page_area, &border,
-                                                   &end.x, &end.y);
-
        ev_document_doc_mutex_lock ();
        page = ev_document_get_page (view->document, annot_page);
         switch (view->adding_annot_info.type) {
@@ -3415,6 +3402,45 @@ ev_view_create_annotation (EvView *view)
        view->adding_annot_info.annot = annot;
 }
 
+static void
+ev_view_create_annotation (EvView *view)
+{
+       EvPoint         start;
+       EvPoint         end;
+       gint            annot_page;
+       gint            offset;
+       GdkRectangle    page_area;
+       GtkBorder       border;
+
+       find_page_at_location (view, view->adding_annot_info.start.x, view->adding_annot_info.start.y, 
&annot_page, &offset, &offset);
+       if (annot_page == -1) {
+               ev_view_cancel_add_annotation (view);
+               return;
+       }
+
+       ev_view_get_page_extents (view, annot_page, &page_area, &border);
+       _ev_view_transform_view_point_to_doc_point (view, &view->adding_annot_info.start, &page_area, &border,
+                                                   &start.x, &start.y);
+       _ev_view_transform_view_point_to_doc_point (view, &view->adding_annot_info.stop, &page_area, &border,
+                                                   &end.x, &end.y);
+
+       ev_view_create_annotation_real (view, annot_page, start, end);
+}
+
+static void
+ev_view_create_annotation_from_selection (EvView          *view,
+                                         EvViewSelection *selection)
+{
+       EvPoint doc_point_start;
+       EvPoint doc_point_end;
+
+       doc_point_start.x = selection->rect.x1;
+       doc_point_start.y = selection->rect.y1;
+       doc_point_end.x = selection->rect.x2;
+       doc_point_end.y = selection->rect.y2;
+
+       ev_view_create_annotation_real (view, selection->page, doc_point_start, doc_point_end);
+}
 void
 ev_view_focus_annotation (EvView    *view,
                          EvMapping *annot_mapping)
@@ -5631,6 +5657,49 @@ ev_view_motion_notify_event (GtkWidget      *widget,
        return FALSE;
 }
 
+/**
+ * ev_view_add_text_markup_annotation_for_selected_text:
+ * @view: #EvView instance
+ *
+ * Adds a Text Markup annotation (defaulting to a 'highlight' one) to
+ * the currently selected text on the document.
+ *
+ * When the selected text spans more than one page, it will add a
+ * corresponding annotation for each page that contains selected text.
+ *
+ * Returns: %TRUE if annotations were added successfully, %FALSE otherwise.
+ *
+ * Since: 3.28
+ */
+gboolean
+ev_view_add_text_markup_annotation_for_selected_text (EvView  *view)
+{
+       GList *l;
+
+       if (view->adding_annot_info.annot || view->adding_annot_info.adding_annot ||
+           view->selection_info.selections == NULL)
+               return FALSE;
+
+       for (l = view->selection_info.selections; l != NULL; l = l->next) {
+               EvViewSelection *selection = (EvViewSelection *)l->data;
+
+               view->adding_annot_info.adding_annot = TRUE;
+               view->adding_annot_info.type = EV_ANNOTATION_TYPE_TEXT_MARKUP;
+
+               ev_view_create_annotation_from_selection (view, selection);
+
+               if (view->adding_annot_info.adding_annot)
+                       g_signal_emit (view, signals[SIGNAL_ANNOT_ADDED], 0, view->adding_annot_info.annot);
+       }
+
+       clear_selection (view);
+
+       view->adding_annot_info.adding_annot = FALSE;
+       view->adding_annot_info.annot = NULL;
+
+       return TRUE;
+}
+
 static gboolean
 ev_view_button_release_event (GtkWidget      *widget,
                              GdkEventButton *event)
diff --git a/libview/ev-view.h b/libview/ev-view.h
index cd3ddf6..e2a243f 100644
--- a/libview/ev-view.h
+++ b/libview/ev-view.h
@@ -125,6 +125,7 @@ void           ev_view_begin_add_annotation  (EvView          *view,
 void           ev_view_cancel_add_annotation (EvView          *view);
 void           ev_view_remove_annotation     (EvView          *view,
                                              EvAnnotation    *annot);
+gboolean       ev_view_add_text_markup_annotation_for_selected_text (EvView  *view);
 
 /* Caret navigation */
 gboolean       ev_view_supports_caret_navigation    (EvView  *view);
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 8ed743b..21aff4e 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -332,6 +332,9 @@ static void     ev_window_popup_cmd_open_link_new_window(GSimpleAction    *actio
 static void     ev_window_popup_cmd_copy_link_address   (GSimpleAction    *action,
                                                         GVariant         *parameter,
                                                         gpointer          user_data);
+static void     ev_window_popup_cmd_annotate_selected_text (GSimpleAction    *action,
+                                                           GVariant         *parameter,
+                                                           gpointer          user_data);
 static void     ev_window_popup_cmd_save_image_as       (GSimpleAction    *action,
                                                         GVariant         *parameter,
                                                         gpointer          user_data);
@@ -548,6 +551,7 @@ ev_window_update_actions_sensitivity (EvWindow *ev_window)
        ev_window_set_action_enabled (ev_window, "open-menu", !recent_view_mode);
 
        /* Same for popups specific actions */
+       ev_window_set_action_enabled (ev_window, "annotate-selected-text", !recent_view_mode);
        ev_window_set_action_enabled (ev_window, "open-link", !recent_view_mode);
        ev_window_set_action_enabled (ev_window, "open-link-new-window", !recent_view_mode);
        ev_window_set_action_enabled (ev_window, "go-to-link", !recent_view_mode);
@@ -5068,6 +5072,16 @@ view_menu_annot_popup (EvWindow     *ev_window,
        g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_attachment);
 }
 
+static void
+view_menu_text_selection_popup (EvWindow *ev_window,
+                               gboolean  enable)
+{
+       GAction *action;
+
+       action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "annotate-selected-text");
+       g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enable);
+}
+
 static gboolean
 view_menu_popup_cb (EvView   *view,
                    GList    *items,
@@ -5077,6 +5091,7 @@ view_menu_popup_cb (EvView   *view,
        gboolean has_link = FALSE;
        gboolean has_image = FALSE;
        gboolean has_annot = FALSE;
+       gboolean can_annotate;
 
        for (l = items; l; l = g_list_next (l)) {
                if (EV_IS_LINK (l->data)) {
@@ -5098,6 +5113,10 @@ view_menu_popup_cb (EvView   *view,
        if (!has_annot)
                view_menu_annot_popup (ev_window, NULL);
 
+       can_annotate = !has_annot && ev_view_get_has_selection (view);
+
+       view_menu_text_selection_popup (ev_window, can_annotate);
+
        if (!ev_window->priv->view_popup) {
                ev_window->priv->view_popup = gtk_menu_new_from_model (ev_window->priv->view_popup_menu);
                gtk_menu_attach_to_widget (GTK_MENU (ev_window->priv->view_popup),
@@ -5738,6 +5757,7 @@ static const GActionEntry actions[] = {
        { "caret-navigation", NULL, NULL, "false", ev_window_cmd_view_toggle_caret_navigation },
        { "toggle-edit-annots", NULL, NULL, "false", ev_window_cmd_toggle_edit_annots },
        /* Popups specific items */
+       { "annotate-selected-text", ev_window_popup_cmd_annotate_selected_text },
        { "open-link", ev_window_popup_cmd_open_link },
        { "open-link-new-window", ev_window_popup_cmd_open_link_new_window },
        { "go-to-link", ev_window_popup_cmd_open_link },
@@ -6116,6 +6136,16 @@ ev_window_popup_cmd_open_link (GSimpleAction *action,
 }
 
 static void
+ev_window_popup_cmd_annotate_selected_text (GSimpleAction *action,
+                                           GVariant      *parameter,
+                                           gpointer       user_data)
+{
+       EvWindow *ev_window = user_data;
+       EvView *view = EV_VIEW (ev_window->priv->view);
+       ev_view_add_text_markup_annotation_for_selected_text (view);
+}
+
+static void
 ev_window_popup_cmd_open_link_new_window (GSimpleAction *action,
                                          GVariant      *parameter,
                                          gpointer       user_data)
diff --git a/shell/evince-menus.ui b/shell/evince-menus.ui
index 6100777..e9b01d5 100644
--- a/shell/evince-menus.ui
+++ b/shell/evince-menus.ui
@@ -297,6 +297,11 @@
         <attribute name='hidden-when'>action-disabled</attribute>
       </item>
       <item>
+        <attribute name="label" translatable="yes">Highlight Selected Text</attribute>
+        <attribute name="action">win.annotate-selected-text</attribute>
+        <attribute name='hidden-when'>action-disabled</attribute>
+      </item>
+      <item>
         <attribute name="label" translatable="yes">Open Containing _Folder</attribute>
         <attribute name="action">win.open-containing-folder</attribute>
       </item>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]