[epiphany/wip/search-engine-dialog: 1/4] Restore smart bookmarks



commit 25a9993182d91fc8b50d0243e5e551e045c74b5d
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Mon Oct 31 16:21:03 2016 -0500

    Restore smart bookmarks
    
    It works exactly the same as before. If the bookmark includes %s, add it
    to the completion model.

 src/bookmarks/ephy-bookmark.c          |   35 +++++++++
 src/bookmarks/ephy-bookmark.h          |    4 +
 src/bookmarks/ephy-bookmarks-manager.c |   33 ++++++++
 src/bookmarks/ephy-bookmarks-manager.h |    1 +
 src/ephy-completion-model.c            |    5 +-
 src/ephy-location-controller.c         |  131 +++++++++++++++++++++++++++++++-
 6 files changed, 204 insertions(+), 5 deletions(-)
---
diff --git a/src/bookmarks/ephy-bookmark.c b/src/bookmarks/ephy-bookmark.c
index 96ddd6d..ffe12fb 100644
--- a/src/bookmarks/ephy-bookmark.c
+++ b/src/bookmarks/ephy-bookmark.c
@@ -586,3 +586,38 @@ out:
 
   return bookmark;
 }
+
+gboolean
+ephy_bookmark_is_smart (EphyBookmark *bookmark)
+{
+  g_return_val_if_fail (EPHY_IS_BOOKMARK (bookmark), FALSE);
+
+  return !!strstr (bookmark->url, "%s");
+}
+
+char *
+ephy_bookmark_resolve_smart_url (EphyBookmark *bookmark,
+                                 const char   *search_term)
+{
+  GString *url;
+  const char *original_url;
+  char *result;
+  gssize pos;
+
+  g_return_val_if_fail (EPHY_IS_BOOKMARK (bookmark), FALSE);
+  g_return_val_if_fail (ephy_bookmark_is_smart (bookmark), FALSE);
+  g_return_val_if_fail (search_term != NULL, FALSE);
+  g_return_val_if_fail (search_term[0] != '\0', FALSE);
+
+  original_url = ephy_bookmark_get_url (bookmark);
+  url = g_string_new (original_url);
+  pos = (gssize)(strstr (original_url, "%s") - original_url);
+  g_assert (pos > 0);
+
+  g_string_erase (url, pos, 2);
+  g_string_insert (url, pos, search_term);
+
+  result = url->str;
+  g_string_free (url, FALSE);
+  return result;
+}
diff --git a/src/bookmarks/ephy-bookmark.h b/src/bookmarks/ephy-bookmark.h
index e945820..cc7be4a 100644
--- a/src/bookmarks/ephy-bookmark.h
+++ b/src/bookmarks/ephy-bookmark.h
@@ -73,4 +73,8 @@ int                  ephy_bookmark_tags_compare          (const char *tag1,
 char                *ephy_bookmark_to_bso                (EphyBookmark *self);
 EphyBookmark        *ephy_bookmark_from_bso              (JsonObject *bso);
 
+gboolean             ephy_bookmark_is_smart              (EphyBookmark *self);
+char                *ephy_bookmark_resolve_smart_url     (EphyBookmark *self,
+                                                          const char   *search_term);
+
 G_END_DECLS
diff --git a/src/bookmarks/ephy-bookmarks-manager.c b/src/bookmarks/ephy-bookmarks-manager.c
index 7a4702d..c2a503e 100644
--- a/src/bookmarks/ephy-bookmarks-manager.c
+++ b/src/bookmarks/ephy-bookmarks-manager.c
@@ -487,6 +487,39 @@ ephy_bookmarks_manager_get_bookmarks_with_tag (EphyBookmarksManager *self,
   return bookmarks;
 }
 
+static int
+compare_smart_bookmarks (EphyBookmark *a,
+                         EphyBookmark *b)
+{
+  return g_utf8_collate (ephy_bookmark_get_title (a), ephy_bookmark_get_title (b));
+}
+
+GSequence *
+ephy_bookmarks_manager_get_smart_bookmarks (EphyBookmarksManager *self)
+{
+  GSequence *bookmarks;
+  GSequenceIter *iter;
+
+  g_return_val_if_fail (EPHY_IS_BOOKMARKS_MANAGER (self), NULL);
+
+  bookmarks = g_sequence_new (g_object_unref);
+
+  for (iter = g_sequence_get_begin_iter (self->bookmarks);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter)) {
+    EphyBookmark *bookmark = g_sequence_get (iter);
+
+    if (ephy_bookmark_is_smart (bookmark)) {
+      g_sequence_insert_sorted (bookmarks,
+                                bookmark,
+                                (GCompareDataFunc)compare_smart_bookmarks,
+                                NULL);
+    }
+  }
+
+  return bookmarks;
+}
+
 GSequence *
 ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self)
 {
diff --git a/src/bookmarks/ephy-bookmarks-manager.h b/src/bookmarks/ephy-bookmarks-manager.h
index 4d2a59c..b419235 100644
--- a/src/bookmarks/ephy-bookmarks-manager.h
+++ b/src/bookmarks/ephy-bookmarks-manager.h
@@ -51,6 +51,7 @@ gboolean     ephy_bookmarks_manager_tag_exists                    (EphyBookmarks
 GSequence   *ephy_bookmarks_manager_get_bookmarks                 (EphyBookmarksManager *self);
 GSequence   *ephy_bookmarks_manager_get_bookmarks_with_tag        (EphyBookmarksManager *self,
                                                                    const char           *tag);
+GSequence   *ephy_bookmarks_manager_get_smart_bookmarks           (EphyBookmarksManager *self);
 GSequence   *ephy_bookmarks_manager_get_tags                      (EphyBookmarksManager *self);
 
 void        ephy_bookmarks_manager_save_to_file_async             (EphyBookmarksManager *self,
diff --git a/src/ephy-completion-model.c b/src/ephy-completion-model.c
index f22a645..8459ef0 100644
--- a/src/ephy-completion-model.c
+++ b/src/ephy-completion-model.c
@@ -429,9 +429,10 @@ query_completed_cb (EphyHistoryService *service,
     url = ephy_bookmark_get_url (bookmark);
     title = ephy_bookmark_get_title (bookmark);
 
-    if (should_add_bookmark_to_model (model, user_data->search_string,
-                                      title, url))
+    if (!ephy_bookmark_is_smart (bookmark) &&
+        should_add_bookmark_to_model (model, user_data->search_string, title, url)) {
       list = add_to_potential_rows (list, title, url, NULL, 0, TRUE, FALSE);
+    }
   }
 
   /* History */
diff --git a/src/ephy-location-controller.c b/src/ephy-location-controller.c
index ba0cb4b..ea46e54 100644
--- a/src/ephy-location-controller.c
+++ b/src/ephy-location-controller.c
@@ -22,16 +22,18 @@
 #include "config.h"
 #include "ephy-location-controller.h"
 
-#include "ephy-widgets-type-builtins.h"
+#include "ephy-bookmark.h"
+#include "ephy-bookmarks-manager.h"
 #include "ephy-completion-model.h"
 #include "ephy-debug.h"
+#include "ephy-dnd.h"
 #include "ephy-embed-container.h"
 #include "ephy-embed-utils.h"
 #include "ephy-link.h"
 #include "ephy-location-entry.h"
-#include "ephy-dnd.h"
 #include "ephy-shell.h"
 #include "ephy-title-widget.h"
+#include "ephy-widgets-type-builtins.h"
 
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
@@ -49,6 +51,8 @@ struct _EphyLocationController {
 
   EphyWindow *window;
   EphyTitleWidget *title_widget;
+  EphyBookmarksManager *bookmarks_manager;
+  GSequence *smart_bookmarks;
   char *address;
   guint editable : 1;
   gboolean sync_address_is_blocked;
@@ -86,6 +90,35 @@ match_func (GtkEntryCompletion *completion,
 }
 
 static void
+action_activated_cb (GtkEntryCompletion     *completion,
+                     int                     index,
+                     EphyLocationController *controller)
+{
+  GtkWidget *entry;
+  char *content;
+  char *url;
+  GSequenceIter *iter;
+  EphyBookmark *bookmark;
+
+  entry = gtk_entry_completion_get_entry (completion);
+  content = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+
+  if (content == NULL)
+    return;
+
+  iter = g_sequence_get_iter_at_pos (controller->smart_bookmarks, index);
+  g_assert (!g_sequence_iter_is_end (iter));
+  bookmark = g_sequence_get (iter);
+  url = ephy_bookmark_resolve_smart_url (bookmark, content);
+
+  ephy_link_open (EPHY_LINK (controller), url, NULL,
+                  ephy_link_flags_from_current_event () | EPHY_LINK_TYPED);
+
+  g_free (content);
+  g_free (url);
+}
+
+static void
 entry_drag_data_received_cb (GtkWidget *widget,
                              GdkDragContext *context,
                              gint x, gint y,
@@ -148,9 +181,11 @@ entry_activate_cb (GtkEntry               *entry,
   }
 
   content = gtk_entry_get_text (entry);
-  if (content == NULL || content[0] == '\0') return;
+  if (content == NULL || content[0] == '\0')
+    return;
 
   address = g_strdup (content);
+
   effective_address = ephy_embed_utils_normalize_or_autosearch_address (g_strstrip (address));
   g_free (address);
 #if 0
@@ -242,6 +277,84 @@ get_title_cb (EphyLocationEntry      *entry,
   return g_strdup (ephy_embed_get_title (embed));
 }
 
+static void
+remove_completion_actions (EphyLocationController *controller,
+                           EphyLocationEntry      *lentry)
+{
+  GtkEntryCompletion *completion;
+  gint num_actions;
+
+  completion = gtk_entry_get_completion (GTK_ENTRY (lentry));
+  num_actions = g_sequence_get_length (controller->smart_bookmarks);
+
+  for (int i = 0; i < num_actions; i++)
+    gtk_entry_completion_delete_action (completion, 0);
+
+  g_signal_handlers_disconnect_by_func (completion,
+                                        G_CALLBACK (action_activated_cb),
+                                        controller);
+}
+
+static void
+refresh_smart_bookmarks (EphyLocationController *controller)
+{
+  if (controller->smart_bookmarks != NULL)
+    g_sequence_free (controller->smart_bookmarks);
+
+  controller->smart_bookmarks = ephy_bookmarks_manager_get_smart_bookmarks (controller->bookmarks_manager);
+}
+
+static void
+add_completion_actions (EphyLocationController *controller,
+                        EphyLocationEntry      *lentry)
+{
+  GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (lentry));
+  GSequenceIter *iter;
+  int i = 0;
+
+  for (iter = g_sequence_get_begin_iter (controller->smart_bookmarks);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter), i++) {
+    EphyBookmark *bookmark;
+    const char *title;
+
+    bookmark = g_sequence_get (iter);
+    title = ephy_bookmark_get_title (bookmark);
+    gtk_entry_completion_insert_action_text (completion, i, title);
+  }
+
+  g_signal_connect (completion, "action_activated",
+                    G_CALLBACK (action_activated_cb), controller);
+}
+
+static void
+update_actions_list (EphyLocationController *controller)
+{
+  g_assert (EPHY_IS_LOCATION_ENTRY (controller->title_widget));
+
+  remove_completion_actions (controller, EPHY_LOCATION_ENTRY (controller->title_widget));
+  refresh_smart_bookmarks (controller);
+  add_completion_actions (controller, EPHY_LOCATION_ENTRY (controller->title_widget));
+}
+
+static void
+bookmark_added_cb (EphyBookmarksManager   *manager,
+                   EphyBookmark           *bookmark,
+                   EphyLocationController *controller)
+{
+  if (ephy_bookmark_is_smart (bookmark))
+    update_actions_list (controller);
+}
+
+static void
+bookmark_removed_cb (EphyBookmarksManager   *manager,
+                     EphyBookmark           *bookmark,
+                     EphyLocationController *controller)
+{
+  if (ephy_bookmark_is_smart (bookmark))
+    update_actions_list (controller);
+}
+
 static gboolean
 focus_in_event_cb (GtkWidget              *entry,
                    GdkEventFocus          *event,
@@ -323,6 +436,16 @@ ephy_location_controller_constructed (GObject *object)
                                       controller->title_widget,
                                       NULL);
 
+  refresh_smart_bookmarks (controller);
+  add_completion_actions (controller, EPHY_LOCATION_ENTRY (controller->title_widget));
+
+  /* FIXME: This is not enough. We miss when an existing bookmark is edited.
+   * Need to add a bookmark-modified signal to EphyBookmarksManager. */
+  g_signal_connect_object (controller->bookmarks_manager, "bookmark-added",
+                           G_CALLBACK (bookmark_added_cb), controller, 0);
+  g_signal_connect_object (controller->bookmarks_manager, "bookmark-removed",
+                           G_CALLBACK (bookmark_removed_cb), controller, 0);
+
   g_object_bind_property (controller, "editable",
                           controller->title_widget, "editable",
                           G_BINDING_SYNC_CREATE);
@@ -484,6 +607,7 @@ ephy_location_controller_init (EphyLocationController *controller)
 {
   controller->address = g_strdup ("");
   controller->editable = TRUE;
+  controller->bookmarks_manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
   controller->sync_address_is_blocked = FALSE;
 }
 
@@ -492,6 +616,7 @@ ephy_location_controller_finalize (GObject *object)
 {
   EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object);
 
+  g_sequence_free (controller->smart_bookmarks);
   g_free (controller->address);
 
   G_OBJECT_CLASS (ephy_location_controller_parent_class)->finalize (object);


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