dialog-hyperlink.c 16.9 KB
Newer Older
Jody Goldberg's avatar
Jody Goldberg committed
1 2 3 4 5 6 7 8
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 * dialog-hyperlink.c: Add or edit a hyperlink
 *
 * Copyright (C) 2002 Jody Goldberg (jody@gnome.org)
 *
 * This program is free software; you can redistribute it and/or
9 10 11
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) version 3.
Jody Goldberg's avatar
Jody Goldberg committed
12 13 14 15 16 17 18 19
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
Jody Goldberg's avatar
Jody Goldberg committed
21 22
 * USA
 */
23

Jody Goldberg's avatar
Jody Goldberg committed
24 25 26
#include <gnumeric-config.h>
#include <gnumeric.h>
#include "dialogs.h"
27
#include "help.h"
Jody Goldberg's avatar
Jody Goldberg committed
28

29 30 31
#include <commands.h>
#include <widgets/gnumeric-expr-entry.h>
#include "expr-name.h"
32
#include "expr.h"
Jody Goldberg's avatar
Jody Goldberg committed
33 34
#include <gui-util.h>
#include <hlink.h>
35
#include <mstyle.h>
36
#include <style-color.h>
37 38 39
#include <sheet-control.h>
#include <sheet-view.h>
#include <sheet-style.h>
40
#include <value.h>
41
#include <wbc-gtk.h>
42
#include <goffice/goffice.h>
43

44
#include <gtk/gtk.h>
45
#include <glib/gi18n-lib.h>
46

Jody Goldberg's avatar
Jody Goldberg committed
47
#include <string.h>
Jody Goldberg's avatar
Jody Goldberg committed
48

49

Jody Goldberg's avatar
Jody Goldberg committed
50
typedef struct {
51
	WBCGtk  *wbcg;
Jody Goldberg's avatar
Jody Goldberg committed
52
	Workbook  *wb;
53
	SheetControl *sc;
54
	Sheet *sheet;
Jody Goldberg's avatar
Jody Goldberg committed
55

56
	GtkBuilder *gui;
Jody Goldberg's avatar
Jody Goldberg committed
57 58 59 60
	GtkWidget *dialog;

	GtkImage  *type_image;
	GtkLabel  *type_descriptor;
61
	GnmExprEntry *internal_link_ee;
Jody Goldberg's avatar
Jody Goldberg committed
62
	GnmHLink  *link;
63
	gboolean   is_new;
64 65

	GtkWidget *use_def_widget;
Jody Goldberg's avatar
Jody Goldberg committed
66 67
} HyperlinkState;

Jody Goldberg's avatar
Jody Goldberg committed
68
static void
69
dhl_free (HyperlinkState *state)
Jody Goldberg's avatar
Jody Goldberg committed
70 71
{
	if (state->gui != NULL) {
72
		g_object_unref (state->gui);
Jody Goldberg's avatar
Jody Goldberg committed
73 74 75
		state->gui = NULL;
	}
	if (state->link != NULL) {
76
		g_object_unref (state->link);
Jody Goldberg's avatar
Jody Goldberg committed
77 78 79 80 81 82
		state->link = NULL;
	}
	state->dialog = NULL;
	g_free (state);
}

83 84 85 86 87 88 89 90 91 92
static char *
dhl_get_default_tip (char const * const target) {
	char *default_text = _("Left click once to follow this link.\n"
			       "Middle click once to select this cell");
	if (target == NULL)
		return g_strdup (default_text);
	else
		return g_strjoin ("\n", target, default_text, NULL);
}

Jody Goldberg's avatar
Jody Goldberg committed
93
static void
94
dhl_set_tip (HyperlinkState* state)
Jody Goldberg's avatar
Jody Goldberg committed
95
{
96 97 98
	char const *tip = gnm_hlink_get_tip (state->link);
	GtkTextBuffer *tb;
	GtkWidget *w;
99

100
	if (state->is_new) {
Morten Welinder's avatar
Morten Welinder committed
101
			w = go_gtk_builder_get_widget (state->gui, "use-default-tip");
102 103
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
			return;
104
	}
105 106 107 108

	if (tip != NULL) {
		char const * const target = gnm_hlink_get_target (state->link);
		char *default_tip = dhl_get_default_tip (target);
109 110 111 112 113
		gboolean is_default = (strcmp (tip, default_tip) == 0);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (state->use_def_widget),
					      is_default);
		g_free (default_tip);
		if (is_default)
114
			return;
Morten Welinder's avatar
Morten Welinder committed
115
	}
