diff --git a/midori/midori-locationaction.c b/midori/midori-locationaction.c index 90d1ae46..a0940758 100644 --- a/midori/midori-locationaction.c +++ b/midori/midori-locationaction.c @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Christian Dywan + Copyright (C) 2008 Dale Whittaker This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -12,10 +13,14 @@ #include "midori-locationaction.h" #include "gtkiconentry.h" +#include "sokoke.h" +#include #include #include +#define MAX_ITEMS 25 + struct _MidoriLocationAction { GtkAction parent_instance; @@ -24,6 +29,9 @@ struct _MidoriLocationAction gdouble progress; GtkTreeModel* model; + GtkTreeModel* filter_model; + GtkTreeModel* sort_model; + GdkPixbuf* default_icon; }; struct _MidoriLocationActionClass @@ -53,6 +61,16 @@ enum static guint signals[LAST_SIGNAL]; +enum +{ + FAVICON_COL, + URI_COL, + TITLE_COL, + VISITS_COL, + VISIBLE_COL, + N_COLS +}; + static void midori_location_action_finalize (GObject* object); @@ -199,10 +217,27 @@ midori_location_action_class_init (MidoriLocationActionClass* class) static void midori_location_action_init (MidoriLocationAction* location_action) { + GtkTreeModel* liststore; + GtkTreeModel* sort_model; + GtkTreeModel* filter_model; + location_action->uri = NULL; location_action->progress = 0.0; - location_action->model = NULL; + liststore = (GtkTreeModel*)gtk_list_store_new (N_COLS, + GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INT, G_TYPE_BOOLEAN); + sort_model = (GtkTreeModel*)gtk_tree_model_sort_new_with_model (liststore); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), + VISITS_COL, GTK_SORT_DESCENDING); + filter_model = gtk_tree_model_filter_new (sort_model, NULL); + gtk_tree_model_filter_set_visible_column ( + GTK_TREE_MODEL_FILTER (filter_model), VISIBLE_COL); + + location_action->model = liststore; + location_action->filter_model = filter_model; + location_action->sort_model = sort_model; + location_action->default_icon = NULL; } static void @@ -210,9 +245,12 @@ midori_location_action_finalize (GObject* object) { MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (object); - g_free (location_action->uri); + katze_assign (location_action->uri, NULL); katze_object_assign (location_action->model, NULL); + katze_object_assign (location_action->sort_model, NULL); + katze_object_assign (location_action->filter_model, NULL); + katze_object_assign (location_action->default_icon, NULL); G_OBJECT_CLASS (midori_location_action_parent_class)->finalize (object); } @@ -228,17 +266,13 @@ midori_location_action_set_property (GObject* object, switch (prop_id) { case PROP_PROGRESS: - { midori_location_action_set_progress (location_action, g_value_get_double (value)); break; - } case PROP_SECONDARY_ICON: - { midori_location_action_set_secondary_icon (location_action, g_value_get_string (value)); break; - } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -276,20 +310,16 @@ static GtkWidget* midori_location_action_create_tool_item (GtkAction* action) { GtkWidget* toolitem; - GtkWidget* entry; + GtkWidget* location_entry; GtkWidget* alignment; toolitem = GTK_WIDGET (gtk_tool_item_new ()); gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE); - entry = midori_location_entry_new (); - midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry), - MIDORI_LOCATION_ACTION (action)->progress); - gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY ( - gtk_bin_get_child (GTK_BIN (entry))), - GTK_ICON_ENTRY_SECONDARY, TRUE); + location_entry = midori_location_entry_new (); + alignment = gtk_alignment_new (0, 0.5, 1, 0.1); - gtk_container_add (GTK_CONTAINER (alignment), entry); - gtk_widget_show (entry); + gtk_container_add (GTK_CONTAINER (alignment), location_entry); + gtk_widget_show (location_entry); gtk_container_add (GTK_CONTAINER (toolitem), alignment); gtk_widget_show (alignment); @@ -297,15 +327,17 @@ midori_location_action_create_tool_item (GtkAction* action) } static void -midori_location_action_active_changed_cb (GtkWidget* widget, +midori_location_action_active_changed_cb (GtkWidget* location_entry, gint active, GtkAction* action) { MidoriLocationAction* location_action; + GtkWidget* entry; const gchar* text; location_action = MIDORI_LOCATION_ACTION (action); - text = midori_location_entry_get_text (MIDORI_LOCATION_ENTRY (widget)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); + text = gtk_entry_get_text (GTK_ENTRY (entry)); katze_assign (location_action->uri, g_strdup (text)); g_signal_emit (action, signals[ACTIVE_CHANGED], 0, active); @@ -359,6 +391,397 @@ midori_location_action_icon_released_cb (GtkWidget* widget, g_signal_emit (action, signals[SECONDARY_ICON_RELEASED], 0, widget); } +static void +midori_location_entry_render_pixbuf_cb (GtkCellLayout* layout, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + gpointer data) +{ + GdkPixbuf* pixbuf; + + gtk_tree_model_get (model, iter, FAVICON_COL, &pixbuf, -1); + if (pixbuf) + { + g_object_set (renderer, "pixbuf", pixbuf, "yalign", 0.25, NULL); + g_object_unref (pixbuf); + } +} + +static void +midori_location_entry_render_text_cb (GtkCellLayout* layout, + GtkCellRenderer* renderer, + GtkTreeModel* model, + GtkTreeIter* iter, + gpointer data) +{ + gchar* uri; + gchar* title; + gchar* desc; + gchar* desc_uri; + gchar* desc_title; + GtkWidget* entry; + gchar* key; + gchar* temp; + gchar** parts; + + gtk_tree_model_get (model, iter, URI_COL, &uri, TITLE_COL, &title, -1); + + desc_uri = desc_title = key = NULL; + if (data) + { + entry = gtk_entry_completion_get_entry (GTK_ENTRY_COMPLETION (data)); + key = g_utf8_strdown (gtk_entry_get_text (GTK_ENTRY (entry)), -1); + } + if (data && uri) + { + temp = g_utf8_strdown (uri, -1); + parts = g_strsplit (temp, key, 2); + g_free (temp); + if (parts && parts[0] && parts[1]) + desc_uri = g_markup_printf_escaped ("%s%s%s", + parts[0], key, parts[1]); + g_strfreev (parts); + } + if (uri && !desc_uri) + desc_uri = g_markup_escape_text (uri, -1); + if (data && title) + { + temp = g_utf8_strdown (title, -1); + parts = g_strsplit (temp, key, 2); + g_free (temp); + if (parts && parts[0] && parts[1]) + desc_title = g_markup_printf_escaped ("%s%s%s", + parts[0], key, parts[1]); + g_strfreev (parts); + } + if (title && !desc_title) + desc_title = g_markup_escape_text (title, -1); + + if (desc_title) + desc = g_strdup_printf ("%s\n%s", + desc_title, desc_uri); + else + desc = g_strdup_printf ("%s", desc_uri); + + g_object_set (renderer, "markup", desc, + "ellipsize-set", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + + g_free (uri); + g_free (title); + g_free (key); + g_free (desc); + g_free (desc_uri); + g_free (desc_title); +} + +static gboolean +midori_location_entry_completion_match_cb (GtkEntryCompletion* completion, + const gchar* key, + GtkTreeIter* iter, + gpointer data) +{ + GtkTreeModel* model; + gchar* uri; + gchar* title; + gboolean match; + gchar* temp; + + model = gtk_entry_completion_get_model (completion); + gtk_tree_model_get (model, iter, URI_COL, &uri, TITLE_COL, &title, -1); + + match = FALSE; + if (uri) + { + temp = g_utf8_casefold (uri, -1); + match = (strstr (temp, key) != NULL); + g_free (temp); + g_free (uri); + + if (!match && title) + { + temp = g_utf8_casefold (title, -1); + match = (strstr (temp, key) != NULL); + g_free (temp); + g_free (title); + } + } + + return match; +} + +static void +midori_location_action_set_item (MidoriLocationAction* location_action, + GtkTreeIter* iter, + MidoriLocationEntryItem* item) +{ + GtkTreeModel* model; + GdkPixbuf* icon; + GdkPixbuf* new_icon; + + model = location_action->model; + gtk_list_store_set (GTK_LIST_STORE (model), iter, + URI_COL, item->uri, TITLE_COL, item->title, -1); + + gtk_tree_model_get (model, iter, FAVICON_COL, &icon, -1); + if (item->favicon) + new_icon = item->favicon; + else if (!icon && !item->favicon) + new_icon = location_action->default_icon; + else + new_icon = NULL; + if (new_icon) + gtk_list_store_set (GTK_LIST_STORE (model), iter, + FAVICON_COL, new_icon, -1); +} + +static gboolean +midori_location_action_child_iter_to_iter (MidoriLocationAction* location_action, + GtkTreeIter* iter, + GtkTreeIter* child_iter) +{ + GtkTreeModel* filter_model; + GtkTreeModel* sort_model; + GtkTreeIter sort_iter; + GtkTreeIter* temp_iter; + + temp_iter = child_iter; + + filter_model = location_action->filter_model; + sort_model = location_action->sort_model; + gtk_tree_model_sort_convert_child_iter_to_iter + (GTK_TREE_MODEL_SORT (sort_model), &sort_iter, child_iter); + temp_iter = &sort_iter; + + return gtk_tree_model_filter_convert_child_iter_to_iter + (GTK_TREE_MODEL_FILTER (filter_model), iter, temp_iter); +} + +static void +midori_location_action_set_active_iter (MidoriLocationAction* location_action, + GtkTreeIter* iter) +{ + GdkPixbuf* pixbuf; + GtkTreeModel* model; + GSList* proxies; + GtkWidget* alignment; + GtkWidget* location_entry; + GtkWidget* entry; + GtkTreeIter parent_iter; + + model = location_action->filter_model; + + /* The filter iter must be set, not the child iter, + * but the row must first be set as visible to + * convert to a filter iter without error. + */ + gtk_list_store_set (GTK_LIST_STORE (model), iter, VISIBLE_COL, TRUE, -1); + + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); + if (!proxies) + return; + + do + if (GTK_IS_TOOL_ITEM (proxies->data)) + { + alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); + location_entry = gtk_bin_get_child (GTK_BIN (alignment)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); + + if (midori_location_action_child_iter_to_iter ( + location_action, &parent_iter, iter)) + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (location_entry), + &parent_iter); + + /* When setting the active iter (when adding or setting an item) + * the icon may have changed, so we must update the entry icon. + */ + gtk_tree_model_get (model, iter, FAVICON_COL, &pixbuf, -1); + + gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, pixbuf); + g_object_unref (pixbuf); + } + while ((proxies = g_slist_next (proxies))); +} + +/** + * midori_location_action_item_iter: + * @location_action: a #MidoriLocationAction + * @uri: a string + * @iter: a GtkTreeIter + * + * Retrieves the iter of the item matching @uri. + * + * Return value: %TRUE if @uri was found, %FALSE otherwise + **/ +static gboolean +midori_location_action_item_iter (MidoriLocationAction* location_action, + const gchar* uri, + GtkTreeIter* iter) +{ + GtkTreeModel* model; + gchar* tmpuri; + gboolean found; + + g_return_val_if_fail (MIDORI_IS_LOCATION_ACTION (location_action), FALSE); + g_return_val_if_fail (uri != NULL, FALSE); + + found = FALSE; + model = location_action->model; // filter_model + if (gtk_tree_model_get_iter_first (model, iter)) + { + tmpuri = NULL; + do + { + gtk_tree_model_get (model, iter, URI_COL, &tmpuri, -1); + found = !g_ascii_strcasecmp (uri, tmpuri); + katze_assign (tmpuri, NULL); + + if (found) + break; + } + while (gtk_tree_model_iter_next (model, iter)); + } + return found; +} + +/** + * midori_location_action_reset: + * @location_action: a #MidoriLocationAction + * + * Clears the text in the entry and resets the icon. + **/ +static void +midori_location_action_reset (MidoriLocationAction* location_action) +{ + GSList* proxies; + GtkWidget* alignment; + GtkWidget* location_entry; + GtkWidget* entry; + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); + if (!proxies) + return; + + do + if (GTK_IS_TOOL_ITEM (proxies->data)) + { + alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); + location_entry = gtk_bin_get_child (GTK_BIN (alignment)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); + + gtk_entry_set_text (GTK_ENTRY (entry), ""); + gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, GTK_STOCK_FILE); + } + while ((proxies = g_slist_next (proxies))); +} + +/** + * midori_location_action_set_item_from_uri: + * @location_action: a #MidoriLocationAction + * @uri: a string + * + * Finds the item from the list matching @uri + * and sets it as the active item. + * If @uri is not found it clears the active item. + **/ +static void +midori_location_action_set_item_from_uri (MidoriLocationAction* location_action, + const gchar* uri) +{ + GtkTreeIter iter; + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + + if (midori_location_action_item_iter (location_action, uri, &iter)) + midori_location_action_set_active_iter (location_action, &iter); + else + midori_location_action_reset (location_action); + +} + +static gboolean +midori_location_entry_completion_selected (GtkEntryCompletion* completion, + GtkTreeModel* model, + GtkTreeIter* iter, + MidoriLocationAction* location_action) +{ + gchar* uri; + + gtk_tree_model_get (model, iter, URI_COL, &uri, -1); + midori_location_action_set_item_from_uri (location_action, uri); + g_free (uri); + + return FALSE; +} + +static void +midori_location_action_completion_init (MidoriLocationAction* location_action, + GtkWidget* location_entry) +{ + GtkWidget* entry; + GtkEntryCompletion* completion; + GtkCellRenderer* renderer; + + entry = gtk_bin_get_child (GTK_BIN (location_entry)); + completion = gtk_entry_completion_new (); + + gtk_entry_completion_set_model (completion, location_action->sort_model); + gtk_entry_completion_set_text_column (completion, URI_COL); + gtk_cell_layout_clear (GTK_CELL_LAYOUT (completion)); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, FALSE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer, + midori_location_entry_render_pixbuf_cb, + NULL, NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, TRUE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer, + midori_location_entry_render_text_cb, + completion, NULL); + gtk_entry_completion_set_match_func (completion, + midori_location_entry_completion_match_cb, NULL, NULL); + + gtk_entry_set_completion (GTK_ENTRY (entry), completion); + g_signal_connect (completion, "match-selected", + G_CALLBACK (midori_location_entry_completion_selected), location_entry); + + g_object_unref (completion); +} + +static void +midori_location_action_entry_changed_cb (GtkComboBox* combo_box, + MidoriLocationAction* location_action) +{ + GtkTreeIter iter; + GtkIconEntry* entry; + GtkTreeModel* model; + GdkPixbuf* pixbuf; + + if (gtk_combo_box_get_active_iter (combo_box, &iter)) + { + if ((entry = GTK_ICON_ENTRY (gtk_bin_get_child (GTK_BIN (combo_box))))) + { + pixbuf = NULL; + + model = location_action->filter_model; + gtk_tree_model_get (model, &iter, FAVICON_COL, &pixbuf, -1); + + gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, pixbuf); + g_object_unref (pixbuf); + + g_signal_emit (MIDORI_LOCATION_ENTRY (combo_box), + signals[ACTIVE_CHANGED], 0, gtk_combo_box_get_active (combo_box)); + } + } +} + static void midori_location_action_connect_proxy (GtkAction* action, GtkWidget* proxy) @@ -366,6 +789,7 @@ midori_location_action_connect_proxy (GtkAction* action, GtkWidget* alignment; GtkWidget* entry; MidoriLocationAction* location_action; + GtkCellRenderer* renderer; GTK_ACTION_CLASS (midori_location_action_parent_class)->connect_proxy ( action, proxy); @@ -376,14 +800,30 @@ midori_location_action_connect_proxy (GtkAction* action, entry = gtk_bin_get_child (GTK_BIN (alignment)); location_action = MIDORI_LOCATION_ACTION (action); - if (location_action->model) - gtk_combo_box_set_model (GTK_COMBO_BOX (entry), - location_action->model); - else - location_action->model = g_object_ref (gtk_combo_box_get_model ( - GTK_COMBO_BOX (entry))); + midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry), + MIDORI_LOCATION_ACTION (action)->progress); + gtk_combo_box_set_model (GTK_COMBO_BOX (entry), + MIDORI_LOCATION_ACTION (action)->filter_model); + gtk_combo_box_entry_set_text_column ( + GTK_COMBO_BOX_ENTRY (entry), URI_COL); + gtk_cell_layout_clear (GTK_CELL_LAYOUT (entry)); - g_signal_connect (entry, "active-changed", + /* Setup the renderer for the favicon */ + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry), renderer, FALSE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry), + renderer, midori_location_entry_render_pixbuf_cb, NULL, NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry), renderer, TRUE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry), + renderer, midori_location_entry_render_text_cb, NULL, NULL); + + gtk_combo_box_set_active (GTK_COMBO_BOX (entry), -1); + midori_location_action_completion_init (location_action, entry); + g_signal_connect (entry, "changed", + G_CALLBACK (midori_location_action_entry_changed_cb), action); + + g_signal_connect (location_action, "active-changed", G_CALLBACK (midori_location_action_active_changed_cb), action); g_object_connect (gtk_bin_get_child (GTK_BIN (entry)), "signal::key-press-event", @@ -416,18 +856,26 @@ midori_location_action_get_uri (MidoriLocationAction* location_action) return location_action->uri; } -void -midori_location_action_set_uri (MidoriLocationAction* location_action, - const gchar* uri) +/** + * midori_location_action_set_text: + * @location_action: a #MidoriLocationAction + * @text: a string + * + * Sets the entry text to @text and, if applicable, updates the icon. + **/ +static void +midori_location_action_set_text (MidoriLocationAction* location_action, + const gchar* text) { GSList* proxies; GtkWidget* alignment; + GtkWidget* location_entry; GtkWidget* entry; + GtkTreeIter iter; + GtkTreeModel* model; + GdkPixbuf* icon; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); - g_return_if_fail (uri != NULL); - - katze_assign (location_action->uri, g_strdup (uri)); proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); if (!proxies) @@ -437,20 +885,128 @@ midori_location_action_set_uri (MidoriLocationAction* location_action, if (GTK_IS_TOOL_ITEM (proxies->data)) { alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); + location_entry = gtk_bin_get_child (GTK_BIN (alignment)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); - midori_location_entry_set_text (MIDORI_LOCATION_ENTRY (entry), uri); + gtk_entry_set_text (GTK_ENTRY (entry), text); + if (midori_location_action_item_iter (location_action, text, &iter)) + { + model = location_action->model; // filter_model + gtk_tree_model_get (model, &iter, FAVICON_COL, &icon, -1); + gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, icon); + } + /* FIXME: Due to a bug in GtkIconEntry we can't reset the icon + else + gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, location_action->default_icon);*/ } while ((proxies = g_slist_next (proxies))); } +void +midori_location_action_set_uri (MidoriLocationAction* location_action, + const gchar* uri) +{ + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + g_return_if_fail (uri != NULL); + + katze_assign (location_action->uri, g_strdup (uri)); + + midori_location_action_set_text (location_action, uri); +} + +/** + * midori_location_action_prepend_item: + * @location_action: a #MidoriLocationAction + * @item: a MidoriLocationItem + * + * Prepends @item if it is not already in the list. + * If the item already exists, it is moved before the first item. + * If the maximum is reached, the last item is removed. + **/ +static void +midori_location_action_prepend_item (MidoriLocationAction* location_action, + MidoriLocationEntryItem* item) +{ + GtkTreeModel* filter_model; + GtkTreeModel* model; + GtkTreeIter iter; + GtkTreeIter index; + gint n; + gint visits = 0; + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + g_return_if_fail (item->uri != NULL); + + filter_model = location_action->filter_model; + model = location_action->model; + + if (midori_location_action_item_iter (location_action, item->uri, &iter)) + { + gtk_tree_model_get_iter_first (model, &index); + gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); + gtk_list_store_move_before (GTK_LIST_STORE (model), &iter, &index); + } + else + gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); + + n = gtk_tree_model_iter_n_children (filter_model, NULL); + if (n > MAX_ITEMS) + { + gtk_tree_model_iter_nth_child (model, &index, NULL, n - 1); + gtk_list_store_set (GTK_LIST_STORE (model), + &index, VISIBLE_COL, FALSE, -1); + } + + /* Only increment the visits when we add the uri */ + if (!item->title && !item->favicon) + gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISITS_COL, ++visits, + VISIBLE_COL, TRUE, -1); + midori_location_action_set_item (location_action, &iter, item); +} + +/** + * midori_location_entry_append_item: + * @location_entry: a #MidoriLocationEntry + * @item: a MidoriLocationItem + * + * Appends @item if it is not already in the list. + * @item is not added if the maximum is reached. + **/ +static void +midori_location_action_append_item (MidoriLocationAction* location_action, + MidoriLocationEntryItem* item) +{ + GtkTreeModel* model; + GtkTreeIter iter; + gint n; + gint visits = 0; + + g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); + g_return_if_fail (item->uri != NULL); + + model = location_action->model; + + if (!midori_location_action_item_iter (location_action, item->uri, &iter)) + { + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + n = gtk_tree_model_iter_n_children (model, NULL); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISIBLE_COL, + (n <= MAX_ITEMS), -1); + } + else + gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISITS_COL, ++visits, -1); + midori_location_action_set_item (location_action, &iter, item); +} + void midori_location_action_add_uri (MidoriLocationAction* location_action, const gchar* uri) { - GSList* proxies; - GtkWidget* alignment; - GtkWidget* entry; MidoriLocationEntryItem item; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); @@ -458,23 +1014,10 @@ midori_location_action_add_uri (MidoriLocationAction* location_action, katze_assign (location_action->uri, g_strdup (uri)); - proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); - if (!proxies) - return; - - do - if (GTK_IS_TOOL_ITEM (proxies->data)) - { - alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); - - item.favicon = NULL; - item.uri = uri; - item.title = NULL; - midori_location_entry_prepend_item ( - MIDORI_LOCATION_ENTRY (entry), &item); - } - while ((proxies = g_slist_next (proxies))); + item.favicon = NULL; + item.uri = uri; + item.title = NULL; + midori_location_action_prepend_item (location_action, &item); } void @@ -485,8 +1028,8 @@ midori_location_action_add_item (MidoriLocationAction* location_action, { GSList* proxies; GtkWidget* alignment; + GtkWidget* location_entry; GtkWidget* entry; - GtkWidget* child; MidoriLocationEntryItem item; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); @@ -496,25 +1039,25 @@ midori_location_action_add_item (MidoriLocationAction* location_action, katze_assign (location_action->uri, g_strdup (uri)); + item.favicon = icon; + item.uri = uri; + item.title = title; + midori_location_action_append_item (location_action, &item); + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); if (!proxies) return; do - if (GTK_IS_TOOL_ITEM (proxies->data)) + if (GTK_IS_TOOL_ITEM (proxies->data) && + !g_strcmp0 (location_action->uri, uri)) { alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); - child = gtk_bin_get_child (GTK_BIN (entry)); + location_entry = gtk_bin_get_child (GTK_BIN (alignment)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); - item.favicon = icon; - item.uri = uri; - item.title = title; - midori_location_entry_append_item ( - MIDORI_LOCATION_ENTRY (entry), &item); - if (!g_strcmp0 (location_action->uri, uri)) - gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (child), - GTK_ICON_ENTRY_PRIMARY, icon); + gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, icon); } while ((proxies = g_slist_next (proxies))); } @@ -526,33 +1069,33 @@ midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action, { GSList* proxies; GtkWidget* alignment; + GtkWidget* location_entry; GtkWidget* entry; - GtkWidget* child; MidoriLocationEntryItem item; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); g_return_if_fail (!icon || GDK_IS_PIXBUF (icon)); g_return_if_fail (uri != NULL); + item.favicon = icon; + item.uri = uri; + item.title = NULL; + midori_location_action_prepend_item (location_action, &item); + proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); if (!proxies) return; do - if (GTK_IS_TOOL_ITEM (proxies->data)) + if (GTK_IS_TOOL_ITEM (proxies->data) && + !g_strcmp0 (location_action->uri, uri)) { alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); - child = gtk_bin_get_child (GTK_BIN (entry)); + location_entry = gtk_bin_get_child (GTK_BIN (alignment)); + entry = gtk_bin_get_child (GTK_BIN (location_entry)); - item.favicon = icon; - item.uri = uri; - item.title = NULL; - midori_location_entry_prepend_item ( - MIDORI_LOCATION_ENTRY (entry), &item); - if (!g_strcmp0 (location_action->uri, uri)) - gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (child), - GTK_ICON_ENTRY_PRIMARY, icon); + gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_PRIMARY, icon); } while ((proxies = g_slist_next (proxies))); } @@ -562,32 +1105,16 @@ midori_location_action_set_title_for_uri (MidoriLocationAction* location_action, const gchar* title, const gchar* uri) { - GSList* proxies; - GtkWidget* alignment; - GtkWidget* entry; MidoriLocationEntryItem item; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); g_return_if_fail (title != NULL); g_return_if_fail (uri != NULL); - proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); - if (!proxies) - return; - - do - if (GTK_IS_TOOL_ITEM (proxies->data)) - { - alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); - - item.favicon = NULL; - item.uri = uri; - item.title = title; - midori_location_entry_prepend_item ( - MIDORI_LOCATION_ENTRY (entry), &item); - } - while ((proxies = g_slist_next (proxies))); + item.favicon = NULL; + item.uri = uri; + item.title = title; + midori_location_action_prepend_item (location_action, &item); } gdouble @@ -660,31 +1187,35 @@ midori_location_action_set_secondary_icon (MidoriLocationAction* location_action while ((proxies = g_slist_next (proxies))); } +/** + * midori_location_entry_set_item_from_uri: + * @location_entry: a #MidoriLocationEntry + * @uri: a string + * + * Finds the item from the list matching @uri + * and removes it if it is the last instance. + **/ void midori_location_action_delete_item_from_uri (MidoriLocationAction* location_action, const gchar* uri) { - GSList* proxies; - GtkWidget* alignment; - GtkWidget* entry; + GtkTreeModel* model; + GtkTreeIter iter; + gint visits; g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action)); g_return_if_fail (uri != NULL); - proxies = gtk_action_get_proxies (GTK_ACTION (location_action)); - if (!proxies) - return; - - do - if (GTK_IS_TOOL_ITEM (proxies->data)) + model = location_action->model; + if (midori_location_action_item_iter (location_action, uri, &iter)) { - alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); - entry = gtk_bin_get_child (GTK_BIN (alignment)); - - midori_location_entry_delete_item_from_uri - (MIDORI_LOCATION_ENTRY (entry), uri); + gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); + if (visits > 1) + gtk_list_store_set (GTK_LIST_STORE (model), + &iter, VISITS_COL, --visits, -1); + else + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); } - while ((proxies = g_slist_next (proxies))); } void @@ -706,7 +1237,7 @@ midori_location_action_clear (MidoriLocationAction* location_action) alignment = gtk_bin_get_child (GTK_BIN (proxies->data)); entry = gtk_bin_get_child (GTK_BIN (alignment)); - midori_location_entry_clear (MIDORI_LOCATION_ENTRY (entry)); + gtk_list_store_clear (GTK_LIST_STORE (location_action->filter_model)); } while ((proxies = g_slist_next (proxies))); } diff --git a/midori/midori-locationaction.h b/midori/midori-locationaction.h index 5a8f53de..a95301c9 100644 --- a/midori/midori-locationaction.h +++ b/midori/midori-locationaction.h @@ -34,6 +34,13 @@ G_BEGIN_DECLS typedef struct _MidoriLocationAction MidoriLocationAction; typedef struct _MidoriLocationActionClass MidoriLocationActionClass; +struct _MidoriLocationEntryItem +{ + GdkPixbuf* favicon; + const gchar* uri; + const gchar* title; +}; + GType midori_location_action_get_type (void); diff --git a/midori/midori-locationentry.c b/midori/midori-locationentry.c index 6170c8dd..1e9a4766 100644 --- a/midori/midori-locationentry.c +++ b/midori/midori-locationentry.c @@ -10,15 +10,10 @@ */ #include "midori-locationentry.h" + #include "gtkiconentry.h" #include "sokoke.h" - #include -#include - -#define DEFAULT_ICON GTK_STOCK_FILE -#define MAX_ITEMS 25 -/* #define ORDER_BY_VISITS 1 */ struct _MidoriLocationEntry { @@ -45,108 +40,15 @@ enum N_COLS }; -enum -{ - ACTIVE_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - static gboolean entry_key_press_event (GtkWidget* widget, GdkEventKey* event, MidoriLocationEntry* location_entry); -static void -midori_location_entry_changed (GtkComboBox* combo_box, - gpointer user_data); - static void midori_location_entry_class_init (MidoriLocationEntryClass* class) { - signals[ACTIVE_CHANGED] = g_signal_new ("active-changed", - G_TYPE_FROM_CLASS (class), - (GSignalFlags) (G_SIGNAL_RUN_LAST), - 0, - 0, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); -} -static GtkTreeModel* -midori_location_entry_get_filter_model (MidoriLocationEntry* location_entry) -{ - return gtk_combo_box_get_model (GTK_COMBO_BOX (location_entry)); -} - -static GtkTreeModel* -midori_location_entry_get_sort_model (MidoriLocationEntry* location_entry) -{ - GtkTreeModel* model; - GtkTreeModelFilter* filter_model; - - model = midori_location_entry_get_filter_model (location_entry); - filter_model = GTK_TREE_MODEL_FILTER (model); - g_assert (filter_model); - - return gtk_tree_model_filter_get_model (filter_model); -} - -static GtkTreeModel* -midori_location_entry_get_model (MidoriLocationEntry* location_entry) -{ - - GtkTreeModel* model; -#ifdef ORDER_BY_VISITS - GtkTreeModelSort* sort_model; -#endif - - model = midori_location_entry_get_sort_model (location_entry); - -#ifdef ORDER_BY_VISITS - sort_model = GTK_TREE_MODEL_SORT (model); - g_assert (sort_model); - - return gtk_tree_model_sort_get_model (sort_model); -#else - return GTK_IS_TREE_MODEL (model) ? model : NULL; -#endif - -} - -static gboolean -midori_location_entry_child_iter_to_iter (MidoriLocationEntry* location_entry, - GtkTreeIter* iter, - GtkTreeIter* child_iter) -{ - GtkTreeModel* filter_model; -#ifdef ORDER_BY_VISITS - GtkTreeModel* sort_model; - GtkTreeIter sort_iter; -#endif - GtkTreeIter* temp_iter; - - temp_iter = child_iter; - - filter_model = midori_location_entry_get_filter_model (location_entry); - -#ifdef ORDER_BY_VISITS - sort_model = midori_location_entry_get_sort_model (location_entry); - - g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter_model) && - GTK_IS_TREE_MODEL_SORT (sort_model), FALSE); - - gtk_tree_model_sort_convert_child_iter_to_iter - (GTK_TREE_MODEL_SORT (sort_model), &sort_iter, child_iter); - - temp_iter = &sort_iter; -#endif - - return gtk_tree_model_filter_convert_child_iter_to_iter - (GTK_TREE_MODEL_FILTER (filter_model), iter, temp_iter); } #define HAVE_ENTRY_PROGRESS 1 @@ -456,14 +358,6 @@ entry_expose_event (GtkWidget* entry, #endif -gdouble -midori_location_entry_get_progress (MidoriLocationEntry* location_entry) -{ - g_return_val_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry), 0.0); - - return location_entry->progress; -} - void midori_location_entry_set_progress (MidoriLocationEntry* location_entry, gdouble progress) @@ -483,188 +377,12 @@ midori_location_entry_set_progress (MidoriLocationEntry* location_entry, #endif } -static gboolean -midori_location_entry_completion_selected (GtkEntryCompletion* completion, - GtkTreeModel* model, - GtkTreeIter* iter, - MidoriLocationEntry* location_entry) -{ - gchar* uri; - - gtk_tree_model_get (model, iter, URI_COL, &uri, -1); - midori_location_entry_set_item_from_uri (location_entry, uri); - g_free (uri); - - return FALSE; -} - -static void -midori_location_entry_render_pixbuf_cb (GtkCellLayout* layout, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - gpointer data) -{ - GdkPixbuf* pixbuf; - - gtk_tree_model_get (model, iter, FAVICON_COL, &pixbuf, -1); - if (pixbuf) - { - g_object_set (renderer, "pixbuf", pixbuf, "yalign", 0.25, NULL); - g_object_unref (pixbuf); - } -} - -static void -midori_location_entry_render_text_cb (GtkCellLayout* layout, - GtkCellRenderer* renderer, - GtkTreeModel* model, - GtkTreeIter* iter, - gpointer data) -{ - gchar* uri; - gchar* title; - gchar* desc; - gchar* desc_uri; - gchar* desc_title; - GtkWidget* entry; - gchar* key; - gchar* temp; - gchar** parts; - - gtk_tree_model_get (model, iter, URI_COL, &uri, TITLE_COL, &title, -1); - - desc_uri = desc_title = key = NULL; - if (data) - { - entry = gtk_entry_completion_get_entry (GTK_ENTRY_COMPLETION (data)); - key = g_utf8_strdown (gtk_entry_get_text (GTK_ENTRY (entry)), -1); - } - if (data && uri) - { - temp = g_utf8_strdown (uri, -1); - parts = g_strsplit (temp, key, 2); - g_free (temp); - if (parts && parts[0] && parts[1]) - desc_uri = g_markup_printf_escaped ("%s%s%s", - parts[0], key, parts[1]); - g_strfreev (parts); - } - if (uri && !desc_uri) - desc_uri = g_markup_escape_text (uri, -1); - if (data && title) - { - temp = g_utf8_strdown (title, -1); - parts = g_strsplit (temp, key, 2); - g_free (temp); - if (parts && parts[0] && parts[1]) - desc_title = g_markup_printf_escaped ("%s%s%s", - parts[0], key, parts[1]); - g_strfreev (parts); - } - if (title && !desc_title) - desc_title = g_markup_escape_text (title, -1); - - if (desc_title) - desc = g_strdup_printf ("%s\n%s", - desc_title, desc_uri); - else - desc = g_strdup_printf ("%s", desc_uri); - - g_object_set (renderer, "markup", desc, - "ellipsize-set", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL); - - g_free (uri); - g_free (title); - g_free (key); - g_free (desc); - g_free (desc_uri); - g_free (desc_title); -} - -static gboolean -midori_location_entry_completion_match_cb (GtkEntryCompletion* completion, - const gchar* key, - GtkTreeIter* iter, - gpointer data) -{ - GtkTreeModel* model; - gchar* uri; - gchar* title; - gboolean match; - gchar* temp; - - model = gtk_entry_completion_get_model (completion); - gtk_tree_model_get (model, iter, URI_COL, &uri, TITLE_COL, &title, -1); - - match = FALSE; - if (uri) - { - temp = g_utf8_casefold (uri, -1); - match = (strstr (temp, key) != NULL); - g_free (temp); - g_free (uri); - - if (!match && title) - { - temp = g_utf8_casefold (title, -1); - match = (strstr (temp, key) != NULL); - g_free (temp); - g_free (title); - } - } - - return match; -} - -static void -midori_location_entry_completion_init (MidoriLocationEntry* location_entry) -{ - GtkWidget* entry; - GtkEntryCompletion* completion; - GtkCellRenderer* renderer; - - entry = gtk_bin_get_child (GTK_BIN (location_entry)); - completion = gtk_entry_completion_new (); - - gtk_entry_completion_set_model (GTK_ENTRY_COMPLETION (completion), - midori_location_entry_get_sort_model (location_entry)); - gtk_entry_completion_set_text_column (GTK_ENTRY_COMPLETION (completion), - URI_COL); - gtk_cell_layout_clear (GTK_CELL_LAYOUT (completion)); - - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, FALSE); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer, - midori_location_entry_render_pixbuf_cb, - NULL, NULL); - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, TRUE); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion), renderer, - midori_location_entry_render_text_cb, - completion, NULL); - gtk_entry_completion_set_match_func (completion, - midori_location_entry_completion_match_cb, NULL, NULL); - - gtk_entry_set_completion (GTK_ENTRY (entry), completion); - g_signal_connect (completion, "match-selected", - G_CALLBACK (midori_location_entry_completion_selected), location_entry); - - g_object_unref (completion); -} - static void midori_location_entry_init (MidoriLocationEntry* location_entry) { GtkWidget* entry; - GtkListStore* store; - GtkCellRenderer* renderer; - GtkTreeModel* filter_model; -#ifdef ORDER_BY_VISITS - GtkTreeModel* sort_model; -#endif - /* we want the widget to have appears-as-list applied */ + /* We want the widget to have appears-as-list applied */ gtk_rc_parse_string ("style \"midori-location-entry-style\" {\n" " GtkComboBox::appears-as-list = 1\n }\n" "widget_class \"*MidoriLocationEntry\" " @@ -674,57 +392,17 @@ midori_location_entry_init (MidoriLocationEntry* location_entry) entry = gtk_icon_entry_new (); gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, DEFAULT_ICON); + GTK_ICON_ENTRY_PRIMARY, GTK_STOCK_FILE); + gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry), + GTK_ICON_ENTRY_SECONDARY, TRUE); g_signal_connect_after (entry, "key-press-event", G_CALLBACK (entry_key_press_event), location_entry); #ifdef HAVE_ENTRY_PROGRESS g_signal_connect_after (entry, "expose-event", G_CALLBACK (entry_expose_event), location_entry); #endif - gtk_widget_show (entry); gtk_container_add (GTK_CONTAINER (location_entry), entry); - - store = gtk_list_store_new (N_COLS, - GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INT, G_TYPE_BOOLEAN); - -#ifdef ORDER_BY_VISITS - sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store)); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), - VISITS_COL, GTK_SORT_DESCENDING); - filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort_model), NULL); -#else - filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL); -#endif - - gtk_tree_model_filter_set_visible_column ( - GTK_TREE_MODEL_FILTER (filter_model), VISIBLE_COL); - g_object_set (location_entry, "model", filter_model, NULL); - g_object_unref (store); - - gtk_combo_box_entry_set_text_column ( - GTK_COMBO_BOX_ENTRY (location_entry), URI_COL); - gtk_cell_layout_clear (GTK_CELL_LAYOUT (location_entry)); - - /* setup the renderer for the favicon */ - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (location_entry), - renderer, FALSE); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (location_entry), - renderer, midori_location_entry_render_pixbuf_cb, NULL, NULL); - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (location_entry), - renderer, TRUE); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (location_entry), - renderer, midori_location_entry_render_text_cb, NULL, NULL); - - gtk_combo_box_set_active (GTK_COMBO_BOX (location_entry), -1); - - midori_location_entry_completion_init (location_entry); - - g_signal_connect (location_entry, "changed", - G_CALLBACK (midori_location_entry_changed), NULL); } static gboolean @@ -746,101 +424,6 @@ entry_key_press_event (GtkWidget* widget, return FALSE; } -static void -midori_location_entry_changed (GtkComboBox* combo_box, - gpointer user_data) -{ - GtkTreeIter iter; - GtkIconEntry* entry; - GtkTreeModel* model; - GdkPixbuf* pixbuf; - - if (gtk_combo_box_get_active_iter (combo_box, &iter)) - { - entry = GTK_ICON_ENTRY (GTK_BIN (combo_box)->child); - - if (entry) - { - pixbuf = NULL; - - model = midori_location_entry_get_filter_model - (MIDORI_LOCATION_ENTRY (combo_box)); - gtk_tree_model_get (model, &iter, FAVICON_COL, &pixbuf, -1); - - gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, pixbuf); - g_object_unref (pixbuf); - - g_signal_emit (MIDORI_LOCATION_ENTRY (combo_box), - signals[ACTIVE_CHANGED], 0, gtk_combo_box_get_active (combo_box)); - } - } -} - -static void -midori_location_entry_set_item (MidoriLocationEntry* entry, - GtkTreeIter* iter, - MidoriLocationEntryItem* item) -{ - GtkTreeModel* model; - GdkPixbuf* icon; - GdkPixbuf* new_icon; - - model = midori_location_entry_get_model (entry); - gtk_list_store_set (GTK_LIST_STORE (model), iter, - URI_COL, item->uri, TITLE_COL, item->title, -1); - - gtk_tree_model_get (model, iter, FAVICON_COL, &icon, -1); - if (item->favicon) - new_icon = g_object_ref (item->favicon); - else if (!icon && !item->favicon) - new_icon = gtk_widget_render_icon (GTK_WIDGET (entry), DEFAULT_ICON, - GTK_ICON_SIZE_MENU, NULL); - else - new_icon = NULL; - if (new_icon) - { - gtk_list_store_set (GTK_LIST_STORE (model), iter, - FAVICON_COL, new_icon, -1); - g_object_unref (new_icon); - } -} - -static void -midori_location_entry_set_active_iter (MidoriLocationEntry* location_entry, - GtkTreeIter* iter) -{ - GdkPixbuf* pixbuf; - GtkTreeModel* model; - GtkWidget* entry; - GtkTreeIter parent_iter; - - entry = gtk_bin_get_child (GTK_BIN (location_entry)); - model = midori_location_entry_get_model (location_entry); - - /* The filter iter must be set, not the child iter, - * but the row must first be set as visible to - * convert to a filter iter without error. - */ - gtk_list_store_set (GTK_LIST_STORE (model), iter, VISIBLE_COL, TRUE, -1); - if (midori_location_entry_child_iter_to_iter ( - location_entry, &parent_iter, iter)) - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (location_entry), &parent_iter); - - /* When setting the active iter (when adding or setting an item) - * the favicon may have changed, so we must update the entry favicon. - */ - if (entry) - { - gtk_tree_model_get (model, iter, FAVICON_COL, &pixbuf, -1); - - gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, pixbuf); - - g_object_unref (pixbuf); - } -} - /** * midori_location_entry_new: * @@ -853,279 +436,3 @@ midori_location_entry_new (void) { return g_object_new (MIDORI_TYPE_LOCATION_ENTRY, NULL); } - -/** - * midori_location_entry_item_iter: - * @location_entry: a #MidoriLocationEntry - * @uri: a string - * @iter: a GtkTreeIter - * - * Retrieves the iter of the item matching @uri. - * - * Return value: %TRUE if @uri was found, %FALSE otherwise - **/ -gboolean -midori_location_entry_item_iter (MidoriLocationEntry* location_entry, - const gchar* uri, - GtkTreeIter* iter) -{ - GtkTreeModel* model; - gchar* tmpuri; - gboolean found; - - g_return_val_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry), FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - - found = FALSE; - model = midori_location_entry_get_model (location_entry); - if (gtk_tree_model_get_iter_first (model, iter)) - { - tmpuri = NULL; - do - { - gtk_tree_model_get (model, iter, URI_COL, &tmpuri, -1); - found = !g_ascii_strcasecmp (uri, tmpuri); - katze_assign (tmpuri, NULL); - - if (found) - break; - } - while (gtk_tree_model_iter_next (model, iter)); - } - return found; -} - -/** - * midori_location_entry_get_text: - * @location_entry: a #MidoriLocationEntry - * - * Retrieves the text of the embedded entry. - * - * Return value: a string - **/ -const gchar* -midori_location_entry_get_text (MidoriLocationEntry* location_entry) -{ - GtkWidget* entry; - - g_return_val_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry), NULL); - - entry = gtk_bin_get_child (GTK_BIN (location_entry)); - g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL); - - return gtk_entry_get_text (GTK_ENTRY (entry)); -} - -/** - * midori_location_entry_set_text: - * @location_entry: a #MidoriLocationEntry - * @text: a string - * - * Sets the entry text to @text and, if applicable, updates the icon. - **/ -void -midori_location_entry_set_text (MidoriLocationEntry* location_entry, - const gchar* text) -{ - GtkWidget* entry; - GtkTreeIter iter; - GtkTreeModel* model; - GdkPixbuf* icon; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - - entry = gtk_bin_get_child (GTK_BIN (location_entry)); - g_return_if_fail (GTK_IS_ENTRY (entry)); - - gtk_entry_set_text (GTK_ENTRY (entry), text); - if (midori_location_entry_item_iter (location_entry, text, &iter)) - { - model = midori_location_entry_get_model (location_entry); - gtk_tree_model_get (model, &iter, FAVICON_COL, &icon, -1); - gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, icon); - } - /* FIXME: Due to a bug in GtkIconEntry we can't reset the icon - else - gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, DEFAULT_ICON);*/ -} - -/** - * midori_location_entry_reset: - * @location_entry: a #MidoriLocationEntry - * - * Clears the entry text and resets the entry favicon. - **/ -void -midori_location_entry_reset (MidoriLocationEntry* location_entry) -{ - GtkWidget* entry; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - - entry = gtk_bin_get_child (GTK_BIN (location_entry)); - g_return_if_fail (GTK_IS_ICON_ENTRY (entry)); - - gtk_entry_set_text (GTK_ENTRY (entry), ""); - gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), - GTK_ICON_ENTRY_PRIMARY, DEFAULT_ICON); -} - -/** - * midori_location_entry_clear: - * @location_entry: a #MidoriLocationEntry - * - * Removes all items from @location_entry - **/ -void -midori_location_entry_clear (MidoriLocationEntry* location_entry) -{ - GtkTreeModel* model; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - - model = midori_location_entry_get_model (location_entry); - gtk_list_store_clear (GTK_LIST_STORE (model)); -} - -/** - * midori_location_entry_set_item_from_uri: - * @location_entry: a #MidoriLocationEntry - * @uri: a string - * - * Finds the item from the list matching @uri and sets it as the active item. - * If @uri is not found it clears the active item. - **/ -void -midori_location_entry_set_item_from_uri (MidoriLocationEntry* location_entry, - const gchar* uri) -{ - GtkTreeIter iter; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - - if (midori_location_entry_item_iter (location_entry, uri, &iter)) - midori_location_entry_set_active_iter (location_entry, &iter); - else - midori_location_entry_reset (location_entry); - -} - -/** - * midori_location_entry_prepend_item: - * @location_entry: a #MidoriLocationEntry - * @item: a MidoriLocationItem - * - * Prepends @item if it is not already in the list. - * If the item already exists, it is moved before the first item. - * If the maximum is reached, the last item is removed. - **/ -void -midori_location_entry_prepend_item (MidoriLocationEntry* location_entry, - MidoriLocationEntryItem* item) -{ - GtkTreeModel* filter_model; - GtkTreeModel* model; - GtkTreeIter iter; - GtkTreeIter index; - gint n; - gint visits = 0; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - g_return_if_fail (item->uri != NULL); - - filter_model = midori_location_entry_get_filter_model (location_entry); - model = midori_location_entry_get_model (location_entry); - - if (midori_location_entry_item_iter (location_entry, item->uri, &iter)) - { - gtk_tree_model_get_iter_first (model, &index); - gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); - gtk_list_store_move_before (GTK_LIST_STORE (model), &iter, &index); - } - else - gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); - - n = gtk_tree_model_iter_n_children (filter_model, NULL); - if (n > MAX_ITEMS) - { - gtk_tree_model_iter_nth_child (model, &index, NULL, n - 1); - gtk_list_store_set (GTK_LIST_STORE (model), - &index, VISIBLE_COL, FALSE, -1); - } - - /* Only increment the visits when we add the uri */ - if (!item->title && !item->favicon) - gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISITS_COL, ++visits, - VISIBLE_COL, TRUE, -1); - midori_location_entry_set_item (location_entry, &iter, item); -} - -/** - * midori_location_entry_append_item: - * @location_entry: a #MidoriLocationEntry - * @item: a MidoriLocationItem - * - * Appends @item if it is not already in the list. - * @item is not added if the maximum is reached. - **/ -void -midori_location_entry_append_item (MidoriLocationEntry* location_entry, - MidoriLocationEntryItem* item) -{ - GtkTreeModel* model; - GtkTreeIter iter; - gint n; - gint visits = 0; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - g_return_if_fail (item->uri != NULL); - - model = midori_location_entry_get_model (location_entry); - - if (!midori_location_entry_item_iter (location_entry, item->uri, &iter)) - { - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - - n = gtk_tree_model_iter_n_children (model, NULL); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISIBLE_COL, - (n <= MAX_ITEMS), -1); - } - else - gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, VISITS_COL, ++visits, -1); - midori_location_entry_set_item (location_entry, &iter, item); -} - -/** - * midori_location_entry_set_item_from_uri: - * @location_entry: a #MidoriLocationEntry - * @uri: a string - * - * Finds the item from the list matching @uri - * and removes it if it is the last instance. - **/ -void -midori_location_entry_delete_item_from_uri (MidoriLocationEntry* location_entry, - const gchar* uri) -{ - GtkTreeModel* model; - GtkTreeIter iter; - gint visits = 0; - - g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry)); - - model = midori_location_entry_get_model (location_entry); - if (midori_location_entry_item_iter (location_entry, uri, &iter)) - { - gtk_tree_model_get (model, &iter, VISITS_COL, &visits, -1); - if (visits > 1) - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, VISITS_COL, --visits, -1); - else - gtk_list_store_remove (GTK_LIST_STORE (model), &iter); - } -} - diff --git a/midori/midori-locationentry.h b/midori/midori-locationentry.h index 6be5ed69..f84d0b29 100644 --- a/midori/midori-locationentry.h +++ b/midori/midori-locationentry.h @@ -27,56 +27,12 @@ typedef struct _MidoriLocationEntry MidoriLocationEntry; typedef struct _MidoriLocationEntryClass MidoriLocationEntryClass; typedef struct _MidoriLocationEntryItem MidoriLocationEntryItem; -struct _MidoriLocationEntryItem -{ - GdkPixbuf* favicon; - const gchar* uri; - const gchar* title; -}; - GType midori_location_entry_get_type (void); GtkWidget* midori_location_entry_new (void); -gboolean -midori_location_entry_item_iter (MidoriLocationEntry* location_entry, - const gchar* uri, - GtkTreeIter* iter); - -const gchar* -midori_location_entry_get_text (MidoriLocationEntry* location_entry); - -void -midori_location_entry_set_text (MidoriLocationEntry* location_entry, - const gchar* text); - -void -midori_location_entry_reset (MidoriLocationEntry* location_entry); - -void -midori_location_entry_clear (MidoriLocationEntry* location_entry); - -void -midori_location_entry_set_item_from_uri (MidoriLocationEntry* location_entry, - const gchar* uri); - -void -midori_location_entry_prepend_item (MidoriLocationEntry* location_entry, - MidoriLocationEntryItem* item); - -void -midori_location_entry_append_item (MidoriLocationEntry* location_entry, - MidoriLocationEntryItem* item); - -void -midori_location_entry_delete_item_from_uri (MidoriLocationEntry* location_entry, - const gchar* uri); - -gdouble -midori_location_entry_get_progress (MidoriLocationEntry* location_entry); - void midori_location_entry_set_progress (MidoriLocationEntry* location_entry, gdouble progress);