1 /*
2  * e-url-entry.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 #include "evolution-config.h"
19 
20 #include "e-url-entry.h"
21 
22 #include <gtk/gtk.h>
23 #include <glib/gi18n.h>
24 
25 #include "e-misc-utils.h"
26 
27 #define E_URL_ENTRY_GET_PRIVATE(obj) \
28 	(G_TYPE_INSTANCE_GET_PRIVATE \
29 	((obj), E_TYPE_URL_ENTRY, EUrlEntryPrivate))
30 
31 #define ICON_POSITION GTK_ENTRY_ICON_SECONDARY
32 
33 enum {
34 	PROP_0,
35 	PROP_ICON_VISIBLE
36 };
37 
G_DEFINE_TYPE(EUrlEntry,e_url_entry,GTK_TYPE_ENTRY)38 G_DEFINE_TYPE (
39 	EUrlEntry,
40 	e_url_entry,
41 	GTK_TYPE_ENTRY)
42 
43 static gboolean
44 url_entry_text_to_sensitive (GBinding *binding,
45                              const GValue *source_value,
46                              GValue *target_value,
47                              gpointer user_data)
48 {
49 	const gchar *text;
50 	gboolean sensitive = FALSE;
51 
52 	text = g_value_get_string (source_value);
53 
54 	if (text != NULL) {
55 		/* Skip leading whitespace. */
56 		while (g_ascii_isspace (*text))
57 			text++;
58 
59 		sensitive = *text != '\0';
60 	}
61 
62 	g_value_set_boolean (target_value, sensitive);
63 
64 	return TRUE;
65 }
66 
67 static void
url_entry_icon_release_cb(GtkEntry * entry,GtkEntryIconPosition icon_position,GdkEvent * event)68 url_entry_icon_release_cb (GtkEntry *entry,
69                            GtkEntryIconPosition icon_position,
70                            GdkEvent *event)
71 {
72 	gpointer toplevel;
73 
74 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
75 	toplevel = gtk_widget_is_toplevel (toplevel) ? toplevel : NULL;
76 
77 	if (icon_position == ICON_POSITION) {
78 		const gchar *text;
79 
80 		text = gtk_entry_get_text (entry);
81 		g_return_if_fail (text != NULL);
82 
83 		/* Skip leading whitespace. */
84 		while (g_ascii_isspace (*text))
85 			text++;
86 
87 		e_show_uri (toplevel, text);
88 	}
89 }
90 
91 static void
e_url_entry_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)92 e_url_entry_set_property (GObject *object,
93 			  guint property_id,
94 			  const GValue *value,
95 			  GParamSpec *pspec)
96 {
97 	switch (property_id) {
98 		case PROP_ICON_VISIBLE:
99 			e_url_entry_set_icon_visible (
100 				E_URL_ENTRY (object),
101 				g_value_get_boolean (value));
102 			return;
103 	}
104 
105 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
106 }
107 
108 static void
e_url_entry_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)109 e_url_entry_get_property (GObject *object,
110 			  guint property_id,
111 			  GValue *value,
112 			  GParamSpec *pspec)
113 {
114 	switch (property_id) {
115 		case PROP_ICON_VISIBLE:
116 			g_value_set_boolean (
117 				value,
118 				e_url_entry_get_icon_visible (
119 				E_URL_ENTRY (object)));
120 			return;
121 	}
122 
123 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
124 }
125 
126 static void
e_url_entry_class_init(EUrlEntryClass * class)127 e_url_entry_class_init (EUrlEntryClass *class)
128 {
129 	GObjectClass *object_class;
130 
131 	object_class = G_OBJECT_CLASS (class);
132 	object_class->set_property = e_url_entry_set_property;
133 	object_class->get_property = e_url_entry_get_property;
134 
135 	g_object_class_install_property (
136 		object_class,
137 		PROP_ICON_VISIBLE,
138 		g_param_spec_boolean (
139 			"icon-visible",
140 			NULL,
141 			NULL,
142 			FALSE,
143 			G_PARAM_READWRITE |
144 			G_PARAM_STATIC_STRINGS));
145 }
146 
147 static void
e_url_entry_init(EUrlEntry * url_entry)148 e_url_entry_init (EUrlEntry *url_entry)
149 {
150 	GtkEntry *entry;
151 
152 	entry = GTK_ENTRY (url_entry);
153 
154 	gtk_entry_set_icon_tooltip_text (
155 		entry, ICON_POSITION, _("Click here to open the URL"));
156 
157 	e_url_entry_set_icon_visible (url_entry, TRUE);
158 
159 	/* XXX GtkEntryClass has no "icon_release" method pointer to
160 	 *     override, so instead we have to connect to the signal. */
161 	g_signal_connect (
162 		url_entry, "icon-release",
163 		G_CALLBACK (url_entry_icon_release_cb), NULL);
164 
165 	e_binding_bind_property_full (
166 		url_entry, "text",
167 		url_entry, "secondary-icon-sensitive",
168 		G_BINDING_SYNC_CREATE,
169 		url_entry_text_to_sensitive,
170 		(GBindingTransformFunc) NULL,
171 		NULL, (GDestroyNotify) NULL);
172 }
173 
174 GtkWidget *
e_url_entry_new(void)175 e_url_entry_new (void)
176 {
177 	return g_object_new (E_TYPE_URL_ENTRY, NULL);
178 }
179 
180 void
e_url_entry_set_icon_visible(EUrlEntry * url_entry,gboolean visible)181 e_url_entry_set_icon_visible (EUrlEntry *url_entry,
182 			      gboolean visible)
183 {
184 	GtkEntry *entry;
185 
186 	g_return_if_fail (E_IS_URL_ENTRY (url_entry));
187 
188 	entry = GTK_ENTRY (url_entry);
189 
190 	if (visible) {
191 		gtk_entry_set_icon_from_icon_name (entry, ICON_POSITION, "go-jump");
192 		gtk_entry_set_placeholder_text (entry, _("Enter a URL here"));
193 	} else {
194 		gtk_entry_set_icon_from_icon_name (entry, ICON_POSITION, NULL);
195 		gtk_entry_set_placeholder_text (entry, NULL);
196 	}
197 }
198 
199 gboolean
e_url_entry_get_icon_visible(EUrlEntry * url_entry)200 e_url_entry_get_icon_visible (EUrlEntry *url_entry)
201 {
202 	g_return_val_if_fail (E_IS_URL_ENTRY (url_entry), FALSE);
203 
204 	return gtk_entry_get_icon_name (GTK_ENTRY (url_entry), ICON_POSITION) != NULL;
205 }
206