Morten Welinder's avatar
Morten Welinder committed
116
	w = go_gtk_builder_get_widget (state->gui, "use-this-tip");
117
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);
Morten Welinder's avatar
Morten Welinder committed
118

Morten Welinder's avatar
Morten Welinder committed
119
	tb = gtk_text_view_get_buffer
Morten Welinder's avatar
Morten Welinder committed
120
		(GTK_TEXT_VIEW (go_gtk_builder_get_widget (state->gui, "tip-entry")));
121 122

	gtk_text_buffer_set_text (tb, (tip == NULL) ? "" : tip, -1);
123 124
}

125 126
static char *
dhl_get_tip (HyperlinkState *state, char const *target)
127
{
128 129
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (state->use_def_widget)))
		return NULL;
130 131
	else {
		char *tip;
Morten Welinder's avatar
Morten Welinder committed
132
		GtkTextBuffer *tb = gtk_text_view_get_buffer
Morten Welinder's avatar
Morten Welinder committed
133
			(GTK_TEXT_VIEW (go_gtk_builder_get_widget (state->gui, "tip-entry")));
134 135 136 137 138 139 140 141 142 143 144 145 146 147
		GtkTextIter start_iter, end_iter;

		gtk_text_buffer_get_start_iter (tb, &start_iter);
		gtk_text_buffer_get_end_iter (tb, &end_iter);

		tip  = gtk_text_buffer_get_text (tb, &start_iter, &end_iter, FALSE);

		if (tip != NULL && strlen (tip) == 0) {
			g_free (tip);
			tip = NULL;
		}

		return tip;
	}
Jody Goldberg's avatar
Jody Goldberg committed
148 149 150
}

static void
151
dhl_set_target_cur_wb (HyperlinkState *state, const char* const target)
Jody Goldberg's avatar
Jody Goldberg committed
152
{
153 154 155
	gnm_expr_entry_load_from_text (state->internal_link_ee, target);
}

156
static char *
157 158 159
dhl_get_target_cur_wb (HyperlinkState *state, gboolean *success)
{
	char *ret = NULL;
160
	GnmExprEntry *gee = state->internal_link_ee;
161 162
	char const *target = gnm_expr_entry_get_text (gee);
	Sheet *sheet = sc_sheet (state->sc);
Jody Goldberg's avatar
Jody Goldberg committed
163
	GnmValue *val;
164 165 166 167 168 169 170 171

	*success = FALSE;
	if (strlen (target) == 0) {
		*success = TRUE;
	} else {
		val = gnm_expr_entry_parse_as_value (gee, sheet);
		if (!val) {
			/* not an address, is it a name ? */
Morten Welinder's avatar
Morten Welinder committed
172
			GnmParsePos pp;
173 174
			GnmNamedExpr *nexpr;

175
			parse_pos_init_sheet (&pp, sheet);
176 177
			nexpr = expr_name_lookup (&pp, target);
			if (nexpr != NULL)
178
				val = gnm_expr_top_get_range (nexpr->texpr);
179 180 181
		}
		if (val) {
			*success = TRUE;
Morten Welinder's avatar
Morten Welinder committed
182
			ret = g_strdup (target);
183 184
			value_release (val);
		} else {
Morten Welinder's avatar
Morten Welinder committed
185
			go_gtk_notice_dialog (GTK_WINDOW (state->dialog),
186
					 GTK_MESSAGE_ERROR,
187 188 189 190
					 _("Not a range or name"));
			gnm_expr_entry_grab_focus (gee, TRUE);
		}
	}
Morten Welinder's avatar
Morten Welinder committed
191
	return ret;
192 193 194 195 196
}

static void
dhl_set_target_external (HyperlinkState *state, const char* const target)
{
Morten Welinder's avatar
Morten Welinder committed
197
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "external-link");
198 199 200 201

	gtk_entry_set_text (GTK_ENTRY (w), target);
}

202
static char *
203 204
dhl_get_target_external (HyperlinkState *state, gboolean *success)
{
Morten Welinder's avatar
Morten Welinder committed
205
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "external-link");
206 207 208
	const char *target = gtk_entry_get_text (GTK_ENTRY (w));

	*success = TRUE;
209
	return strlen (target) > 0 ? g_strdup (target) : NULL;
210 211
}

