aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
authorThomas Meire <blackskad@gmail.com>2010-01-12 23:34:39 +0800
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2010-01-12 23:36:01 +0800
commit0ee842ac627f30fa14d75b06cd7147a67090731e (patch)
treefb0732e13d95ca15fa7a0ad29d88b3c26d95c3e8 /libempathy-gtk
parent183fa2e8a94d94a7098120fc43cde9ad83869de6 (diff)
downloadgsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar.gz
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar.bz2
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar.lz
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar.xz
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.tar.zst
gsoc2013-empathy-0ee842ac627f30fa14d75b06cd7147a67090731e.zip
Add search bar in chat text views (#585168)
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/Makefile.am5
-rw-r--r--libempathy-gtk/empathy-chat-text-view.c5
-rw-r--r--libempathy-gtk/empathy-chat.c17
-rw-r--r--libempathy-gtk/empathy-search-bar.c263
-rw-r--r--libempathy-gtk/empathy-search-bar.h64
-rw-r--r--libempathy-gtk/empathy-search-bar.ui110
-rw-r--r--libempathy-gtk/empathy-theme-manager.c3
7 files changed, 462 insertions, 5 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index 7f73d7c56..2dd50bb6e 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -59,6 +59,7 @@ libempathy_gtk_handwritten_source = \
empathy-notify-manager.c \
empathy-presence-chooser.c \
empathy-protocol-chooser.c \
+ empathy-search-bar.c \
empathy-share-my-desktop.c \
empathy-smiley-manager.c \
empathy-sound.c \
@@ -104,6 +105,7 @@ libempathy_gtk_headers = \
empathy-notify-manager.h \
empathy-presence-chooser.h \
empathy-protocol-chooser.h \
+ empathy-search-bar.h \
empathy-share-my-desktop.h \
empathy-smiley-manager.h \
empathy-sound.h \
@@ -158,7 +160,8 @@ ui_DATA = \
empathy-status-preset-dialog.ui \
empathy-log-window.ui \
empathy-chat.ui \
- empathy-contact-selector-dialog.ui
+ empathy-contact-selector-dialog.ui \
+ empathy-search-bar.ui
empathy-gtk-marshal.list: $(libempathy_gtk_la_SOURCES) Makefile.am
$(QUIET_GEN)( cd $(srcdir) && \
diff --git a/libempathy-gtk/empathy-chat-text-view.c b/libempathy-gtk/empathy-chat-text-view.c
index 4f38865f6..fcd6ebb32 100644
--- a/libempathy-gtk/empathy-chat-text-view.c
+++ b/libempathy-gtk/empathy-chat-text-view.c
@@ -880,7 +880,7 @@ chat_text_view_find_previous (EmpathyChatView *view,
from_start = TRUE;
}
- if (priv->find_mark_previous) {
+ if (!new_search && priv->find_mark_previous) {
gtk_text_buffer_get_iter_at_mark (buffer,
&iter_at_mark,
priv->find_mark_previous);
@@ -995,7 +995,7 @@ chat_text_view_find_next (EmpathyChatView *view,
from_start = TRUE;
}
- if (priv->find_mark_next) {
+ if (!new_search && priv->find_mark_next) {
gtk_text_buffer_get_iter_at_mark (buffer,
&iter_at_mark,
priv->find_mark_next);
@@ -1161,7 +1161,6 @@ chat_text_view_highlight (EmpathyChatView *view,
&iter_match_end);
iter = iter_match_end;
- gtk_text_iter_forward_char (&iter);
}
}
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c
index 02d123b54..95e9ecbc5 100644
--- a/libempathy-gtk/empathy-chat.c
+++ b/libempathy-gtk/empathy-chat.c
@@ -48,6 +48,7 @@
#include "empathy-contact-list-store.h"
#include "empathy-contact-list-view.h"
#include "empathy-contact-menu.h"
+#include "empathy-search-bar.h"
#include "empathy-theme-manager.h"
#include "empathy-smiley-manager.h"
#include "empathy-ui-utils.h"
@@ -93,6 +94,7 @@ typedef struct {
GtkWidget *label_topic;
GtkWidget *contact_list_view;
GtkWidget *info_bar_vbox;
+ GtkWidget *search_bar;
guint unread_messages;
/* TRUE if the pending messages can be displayed. This is to avoid to show
@@ -1369,6 +1371,11 @@ chat_input_key_press_event_cb (GtkWidget *widget,
gtk_adjustment_set_value (adj, val);
return TRUE;
}
+ /* catch ctrl-f to display the search bar */
+ if ((event->state & GDK_CONTROL_MASK) && (event->keyval == GDK_f)) {
+ empathy_search_bar_show (EMPATHY_SEARCH_BAR (priv->search_bar));
+ return TRUE;
+ }
if (!(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) &&
event->keyval == GDK_Tab) {
GtkTextBuffer *buffer;
@@ -2135,6 +2142,13 @@ chat_create_ui (EmpathyChat *chat)
chat->input_text_view);
gtk_widget_show (chat->input_text_view);
+ /* Add the (invisible) search bar */
+ priv->search_bar = empathy_search_bar_new (chat->view);
+ gtk_box_pack_start (GTK_BOX(priv->vbox_left),
+ priv->search_bar,
+ FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX(priv->vbox_left), priv->search_bar, 1);
+
/* Initialy hide the topic, will be shown if not empty */
gtk_widget_hide (priv->hbox_topic);
@@ -2150,7 +2164,8 @@ chat_create_ui (EmpathyChat *chat)
gtk_paned_set_position (GTK_PANED(priv->hpaned), paned_pos);
/* Set widget focus order */
- list = g_list_append (NULL, priv->scrolled_window_input);
+ list = g_list_append (NULL, priv->search_bar);
+ list = g_list_append (list, priv->scrolled_window_input);
gtk_container_set_focus_chain (GTK_CONTAINER (priv->vbox_left), list);
g_list_free (list);
diff --git a/libempathy-gtk/empathy-search-bar.c b/libempathy-gtk/empathy-search-bar.c
new file mode 100644
index 000000000..e4bad3b43
--- /dev/null
+++ b/libempathy-gtk/empathy-search-bar.c
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (C) 2010 Thomas Meire <blackskad@gmail.com>
+ *
+ * The code contained in this file is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either version
+ * 2.1 of the License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this code; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-utils.h>
+
+#include "empathy-chat-view.h"
+#include "empathy-search-bar.h"
+#include "empathy-ui-utils.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathySearchBar)
+
+G_DEFINE_TYPE (EmpathySearchBar, empathy_search_bar, GTK_TYPE_BIN);
+
+typedef struct _EmpathySearchBarPriv EmpathySearchBarPriv;
+struct _EmpathySearchBarPriv
+{
+ EmpathyChatView *chat_view;
+
+ GtkWidget *search_entry;
+ gchar *last_search;
+
+ GtkWidget *search_close;
+ GtkWidget *search_previous;
+ GtkWidget *search_next;
+ GtkWidget *search_not_found;
+};
+
+GtkWidget *
+empathy_search_bar_new (EmpathyChatView *view)
+{
+ EmpathySearchBar *self = g_object_new (EMPATHY_TYPE_SEARCH_BAR, NULL);
+
+ GET_PRIV (self)->chat_view = view;
+
+ return GTK_WIDGET (self);
+}
+
+static void
+empathy_search_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkBin *bin;
+ GtkWidget *child;
+
+ bin = GTK_BIN (widget);
+ child = gtk_bin_get_child (bin);
+
+ if (child && gtk_widget_get_visible (child))
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (child, &child_requisition);
+
+ requisition->width = child_requisition.width;
+ requisition->height = child_requisition.height;
+ }
+}
+
+static void
+empathy_search_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkBin *bin;
+ GtkWidget *child;
+ GtkAllocation child_allocation;
+
+ bin = GTK_BIN (widget);
+ child = gtk_bin_get_child (bin);
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (child && gtk_widget_get_visible (child))
+ {
+ child_allocation.x = allocation->x;
+ child_allocation.y = allocation->y;
+ child_allocation.width = MAX (allocation->width, 0);
+ child_allocation.height = MAX (allocation->height, 0);
+
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+}
+
+static void
+empathy_search_bar_finalize (GObject *object)
+{
+ EmpathySearchBarPriv *priv = GET_PRIV (object);
+
+ g_free (priv->last_search);
+}
+
+static void
+empathy_search_bar_update_buttons (EmpathySearchBar *self)
+{
+ gboolean can_go_forward = FALSE;
+ gboolean can_go_backward = FALSE;
+
+ EmpathySearchBarPriv* priv = GET_PRIV (self);
+
+ /* update previous / next buttons */
+ if (priv->last_search)
+ {
+ empathy_chat_view_find_abilities (priv->chat_view, priv->last_search,
+ &can_go_backward, &can_go_forward);
+ }
+
+ gtk_widget_set_sensitive (priv->search_previous,
+ can_go_backward && !EMP_STR_EMPTY (priv->last_search));
+ gtk_widget_set_sensitive (priv->search_next,
+ can_go_forward && !EMP_STR_EMPTY (priv->last_search));
+}
+
+void
+empathy_search_bar_show (EmpathySearchBar *self)
+{
+ EmpathySearchBarPriv *priv = GET_PRIV (self);
+
+ if (priv->last_search)
+ {
+ /* make sure we have an up to date last_search */
+ g_free (priv->last_search);
+ priv->last_search = gtk_editable_get_chars (
+ GTK_EDITABLE (priv->search_entry), 0, -1);
+ }
+ empathy_chat_view_highlight (priv->chat_view, priv->last_search);
+ empathy_search_bar_update_buttons (self);
+
+ /* grab the focus to the search entry */
+ gtk_widget_grab_focus (priv->search_entry);
+
+ gtk_widget_show (GTK_WIDGET (self));
+}
+
+
+static void
+empathy_search_bar_close_cb (GtkButton *button,
+ gpointer user_data)
+{
+ EmpathySearchBarPriv *priv = GET_PRIV (user_data);
+
+ empathy_chat_view_highlight (priv->chat_view, "");
+ gtk_widget_hide (GTK_WIDGET (user_data));
+
+ /* give the focus back to the focus-chain with the chat view */
+ gtk_widget_grab_focus (GTK_WIDGET (priv->chat_view));
+}
+
+static void
+empathy_search_bar_entry_changed (GtkEditable *entry,
+ gpointer user_data)
+{
+ EmpathySearchBarPriv *priv;
+ gboolean found;
+ gchar *search;
+
+ priv = GET_PRIV (user_data);
+
+ search = gtk_editable_get_chars (entry, 0, -1);
+
+ found = empathy_chat_view_find_previous (priv->chat_view, search, TRUE);
+ gtk_widget_set_visible (priv->search_not_found,
+ !(found || EMP_STR_EMPTY (search)));
+
+ empathy_chat_view_highlight (priv->chat_view, search);
+
+ g_free (priv->last_search);
+ priv->last_search = search;
+
+ empathy_search_bar_update_buttons (EMPATHY_SEARCH_BAR (user_data));
+}
+
+static void
+empathy_search_bar_next_cb (GtkButton *button,
+ gpointer user_data)
+{
+ EmpathySearchBarPriv *priv = GET_PRIV (user_data);
+
+ empathy_chat_view_find_next (priv->chat_view, priv->last_search, FALSE);
+ empathy_search_bar_update_buttons (EMPATHY_SEARCH_BAR (user_data));
+}
+
+static void
+empathy_search_bar_previous_cb (GtkButton *button,
+ gpointer user_data)
+{
+ EmpathySearchBarPriv *priv = GET_PRIV (user_data);
+
+ empathy_chat_view_find_previous (priv->chat_view, priv->last_search, FALSE);
+ empathy_search_bar_update_buttons (EMPATHY_SEARCH_BAR (user_data));
+}
+
+static void
+empathy_search_bar_init (EmpathySearchBar * self)
+{
+ gchar *filename;
+ GtkBuilder *gui;
+ GtkWidget *internal;
+ EmpathySearchBarPriv *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_SEARCH_BAR,
+ EmpathySearchBarPriv);
+
+ self->priv = priv;
+
+ filename = empathy_file_lookup ("empathy-search-bar.ui", "libempathy-gtk");
+ gui = empathy_builder_get_file (filename,
+ "search_widget", &internal,
+ "search_close", &priv->search_close,
+ "search_entry", &priv->search_entry,
+ "search_previous", &priv->search_previous,
+ "search_next", &priv->search_next,
+ "search_not_found", &priv->search_not_found,
+ NULL);
+ g_free (filename);
+
+ /* Add the signals */
+ empathy_builder_connect (gui, self,
+ "search_close", "clicked", empathy_search_bar_close_cb,
+ "search_entry", "changed", empathy_search_bar_entry_changed,
+ "search_previous", "clicked", empathy_search_bar_previous_cb,
+ "search_next", "clicked", empathy_search_bar_next_cb,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (self), internal);
+ gtk_widget_show_all (internal);
+ gtk_widget_hide (priv->search_not_found);
+ g_object_unref (gui);
+}
+
+static void
+empathy_search_bar_class_init (EmpathySearchBarClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ gobject_class->finalize = empathy_search_bar_finalize;
+
+ g_type_class_add_private (gobject_class, sizeof (EmpathySearchBarPriv));
+
+ /* Neither GtkBin nor GtkContainer seems to do this for us :( */
+ widget_class->size_request = empathy_search_bar_size_request;
+ widget_class->size_allocate = empathy_search_bar_size_allocate;
+}
+
diff --git a/libempathy-gtk/empathy-search-bar.h b/libempathy-gtk/empathy-search-bar.h
new file mode 100644
index 000000000..d4cd042fe
--- /dev/null
+++ b/libempathy-gtk/empathy-search-bar.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (C) 2010 Thomas Meire <blackskad@gmail.com>
+ *
+ * The code contained in this file is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either version
+ * 2.1 of the License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this code; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __EMPATHY_SEARCH_BAR_H__
+#define __EMPATHY_SEARCH_BAR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "empathy-chat-view.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_SEARCH_BAR (empathy_search_bar_get_type ())
+#define EMPATHY_SEARCH_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ EMPATHY_TYPE_SEARCH_BAR, EmpathySearchBar))
+#define EMPATHY_SEARCH_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \
+ EMPATHY_TYPE_SEARCH_BAR, EmpathySearchBarClass))
+#define EMPATHY_IS_SEARCH_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ EMPATHY_TYPE_SEARCH_BAR))
+#define EMPATHY_IS_SEARCH_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \
+ EMPATHY_TYPE_SEARCH_BAR))
+#define EMPATHY_SEARCH_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),\
+ EMPATHY_TYPE_SEARCH_BAR, EmpathySearchBarClass))
+
+typedef struct _EmpathySearchBar EmpathySearchBar;
+typedef struct _EmpathySearchBarClass EmpathySearchBarClass;
+
+struct _EmpathySearchBar
+{
+ GtkBin parent;
+
+ /*<private>*/
+ gpointer priv;
+};
+
+struct _EmpathySearchBarClass
+{
+ GtkBinClass parent_class;
+};
+
+GType empathy_search_bar_get_type (void) G_GNUC_CONST;
+GtkWidget * empathy_search_bar_new (EmpathyChatView *view);
+void empathy_search_bar_show (EmpathySearchBar *searchbar);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_SEARCH_BAR_H__ */
diff --git a/libempathy-gtk/empathy-search-bar.ui b/libempathy-gtk/empathy-search-bar.ui
new file mode 100644
index 000000000..9768b1e6c
--- /dev/null
+++ b/libempathy-gtk/empathy-search-bar.ui
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkHBox" id="search_widget">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="search_close">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="search_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Find:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">&#x25CF;</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_previous">
+ <property name="label">Find previous</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image3</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_next">
+ <property name="label">Find next</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="search_not_found">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-error</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Phrase not found</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-close</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-go-back</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-go-forward</property>
+ </object>
+</interface>
diff --git a/libempathy-gtk/empathy-theme-manager.c b/libempathy-gtk/empathy-theme-manager.c
index cda978330..905e0bf1d 100644
--- a/libempathy-gtk/empathy-theme-manager.c
+++ b/libempathy-gtk/empathy-theme-manager.c
@@ -115,6 +115,9 @@ theme_manager_create_irc_view (EmpathyThemeManager *manager)
"foreground", "steelblue",
"underline", PANGO_UNDERLINE_SINGLE,
NULL);
+ empathy_chat_text_view_tag_set (view, EMPATHY_CHAT_TEXT_VIEW_TAG_HIGHLIGHT,
+ "background", "yellow",
+ NULL);
/* Define IRC tags */
empathy_chat_text_view_tag_set (view, EMPATHY_THEME_IRC_TAG_NICK_SELF,