No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2005 Renato Araujo Oliveira Filho - INdT <renato.filho@indt.org.br>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 */
28
29 #include "config.h"
30
31 #include <string.h>
32 #include <time.h>
33
34 #include <glib/gi18n.h>
35 #include <gtk/gtk.h>
36 #include <libsoup/soup.h>
37
38 #include "rb-uri-dialog.h"
39 #include "rb-builder-helpers.h"
40 #include "rb-dialog.h"
41 #include "rb-debug.h"
42
43 /**
44 * SECTION:rb-uri-dialog
45 * @short_description: simple URI entry dialog
46 * @include: rb-uri-dialog.h
47 *
48 * A simple dialog used to request a single URI from the user.
49 */
50
51 static void rb_uri_dialog_class_init (RBURIDialogClass *klass);
52 static void rb_uri_dialog_init (RBURIDialog *dialog);
53 static void rb_uri_dialog_response_cb (GtkDialog *gtkdialog,
54 int response_id,
55 RBURIDialog *dialog);
56 static void rb_uri_dialog_text_changed (GtkEditable *buffer,
57 RBURIDialog *dialog);
58 static void rb_uri_dialog_set_property (GObject *object,
59 guint prop_id,
60 const GValue *value,
61 GParamSpec *pspec);
62 static void rb_uri_dialog_get_property (GObject *object,
63 guint prop_id,
64 GValue *value,
65 GParamSpec *pspec);
66 static void rb_uri_dialog_clipboard_yank_url (GtkClipboard *clipboard,
67 const char *text,
68 gpointer data);
69
70 struct RBURIDialogPrivate
71 {
72 GtkWidget *label;
73 GtkWidget *url;
74 GtkWidget *okbutton;
75 GtkWidget *cancelbutton;
76 };
77
78 #define RB_URI_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_URI_DIALOG, RBURIDialogPrivate))
79
80 enum
81 {
82 LOCATION_ADDED,
83 LAST_SIGNAL
84 };
85
86 enum
87 {
88 PROP_0,
89 PROP_LABEL
90 };
91
92 static guint rb_uri_dialog_signals [LAST_SIGNAL] = { 0 };
93
94 G_DEFINE_TYPE (RBURIDialog, rb_uri_dialog, GTK_TYPE_DIALOG)
95
96 static void
97 rb_uri_dialog_class_init (RBURIDialogClass *klass)
98 {
99 GObjectClass *object_class = G_OBJECT_CLASS (klass);
100
101 object_class->set_property = rb_uri_dialog_set_property;
102 object_class->get_property = rb_uri_dialog_get_property;
103
104 /**
105 * RBURIDialog:label:
106 *
107 * The label displayed in the dialog.
108 */
109 g_object_class_install_property (object_class,
110 PROP_LABEL,
111 g_param_spec_string ("label",
112 "label",
113 "label",
114 "",
115 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
116
117 /**
118 * RBURIDialog::location-added:
119 * @dialog: the #RBURIDialog
120 * @uri: URI entered
121 *
122 * Emitted when the user has entered a URI into the dialog.
123 */
124 rb_uri_dialog_signals [LOCATION_ADDED] =
125 g_signal_new ("location-added",
126 G_OBJECT_CLASS_TYPE (object_class),
127 G_SIGNAL_RUN_LAST,
128 G_STRUCT_OFFSET (RBURIDialogClass, location_added),
129 NULL, NULL,
130 g_cclosure_marshal_VOID__STRING,
131 G_TYPE_NONE,
132 1,
133 G_TYPE_STRING);
134
135 g_type_class_add_private (klass, sizeof (RBURIDialogPrivate));
136 }
137
138 static void
139 rb_uri_dialog_init (RBURIDialog *dialog)
140 {
141 GtkWidget *content_area;
142 GtkBuilder *builder;
143
144 /* create the dialog and some buttons forward - close */
145 dialog->priv = RB_URI_DIALOG_GET_PRIVATE (dialog);
146
147 g_signal_connect_object (G_OBJECT (dialog),
148 "response",
149 G_CALLBACK (rb_uri_dialog_response_cb),
150 dialog, 0);
151
152 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
153
154 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
155 gtk_box_set_spacing (GTK_BOX (content_area), 2);
156
157 dialog->priv->cancelbutton = gtk_dialog_add_button (GTK_DIALOG (dialog),
158 GTK_STOCK_CANCEL,
159 GTK_RESPONSE_CANCEL);
160 dialog->priv->okbutton = gtk_dialog_add_button (GTK_DIALOG (dialog),
161 GTK_STOCK_ADD,
162 GTK_RESPONSE_OK);
163 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
164
165 builder = rb_builder_load ("uri-new.ui", dialog);
166
167 gtk_container_add (GTK_CONTAINER (content_area),
168 GTK_WIDGET (gtk_builder_get_object (builder, "newuri")));
169
170 /* get the widgets from the GtkBuilder */
171 dialog->priv->label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
172 dialog->priv->url = GTK_WIDGET (gtk_builder_get_object (builder, "txt_url"));
173 gtk_entry_set_activates_default (GTK_ENTRY (dialog->priv->url), TRUE);
174
175 g_signal_connect_object (G_OBJECT (dialog->priv->url),
176 "changed",
177 G_CALLBACK (rb_uri_dialog_text_changed),
178 dialog, 0);
179
180 /* if we can get a url from the clipboard, populate the entry with that,
181 * since there's a good chance that's what the user wants to do anyway.
182 */
183 gtk_clipboard_request_text (gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
184 rb_uri_dialog_clipboard_yank_url,
185 dialog);
186 gtk_clipboard_request_text (gtk_clipboard_get(GDK_SELECTION_PRIMARY),
187 rb_uri_dialog_clipboard_yank_url,
188 dialog);
189
190 /* default focus */
191 gtk_widget_grab_focus (dialog->priv->url);
192
193 /* FIXME */
194 gtk_widget_set_sensitive (dialog->priv->okbutton, FALSE);
195
196 g_object_unref (builder);
197 }
198
199 static void
200 rb_uri_dialog_set_property (GObject *object,
201 guint prop_id,
202 const GValue *value,
203 GParamSpec *pspec)
204 {
205 RBURIDialog *dialog = RB_URI_DIALOG (object);
206
207 switch (prop_id) {
208 case PROP_LABEL:
209 gtk_label_set_text (GTK_LABEL (dialog->priv->label), g_value_get_string (value));
210 break;
211 default:
212 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
213 break;
214 }
215 }
216
217 static void
218 rb_uri_dialog_get_property (GObject *object,
219 guint prop_id,
220 GValue *value,
221 GParamSpec *pspec)
222 {
223 RBURIDialog *dialog = RB_URI_DIALOG (object);
224
225 switch (prop_id) {
226 case PROP_LABEL:
227 g_value_set_string (value, gtk_label_get_text (GTK_LABEL (dialog->priv->label)));
228 break;
229 default:
230 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
231 break;
232 }
233 }
234
235 /**
236 * rb_uri_dialog_new:
237 * @title: Window title for the dialog
238 * @label: Label to display in the dialog
239 *
240 * Creates a URI entry dialog.
241 *
242 * Returns: URI dialog instance.
243 */
244 GtkWidget *
245 rb_uri_dialog_new (const char *title, const char *label)
246 {
247 RBURIDialog *dialog;
248
249 dialog = g_object_new (RB_TYPE_URI_DIALOG,
250 "title", title,
251 "label", label,
252 NULL);
253 return GTK_WIDGET (dialog);
254 }
255
256 static void
257 rb_uri_dialog_response_cb (GtkDialog *gtkdialog,
258 int response_id,
259 RBURIDialog *dialog)
260 {
261 char *valid_url;
262 char *str;
263
264 if (response_id != GTK_RESPONSE_OK)
265 return;
266
267 str = gtk_editable_get_chars (GTK_EDITABLE (dialog->priv->url), 0, -1);
268 valid_url = g_strstrip (str);
269
270 g_signal_emit (dialog, rb_uri_dialog_signals [LOCATION_ADDED], 0, valid_url);
271
272 g_free (str);
273
274 gtk_widget_hide (GTK_WIDGET (gtkdialog));
275 }
276
277 static void
278 rb_uri_dialog_text_changed (GtkEditable *buffer,
279 RBURIDialog *dialog)
280 {
281 char *text = gtk_editable_get_chars (buffer, 0, -1);
282 gboolean has_text = ((text != NULL) && (*text != 0));
283
284 g_free (text);
285
286 gtk_widget_set_sensitive (dialog->priv->okbutton, has_text);
287 }
288
289 static void
290 rb_uri_dialog_clipboard_yank_url (GtkClipboard *clipboard, const char *text, gpointer data)
291 {
292 RBURIDialog *dialog = RB_URI_DIALOG (data);
293 SoupURI *uri;
294
295 if (text == NULL) {
296 return;
297 }
298
299 uri = soup_uri_new (text);
300 if (SOUP_URI_VALID_FOR_HTTP (uri)) {
301 gtk_entry_set_text (GTK_ENTRY (dialog->priv->url),
302 soup_uri_to_string (uri, FALSE));
303 gtk_editable_select_region (GTK_EDITABLE (dialog->priv->url), 0, -1);
304 }
305
306 if (uri != NULL) {
307 soup_uri_free (uri);
308 }
309 }