212 213 214
static void
dhl_set_target_email (HyperlinkState *state, const char* const target)
{
Morten Welinder's avatar
Morten Welinder committed
215 216
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "email-address");
	GtkWidget *w2 = go_gtk_builder_get_widget (state->gui, "email-subject");
217 218 219 220 221 222 223 224 225 226 227 228 229 230
	gchar* cursor;
	gchar* subject;
	gchar* guitext;

	if (!target || *target == '\0')
		return;

	if( strncmp (target, "mailto:", strlen ("mailto:")) != 0)
		return;

	cursor = g_strdup (target + strlen ("mailto:"));

	subject = strstr (cursor, "?subject=");
	if (subject) {
231 232
		guitext = g_uri_unescape_string (subject + strlen ("?subject="),
						 NULL);
233
		gtk_entry_set_text (GTK_ENTRY (w2), guitext);
234
		*subject = '\0';
235
		g_free (guitext);
236 237
	}

238
	guitext = g_uri_unescape_string (cursor, NULL);
239 240 241 242 243 244 245

	gtk_entry_set_text (GTK_ENTRY (w), guitext);

	g_free (guitext);
	g_free (cursor);
}

246
static char*
247 248
dhl_get_target_email (HyperlinkState *state, gboolean *success)
{
Morten Welinder's avatar
Morten Welinder committed
249 250
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "email-address");
	GtkWidget *w2 = go_gtk_builder_get_widget (state->gui, "email-subject");
251 252
	const char *address = gtk_entry_get_text (GTK_ENTRY (w));
	const char *subject = gtk_entry_get_text (GTK_ENTRY (w2));
253
	gchar* enc_subj, *enc_addr;
254 255 256 257 258 259 260
	gchar* result;

	*success = TRUE;
	if (!address || *address == '\0') {
		return NULL;
	}

261
	enc_addr = go_url_encode (address, 0);
262
	if (!subject || *subject == '\0') {
263 264 265
		result =  g_strconcat ("mailto:", enc_addr, NULL);
	} else {
		enc_subj = go_url_encode (subject, 0);
Morten Welinder's avatar
Morten Welinder committed
266 267

		result = g_strconcat ("mailto:", enc_addr,
268 269
				      "?subject=", enc_subj, NULL);
		g_free (enc_subj);
270 271
	}

272
	g_free (enc_addr);
273 274 275 276

	return result;
}

277 278 279
static void
dhl_set_target_url (HyperlinkState *state, const char* const target)
{
Morten Welinder's avatar
Morten Welinder committed
280
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "url");
281 282 283 284

	gtk_entry_set_text (GTK_ENTRY (w), target);
}

285
static char *
286 287
dhl_get_target_url (HyperlinkState *state, gboolean *success)
{
Morten Welinder's avatar
Morten Welinder committed
288
	GtkWidget *w = go_gtk_builder_get_widget (state->gui, "url");
289 290 291
	const char *target = gtk_entry_get_text (GTK_ENTRY (w));

	*success = TRUE;
292
	return strlen (target) > 0 ? g_strdup (target) : NULL;
Jody Goldberg's avatar
Jody Goldberg committed
293 294 295 296
}

static struct {
	char const *label;
297
	char const *icon_name;
Jody Goldberg's avatar
Jody Goldberg committed
298 299 300
	char const *name;
	char const *widget_name;
	char const *descriptor;
301
	void (*set_target) (HyperlinkState *state, const char* const target);
302
	char * (*get_target) (HyperlinkState *state, gboolean *success);
303
} const type[] = {
304
	{ N_("Internal Link"), "gnumeric-link-internal",
305
	  "GnmHLinkCurWB",	"internal-link-grid",
306 307 308
	  N_("Jump to specific cells or named range in the current workbook"),
	  dhl_set_target_cur_wb,
	  dhl_get_target_cur_wb },
Morten Welinder's avatar
Morten Welinder committed
309

310
	{ N_("External Link"), "gnumeric-link-external",
311
	  "GnmHLinkExternal",	"external-link-grid" ,
312 313 314
	  N_("Open an external file with the specified name"),
	  dhl_set_target_external,
	  dhl_get_target_external },
315
	{ N_("Email Link"),	"gnumeric-link-email",
316
	  "GnmHLinkEMail",	"email-grid" ,
317 318 319
	  N_("Prepare an email"),
	  dhl_set_target_email,
	  dhl_get_target_email },
320
	{ N_("Web Link"),		"gnumeric-link-url",
321
	  "GnmHLinkURL",	"url-grid" ,
322 323 324
	  N_("Browse to the specified URL"),
	  dhl_set_target_url,
	  dhl_get_target_url }
Jody Goldberg's avatar
Jody Goldberg committed
325 326 327
};

static void
328 329 330
dhl_set_target (HyperlinkState* state)
{
	unsigned i;
331 332
	char const * const target = gnm_hlink_get_target (state->link);
	char const * type_name;
Morten Welinder's avatar
Morten Welinder committed
333

334 335 336 337 338 339 340 341 342 343 344 345
	if (target) {
		type_name = G_OBJECT_TYPE_NAME (state->link);
		for (i = 0 ; i < G_N_ELEMENTS (type); i++) {
			if (strcmp (type_name, type[i].name) == 0) {
				if (type[i].set_target)
					(type[i].set_target) (state, target);
				break;
			}
		}
	}
}

346
static char *
347 348 349
dhl_get_target (HyperlinkState *state, gboolean *success)
{
	unsigned i;
350
	char const *type_name = G_OBJECT_TYPE_NAME (state->link);
351 352 353 354 355 356 357 358 359

	*success = FALSE;
	for (i = 0 ; i < G_N_ELEMENTS (type); i++) {
		if (strcmp (type_name, type[i].name) == 0) {
			if (type[i].get_target)
				return (type[i].get_target) (state, success);
			break;
		}
	}
Morten Welinder's avatar
Morten Welinder committed
360

361 362 363 364 365 366 367 368 369 370 371 372 373
	return NULL;
}


static void
dhl_cb_cancel (G_GNUC_UNUSED GtkWidget *button, HyperlinkState *state)
{
	gtk_widget_destroy (state->dialog);
}

static void
dhl_cb_ok (G_GNUC_UNUSED GtkWidget *button, HyperlinkState *state)
{
Morten Welinder's avatar
Morten Welinder committed
374
	GnmStyle *style;
375
	char *cmdname;
376
	char *target;
377
	char *tip;
378
	gboolean success;
Morten Welinder's avatar
Morten Welinder committed
379

380 381 382
	target = dhl_get_target (state, &success);
	if (!success)
		return;		/* Let user continue editing */
Morten Welinder's avatar
Morten Welinder committed
383

Morten Welinder's avatar
Morten Welinder committed
384
	wb_control_sheet_focus (GNM_WBC (state->wbcg), state->sheet);
385

386
	if (target) {
387
		gnm_hlink_set_sheet (state->link, state->sheet);
388
		gnm_hlink_set_target (state->link, target);
389 390 391
		tip = dhl_get_tip (state, target);
		gnm_hlink_set_tip (state->link, tip);
		g_free (tip);
392 393 394
		style = gnm_style_new ();
		gnm_style_set_hlink (style, g_object_ref (state->link));
		gnm_style_set_font_uline (style, UNDERLINE_SINGLE);
395
		gnm_style_set_font_color (style, gnm_color_new_go (GO_COLOR_BLUE));
396

397
		if (state->is_new) {
398
			cmdname = _("Add Hyperlink");
Morten Welinder's avatar
Morten Welinder committed
399
			cmd_selection_hyperlink (GNM_WBC (state->wbcg),
400 401 402
						 style,
						 cmdname, target);
		} else {
403
			cmdname = _("Edit Hyperlink");
Morten Welinder's avatar
Morten Welinder committed
404
			cmd_selection_hyperlink (GNM_WBC (state->wbcg),
405 406 407 408 409
						 style,
						 cmdname, NULL);
			g_free (target);
		}
	} else if (!state->is_new) {
410 411
		style = gnm_style_new ();
		gnm_style_set_hlink (style, NULL);
412
		cmdname = _("Remove Hyperlink");
Morten Welinder's avatar
Morten Welinder committed
413
		cmd_selection_hyperlink (GNM_WBC (state->wbcg), style,
414
					 cmdname, NULL);
Morten Welinder's avatar
Morten Welinder committed
415
	}
416 417 418 419 420
	gtk_widget_destroy (state->dialog);
}

static void
dhl_setup_type (HyperlinkState *state)
Jody Goldberg's avatar
Jody Goldberg committed
421 422 423 424 425 426
{
	GtkWidget *w;
	char const *name = G_OBJECT_TYPE_NAME (state->link);
	unsigned i;

	for (i = 0 ; i < G_N_ELEMENTS (type); i++) {
Morten Welinder's avatar
Morten Welinder committed
427
		w = go_gtk_builder_get_widget (state->gui, type[i].widget_name);
Jody Goldberg's avatar
Jody Goldberg committed
428 429 430

		if (!strcmp (name, type[i].name)) {
			gtk_widget_show_all (w);
431 432 433
			gtk_image_set_from_icon_name
				(state->type_image, type[i].icon_name,
				 GTK_ICON_SIZE_DIALOG);
Jody Goldberg's avatar
Jody Goldberg committed
434
			gtk_label_set_text (state->type_descriptor,
435
					    _(type[i].descriptor));
Jody Goldberg's avatar
Jody Goldberg committed
436 437 438 439 440 441
		} else
			gtk_widget_hide (w);
	}
}

static void
442
dhl_set_type (HyperlinkState *state, GType type)
Jody Goldberg's avatar
Jody Goldberg committed
443 444 445
{
	GnmHLink *old = state->link;

446
	state->link = gnm_hlink_new (type, state->sheet);
Jody Goldberg's avatar
Jody Goldberg committed
447 448 449
	if (old != NULL) {
		gnm_hlink_set_target (state->link, gnm_hlink_get_target (old));
		gnm_hlink_set_tip (state->link, gnm_hlink_get_tip (old));
450
		g_object_unref (old);
Jody Goldberg's avatar
Jody Goldberg committed
451
	}
452
	dhl_setup_type (state);
Jody Goldberg's avatar
Jody Goldberg committed
453 454 455
}

static void
456
dhl_cb_menu_changed (GtkComboBox *box, HyperlinkState *state)
Jody Goldberg's avatar
Jody Goldberg committed
457
{
458
	int i = gtk_combo_box_get_active (box);
459
	dhl_set_type (state, g_type_from_name (
460
		type [i].name));
Jody Goldberg's avatar
Jody Goldberg committed
461 462 463
}

static gboolean
464
dhl_init (HyperlinkState *state)
Jody Goldberg's avatar
Jody Goldberg committed
465 466 467 468 469 470 471
{
	static char const * const label[] = {
		"internal-link-label",
		"external-link-label",
		"email-address-label",
		"email-subject-label",
		"url-label",
472
		"use-this-tip"
Jody Goldberg's avatar
Jody Goldberg committed
473
	};
474
	GtkWidget *w;
Jody Goldberg's avatar
Jody Goldberg committed
475
	GtkSizeGroup *size_group;
476
	GnmExprEntry *expr_entry;
Jody Goldberg's avatar
Jody Goldberg committed
477
	unsigned i, select = 0;
478 479 480
	GtkListStore *store;
	GtkTreeIter iter;
	GtkCellRenderer *renderer;
Morten Welinder's avatar
Morten Welinder committed
481

Morten Welinder's avatar
Morten Welinder committed
482
#ifdef GNM_NO_MAILTO
483
	gtk_widget_hide (go_gtk_builder_get_widget (state->gui, "email-grid"));
484
#endif
Jody Goldberg's avatar
Jody Goldberg committed
485 486 487
	size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
	for (i = 0 ; i < G_N_ELEMENTS (label); i++)
		gtk_size_group_add_widget (size_group,
Morten Welinder's avatar
Morten Welinder committed
488
					   go_gtk_builder_get_widget (state->gui, label[i]));
Morten Welinder's avatar
Morten Welinder committed
489
	g_object_unref (size_group);
Morten Welinder's avatar
Morten Welinder committed
490

Morten Welinder's avatar
Morten Welinder committed
491
	w = go_gtk_builder_get_widget (state->gui, "link-type-image");
Jody Goldberg's avatar
Jody Goldberg committed
492
	state->type_image = GTK_IMAGE (w);
Morten Welinder's avatar
Morten Welinder committed
493
	w = go_gtk_builder_get_widget (state->gui, "link-type-descriptor");
Jody Goldberg's avatar
Jody Goldberg committed
494
	state->type_descriptor = GTK_LABEL (w);
Morten Welinder's avatar
Morten Welinder committed
495

496
	w = go_gtk_builder_get_widget (state->gui, "internal-link-grid");
497
	expr_entry = gnm_expr_entry_new (state->wbcg, TRUE);
498
	gtk_widget_set_hexpand (GTK_WIDGET (expr_entry), TRUE);
499
	gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (expr_entry));
500 501 502
	gtk_entry_set_activates_default
		(gnm_expr_entry_get_entry (expr_entry), TRUE);
	state->internal_link_ee = expr_entry;
Morten Welinder's avatar
Morten Welinder committed
503

Morten Welinder's avatar
Morten Welinder committed
504
	w = go_gtk_builder_get_widget (state->gui, "cancel_button");
Jody Goldberg's avatar
Jody Goldberg committed
505
	g_signal_connect (G_OBJECT (w),
506 507
			  "clicked",
			  G_CALLBACK (dhl_cb_cancel), state);
Morten Welinder's avatar
Morten Welinder committed
508

Morten Welinder's avatar
Morten Welinder committed
509
	w  = go_gtk_builder_get_widget (state->gui, "ok_button");
Jody Goldberg's avatar
Jody Goldberg committed
510
	g_signal_connect (G_OBJECT (w),
511 512
			  "clicked",
			  G_CALLBACK (dhl_cb_ok), state);
Jody Goldberg's avatar
Jody Goldberg committed
513
	gtk_window_set_default (GTK_WINDOW (state->dialog), w);
Morten Welinder's avatar
Morten Welinder committed
514

Morten Welinder's avatar
Morten Welinder committed
515
	gnm_init_help_button (
Morten Welinder's avatar
Morten Welinder committed
516
		go_gtk_builder_get_widget (state->gui, "help_button"),
517
		GNUMERIC_HELP_LINK_HYPERLINK);
Morten Welinder's avatar
Morten Welinder committed
518

519
	store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
Morten Welinder's avatar
Morten Welinder committed
520
	w = go_gtk_builder_get_widget (state->gui, "link-type-menu");
521
	gtk_combo_box_set_model (GTK_COMBO_BOX (w), GTK_TREE_MODEL (store));
Morten Welinder's avatar
Morten Welinder committed
522
	g_object_unref (store);
Morten Welinder's avatar
Morten Welinder committed
523

Jody Goldberg's avatar
Jody Goldberg committed
524
	for (i = 0 ; i < G_N_ELEMENTS (type); i++) {
525 526 527
		GdkPixbuf *pixbuf = go_gtk_widget_render_icon_pixbuf
			(GTK_WIDGET (wbcg_toplevel (state->wbcg)),
			 type[i].icon_name, GTK_ICON_SIZE_MENU);
528 529
		gtk_list_store_append (store, &iter);
		gtk_list_store_set (store, &iter,
530 531 532
				    0, pixbuf,
				    1, _(type[i].label),
				    -1);
533
		g_object_unref (pixbuf);
Morten Welinder's avatar
Morten Welinder committed
534

535 536
		if (strcmp (G_OBJECT_TYPE_NAME (state->link),
			    type [i].name) == 0)
Jody Goldberg's avatar
Jody Goldberg committed
537 538
			select = i;
	}
Morten Welinder's avatar
Morten Welinder committed
539

540 541
	renderer = gtk_cell_renderer_pixbuf_new ();
	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w),
542 543
				    renderer,
				    FALSE);
544
	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer,
545 546
					"pixbuf", 0,
					NULL);
Morten Welinder's avatar
Morten Welinder committed
547

548 549
	renderer = gtk_cell_renderer_text_new ();
	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w),
550 551
				    renderer,
				    TRUE);
552
	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer,
553 554
					"text", 1,
					NULL);
555
	gtk_combo_box_set_active (GTK_COMBO_BOX (w), select);
Morten Welinder's avatar
Morten Welinder committed
556

557
	g_signal_connect (G_OBJECT (w), "changed",
558 559
			  G_CALLBACK (dhl_cb_menu_changed),
			  state);
Morten Welinder's avatar
Morten Welinder committed
560

Morten Welinder's avatar
Morten Welinder committed
561 562
	gnm_link_button_and_entry (go_gtk_builder_get_widget (state->gui, "use-this-tip"),
				   go_gtk_builder_get_widget (state->gui, "tip-entry"));
Jody Goldberg's avatar
Jody Goldberg committed
563

Morten Welinder's avatar
Morten Welinder committed
564
	gnm_dialog_setup_destroy_handlers (GTK_DIALOG (state->dialog),
565 566
					   state->wbcg,
					   GNM_DIALOG_DESTROY_CURRENT_SHEET_REMOVED);
Morten Welinder's avatar
Morten Welinder committed
567

Jody Goldberg's avatar
Jody Goldberg committed
568 569 570 571 572
	return FALSE;
}

#define DIALOG_KEY "hyperlink-dialog"
void
573
dialog_hyperlink (WBCGtk *wbcg, SheetControl *sc)
Jody Goldberg's avatar
Jody Goldberg committed
574
{
575
	GtkBuilder *gui;
Jody Goldberg's avatar
Jody Goldberg committed
576
	HyperlinkState* state;
577
	GnmHLink	*link = NULL;
578
	GSList		*ptr;
Jody Goldberg's avatar
Jody Goldberg committed
579 580 581

	g_return_if_fail (wbcg != NULL);

Morten Welinder's avatar
Morten Welinder committed
582
	if (gnm_dialog_raise_if_exists (wbcg, DIALOG_KEY))
Jody Goldberg's avatar
Jody Goldberg committed
583 584
		return;

585
	gui = gnm_gtk_builder_load ("res:ui/hyperlink.ui", NULL, GO_CMD_CONTEXT (wbcg));
586
        if (gui == NULL)
587 588
                return;

Jody Goldberg's avatar
Jody Goldberg committed
589 590
	state = g_new (HyperlinkState, 1);
	state->wbcg  = wbcg;
Morten Welinder's avatar
Morten Welinder committed
591
	state->wb   = wb_control_get_workbook (GNM_WBC (wbcg));
592
	state->sc   = sc;
593
	state->gui  = gui;
Morten Welinder's avatar
Morten Welinder committed
594
        state->dialog = go_gtk_builder_get_widget (state->gui, "hyperlink-dialog");
Jody Goldberg's avatar
Jody Goldberg committed
595

596 597
	state->use_def_widget = go_gtk_builder_get_widget (state->gui, "use-default-tip");

598
	state->sheet = sc_sheet (sc);
599 600 601 602
	for (ptr = sc_view (sc)->selections; ptr != NULL; ptr = ptr->next) {
		GnmRange const *r = ptr->data;
		link = sheet_style_region_contains_link (state->sheet, r);
		if (link)
603
			break;
604
	}
Morten Welinder's avatar
Morten Welinder committed
605

606 607 608
	/* We are creating a new link since the existing link */
	/* may be used in many places. */
	/* We are duplicating it here rather than in an ok handler in case */
609
	/* The link is changed for a differnet cell in a different view. */
610
	if (link == NULL) {
611
		state->link = gnm_hlink_new (gnm_hlink_url_get_type (), state->sheet);
612
		state->is_new = TRUE;
613
	} else {
614
		state->link = gnm_hlink_new (G_OBJECT_TYPE (link), state->sheet);
615
		state->is_new = FALSE;
616 617
		gnm_hlink_set_target (state->link, gnm_hlink_get_target (link));
		gnm_hlink_set_tip (state->link, gnm_hlink_get_tip (link));
618
	}
Morten Welinder's avatar
Morten Welinder committed
619

620
	if (dhl_init (state)) {
Jody Goldberg's avatar
Jody Goldberg committed
621
		go_gtk_notice_dialog (wbcg_toplevel (wbcg), GTK_MESSAGE_ERROR,
Jody Goldberg's avatar
Jody Goldberg committed
622 623 624 625 626
				 _("Could not create the hyperlink dialog."));
		g_free (state);
		return;
	}

627 628 629 630
	dhl_setup_type (state);

	dhl_set_target (state);
	dhl_set_tip (state);
Jody Goldberg's avatar
Jody Goldberg committed
631

Jody Goldberg's avatar
Jody Goldberg committed
632
	/* a candidate for merging into attach guru */
Morten Welinder's avatar
Morten Welinder committed
633
	gnm_keyed_dialog (state->wbcg, GTK_WINDOW (state->dialog),
Jody Goldberg's avatar
Jody Goldberg committed
634
			       DIALOG_KEY);
Jody Goldberg's avatar
Jody Goldberg committed
635
	go_gtk_nonmodal_dialog (wbcg_toplevel (state->wbcg),
636
				   GTK_WINDOW (state->dialog));
637 638 639 640

	wbc_gtk_attach_guru (state->wbcg, state->dialog);
	g_object_set_data_full (G_OBJECT (state->dialog),
		"state", state, (GDestroyNotify) dhl_free);
Jody Goldberg's avatar
Jody Goldberg committed
641 642
	gtk_widget_show (state->dialog);
}