gedit-preferences-dialog.c 27.9 KB
Newer Older
1 2 3 4 5
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * gedit-preferences-dialog.c
 * This file is part of gedit
 *
6
 * Copyright (C) 2001-2005 Paolo Maggi
7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This program is free software; you can redistribute it and/or 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) any later version.
 *
 * 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
19
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 21
 */

Paolo Maggi's avatar
Paolo Maggi committed
22 23 24 25
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

26 27
#include "gedit-preferences-dialog.h"

28
#include <stdio.h>
Paolo Maggi's avatar
Paolo Maggi committed
29
#include <string.h>
30
#include <errno.h>
Paolo Maggi's avatar
Paolo Maggi committed
31

Paolo Borelli's avatar
Paolo Borelli committed
32
#include <glib/gi18n.h>
33
#include <glib/gstdio.h>
34
#include <gtksourceview/gtksource.h>
Garrett Regier's avatar
Garrett Regier committed
35
#include <libpeas-gtk/peas-gtk.h>
Paolo Maggi's avatar
Paolo Maggi committed
36 37 38

#include "gedit-utils.h"
#include "gedit-debug.h"
Paolo Borelli's avatar
Paolo Borelli committed
39
#include "gedit-document.h"
40
#include "gedit-dirs.h"
41 42
#include "gedit-settings.h"
#include "gedit-utils.h"
43
#include "gedit-file-chooser-dialog.h"
44 45
#include "gedit-app.h"
#include "gedit-app-private.h"
Paolo Borelli's avatar
Paolo Borelli committed
46 47 48 49 50 51 52 53 54 55 56 57

/*
 * gedit-preferences dialog is a singleton since we don't
 * want two dialogs showing an inconsistent state of the
 * preferences.
 * When gedit_show_preferences_dialog is called and there
 * is already a prefs dialog dialog open, it is reparented
 * and shown.
 */

static GtkWidget *preferences_dialog = NULL;

58
#define GEDIT_SCHEME_ROW_ID_KEY "gedit-scheme-row-id"
59

60 61 62 63
#define GEDIT_TYPE_PREFERENCES_DIALOG (gedit_preferences_dialog_get_type())

G_DECLARE_FINAL_TYPE (GeditPreferencesDialog, gedit_preferences_dialog, GEDIT, PREFERENCES_DIALOG, GtkWindow)

64 65
enum
{
66 67 68
	ID_COLUMN = 0,
	NAME_COLUMN,
	DESC_COLUMN,
69 70 71
	NUM_COLUMNS
};

72 73 74 75 76 77 78 79
enum
{
	CLOSE,
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL];

80
struct _GeditPreferencesDialog
81
{
82 83
	GtkWindow	parent_instance;

84
	GSettings	*editor;
85
	GSettings	*uisettings; /* unfortunately our settings are split for historical reasons */
86

87 88
	GtkWidget	*notebook;

89
	/* Font */
90
	GtkWidget	*default_font_checkbutton;
91
	GtkWidget	*font_button;
92
	GtkWidget	*font_grid;
Paolo Borelli's avatar
Paolo Borelli committed
93

94
	/* Style Scheme */
95
	GtkWidget	*schemes_list;
96 97
	GtkWidget	*install_scheme_button;
	GtkWidget	*uninstall_scheme_button;
98 99 100
	GtkWidget	*schemes_scrolled_window;
	GtkWidget	*schemes_toolbar;

101 102
	GeditFileChooserDialog *
			 install_scheme_file_schooser;
103

Paolo Maggi's avatar
Paolo Maggi committed
104
	/* Tabs */
105
	GtkWidget	*tabs_width_spinbutton;
106
	GtkWidget	*insert_spaces_checkbutton;
Paolo Borelli's avatar
Paolo Borelli committed
107

Paolo Maggi's avatar
Paolo Maggi committed
108
	/* Auto indentation */
109
	GtkWidget	*auto_indent_checkbutton;
110

Paolo Maggi's avatar
Paolo Maggi committed
111
	/* Text Wrapping */
Paolo Maggi's avatar
Paolo Maggi committed
112 113
	GtkWidget	*wrap_text_checkbutton;
	GtkWidget	*split_checkbutton;
Paolo Maggi's avatar
Paolo Maggi committed
114

Paolo Maggi's avatar
Paolo Maggi committed
115
	/* File Saving */
Paolo Maggi's avatar
Paolo Maggi committed
116
	GtkWidget	*backup_copy_checkbutton;
117 118
	GtkWidget	*auto_save_checkbutton;
	GtkWidget	*auto_save_spinbutton;
119

120
	GtkWidget	*display_line_numbers_checkbutton;
121
	GtkWidget	*display_statusbar_checkbutton;
122 123
	GtkWidget	*display_overview_map_checkbutton;
	GtkWidget	*display_grid_checkbutton;
124

Paolo Maggi's avatar
Paolo Maggi committed
125 126
	/* Right margin */
	GtkWidget	*right_margin_checkbutton;
127
	GtkWidget       *right_margin_position_grid;
Paolo Maggi's avatar
Paolo Maggi committed
128
	GtkWidget	*right_margin_position_spinbutton;
129 130 131 132

	/* Highlighting */
	GtkWidget	*highlight_current_line_checkbutton;
	GtkWidget	*bracket_matching_checkbutton;
Paolo Maggi's avatar
Paolo Maggi committed
133

134 135
	/* Plugin manager */
	GtkWidget	*plugin_manager;
136 137
};

138
G_DEFINE_TYPE (GeditPreferencesDialog, gedit_preferences_dialog, GTK_TYPE_WINDOW)
Paolo Borelli's avatar
Paolo Borelli committed
139

140 141 142 143 144
static void
gedit_preferences_dialog_dispose (GObject *object)
{
	GeditPreferencesDialog *dlg = GEDIT_PREFERENCES_DIALOG (object);

145 146
	g_clear_object (&dlg->editor);
	g_clear_object (&dlg->uisettings);
147 148 149 150

	G_OBJECT_CLASS (gedit_preferences_dialog_parent_class)->dispose (object);
}

151 152 153 154 155 156
static void
gedit_preferences_dialog_close (GeditPreferencesDialog *dialog)
{
	gtk_window_close (GTK_WINDOW (dialog));
}

Paolo Maggi's avatar
Paolo Maggi committed
157
static void
158
gedit_preferences_dialog_class_init (GeditPreferencesDialogClass *klass)
159
{
160 161
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
162
	GtkBindingSet *binding_set;
163

Garrett Regier's avatar
Garrett Regier committed
164 165 166
	/* Otherwise libpeas-gtk might not be linked */
	g_type_ensure (PEAS_GTK_TYPE_PLUGIN_MANAGER);

167
	object_class->dispose = gedit_preferences_dialog_dispose;
168

169 170 171 172 173 174 175 176
	signals[CLOSE] =
		g_signal_new_class_handler ("close",
		                            G_TYPE_FROM_CLASS (klass),
		                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		                            G_CALLBACK (gedit_preferences_dialog_close),
		                            NULL, NULL, NULL,
		                            G_TYPE_NONE,
		                            0);
177 178 179

	binding_set = gtk_binding_set_by_class (klass);
	gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
180

181 182 183
	/* Bind class to template */
	gtk_widget_class_set_template_from_resource (widget_class,
	                                             "/org/gnome/gedit/ui/gedit-preferences-dialog.ui");
184 185 186
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, notebook);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_line_numbers_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_statusbar_checkbutton);
187
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_grid_checkbutton);
188
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, display_overview_map_checkbutton);
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, right_margin_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, right_margin_position_grid);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, right_margin_position_spinbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, highlight_current_line_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, bracket_matching_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, wrap_text_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, split_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, tabs_width_spinbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, insert_spaces_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_indent_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, backup_copy_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_save_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, auto_save_spinbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, default_font_checkbutton);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_button);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, font_grid);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_list);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_scrolled_window);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, install_scheme_button);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, uninstall_scheme_button);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, schemes_toolbar);
	gtk_widget_class_bind_template_child (widget_class, GeditPreferencesDialog, plugin_manager);
211 212
}

Paolo Maggi's avatar
Paolo Maggi committed
213 214
static void
setup_editor_page (GeditPreferencesDialog *dlg)
215
{
Paolo Borelli's avatar
Paolo Borelli committed
216
	gedit_debug (DEBUG_PREFS);
217

Paolo Maggi's avatar
Paolo Maggi committed
218
	/* Connect signal */
219
	g_settings_bind (dlg->editor,
220
			 GEDIT_SETTINGS_TABS_SIZE,
221
			 dlg->tabs_width_spinbutton,
222 223
			 "value",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
224
	g_settings_bind (dlg->editor,
225
			 GEDIT_SETTINGS_INSERT_SPACES,
226
			 dlg->insert_spaces_checkbutton,
227 228
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
229
	g_settings_bind (dlg->editor,
230
			 GEDIT_SETTINGS_AUTO_INDENT,
231
			 dlg->auto_indent_checkbutton,
232 233
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
234
	g_settings_bind (dlg->editor,
235
			 GEDIT_SETTINGS_CREATE_BACKUP_COPY,
236
			 dlg->backup_copy_checkbutton,
237 238
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
239
	g_settings_bind (dlg->editor,
240
			 GEDIT_SETTINGS_BRACKET_MATCHING,
241
			 dlg->bracket_matching_checkbutton,
242 243
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
244
	g_settings_bind (dlg->editor,
245
			 GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
246
			 dlg->auto_save_spinbutton,
247 248
			 "value",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
249
	g_settings_bind (dlg->editor,
250
			 GEDIT_SETTINGS_AUTO_SAVE,
251
			 dlg->auto_save_spinbutton,
252 253
			 "sensitive",
			 G_SETTINGS_BIND_GET);
254
	g_settings_bind (dlg->editor,
255
			 GEDIT_SETTINGS_AUTO_SAVE,
256
			 dlg->auto_save_checkbutton,
257 258
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
Paolo Maggi's avatar
Paolo Maggi committed
259 260
}

261
static void
262
wrap_mode_checkbutton_toggled (GtkToggleButton        *button,
Paolo Maggi's avatar
Paolo Maggi committed
263
			       GeditPreferencesDialog *dlg)
264
{
265 266
	GtkWrapMode mode;

267
	if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton)))
Paolo Maggi's avatar
Paolo Maggi committed
268
	{
269 270
		mode = GTK_WRAP_NONE;

271
		gtk_widget_set_sensitive (dlg->split_checkbutton,
Paolo Maggi's avatar
Paolo Maggi committed
272 273
					  FALSE);
		gtk_toggle_button_set_inconsistent (
274
			GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE);
Paolo Maggi's avatar
Paolo Maggi committed
275 276
	}
	else
277
	{
278
		gtk_widget_set_sensitive (dlg->split_checkbutton,
Paolo Maggi's avatar
Paolo Maggi committed
279 280 281
					  TRUE);

		gtk_toggle_button_set_inconsistent (
282
			GTK_TOGGLE_BUTTON (dlg->split_checkbutton), FALSE);
Paolo Maggi's avatar
Paolo Maggi committed
283 284


285
		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dlg->split_checkbutton)))
286
		{
287
			g_settings_set_enum (dlg->editor,
288 289
			                     GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE,
			                     GTK_WRAP_WORD);
290 291

			mode = GTK_WRAP_WORD;
Paolo Maggi's avatar
Paolo Maggi committed
292 293 294
		}
		else
		{
295
			g_settings_set_enum (dlg->editor,
296 297
			                     GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE,
			                     GTK_WRAP_CHAR);
298 299

			mode = GTK_WRAP_CHAR;
Paolo Maggi's avatar
Paolo Maggi committed
300 301
		}
	}
302

303
	g_settings_set_enum (dlg->editor,
304 305
			     GEDIT_SETTINGS_WRAP_MODE,
			     mode);
Paolo Maggi's avatar
Paolo Maggi committed
306 307
}

308 309 310 311 312 313 314 315 316 317 318 319 320 321
static void
grid_checkbutton_toggled (GtkToggleButton        *button,
                          GeditPreferencesDialog *dlg)
{
	GtkSourceBackgroundPatternType background_type;

	background_type = gtk_toggle_button_get_active (button) ?
	                  GTK_SOURCE_BACKGROUND_PATTERN_TYPE_GRID :
		          GTK_SOURCE_BACKGROUND_PATTERN_TYPE_NONE;
	g_settings_set_enum (dlg->editor,
	                     GEDIT_SETTINGS_BACKGROUND_PATTERN,
	                     background_type);
}

Paolo Maggi's avatar
Paolo Maggi committed
322 323 324 325
static void
setup_view_page (GeditPreferencesDialog *dlg)
{
	GtkWrapMode wrap_mode;
326
	GtkWrapMode last_split_mode;
327
	GtkSourceBackgroundPatternType background_pattern;
Paolo Maggi's avatar
Paolo Maggi committed
328
	gboolean display_right_margin;
329
	guint right_margin_position;
Paolo Maggi's avatar
Paolo Maggi committed
330

Paolo Borelli's avatar
Paolo Borelli committed
331
	gedit_debug (DEBUG_PREFS);
332

333
	/* Get values */
334
	display_right_margin = g_settings_get_boolean (dlg->editor,
335
						       GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN);
336
	g_settings_get (dlg->editor, GEDIT_SETTINGS_RIGHT_MARGIN_POSITION,
337
			"u", &right_margin_position);
338 339
	background_pattern = g_settings_get_enum (dlg->editor,
	                                          GEDIT_SETTINGS_BACKGROUND_PATTERN);
340

341
	wrap_mode = g_settings_get_enum (dlg->editor,
342
					 GEDIT_SETTINGS_WRAP_MODE);
Paolo Maggi's avatar
Paolo Maggi committed
343

344
	/* Set initial state */
345
	switch (wrap_mode)
Paolo Maggi's avatar
Paolo Maggi committed
346 347 348
	{
		case GTK_WRAP_WORD:
			gtk_toggle_button_set_active (
349
				GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), TRUE);
Paolo Maggi's avatar
Paolo Maggi committed
350
			gtk_toggle_button_set_active (
351
				GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE);
352

353
			g_settings_set_enum (dlg->editor,
354 355
			                     GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE,
			                     GTK_WRAP_WORD);
Paolo Maggi's avatar
Paolo Maggi committed
356 357 358
			break;
		case GTK_WRAP_CHAR:
			gtk_toggle_button_set_active (
359
				GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), TRUE);
Paolo Maggi's avatar
Paolo Maggi committed
360
			gtk_toggle_button_set_active (
361
				GTK_TOGGLE_BUTTON (dlg->split_checkbutton), FALSE);
362

363
			g_settings_set_enum (dlg->editor,
364 365
			                     GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE,
			                     GTK_WRAP_CHAR);
Paolo Maggi's avatar
Paolo Maggi committed
366 367 368
			break;
		default:
			gtk_toggle_button_set_active (
369
				GTK_TOGGLE_BUTTON (dlg->wrap_text_checkbutton), FALSE);
370

371
			last_split_mode = g_settings_get_enum (dlg->editor,
372
			                                       GEDIT_SETTINGS_WRAP_LAST_SPLIT_MODE);
373
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dlg->split_checkbutton),
374 375
			                              last_split_mode == GTK_WRAP_WORD);

Paolo Maggi's avatar
Paolo Maggi committed
376
			gtk_toggle_button_set_inconsistent (
377
				GTK_TOGGLE_BUTTON (dlg->split_checkbutton), TRUE);
Paolo Maggi's avatar
Paolo Maggi committed
378
	}
379

Paolo Maggi's avatar
Paolo Maggi committed
380
	gtk_toggle_button_set_active (
381
		GTK_TOGGLE_BUTTON (dlg->right_margin_checkbutton),
Paolo Maggi's avatar
Paolo Maggi committed
382
		display_right_margin);
383 384 385
	gtk_toggle_button_set_active (
		GTK_TOGGLE_BUTTON (dlg->display_grid_checkbutton),
		background_pattern == GTK_SOURCE_BACKGROUND_PATTERN_TYPE_GRID);
386

Paolo Maggi's avatar
Paolo Maggi committed
387
	/* Set widgets sensitivity */
388
	gtk_widget_set_sensitive (dlg->split_checkbutton,
Paolo Maggi's avatar
Paolo Maggi committed
389
				  (wrap_mode != GTK_WRAP_NONE));
390

391
	g_settings_bind (dlg->editor,
392
			 GEDIT_SETTINGS_DISPLAY_LINE_NUMBERS,
393
			 dlg->display_line_numbers_checkbutton,
394 395
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
396
	g_settings_bind (dlg->editor,
397
			 GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE,
398
			 dlg->highlight_current_line_checkbutton,
399 400
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
401
	g_settings_bind (dlg->uisettings,
402
	                 GEDIT_SETTINGS_STATUSBAR_VISIBLE,
403
	                 dlg->display_statusbar_checkbutton,
404 405
	                 "active",
	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
406 407 408 409 410
	g_settings_bind (dlg->editor,
			 GEDIT_SETTINGS_DISPLAY_OVERVIEW_MAP,
			 dlg->display_overview_map_checkbutton,
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
411
	g_settings_bind (dlg->editor,
412
	                 GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
413
	                 dlg->right_margin_checkbutton,
414 415
	                 "active",
	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
416
	g_settings_bind (dlg->editor,
417
	                 GEDIT_SETTINGS_DISPLAY_RIGHT_MARGIN,
418
	                 dlg->right_margin_position_grid,
419 420
	                 "sensitive",
	                 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
421
	g_settings_bind (dlg->editor,
422
			 GEDIT_SETTINGS_RIGHT_MARGIN_POSITION,
423
			 dlg->right_margin_position_spinbutton,
424
			 "value",
425
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
426
	g_settings_bind (dlg->editor,
427
			 GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
428
			 dlg->auto_save_spinbutton,
429 430
			 "value",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
431
	g_signal_connect (dlg->wrap_text_checkbutton,
432 433
			  "toggled",
			  G_CALLBACK (wrap_mode_checkbutton_toggled),
Paolo Maggi's avatar
Paolo Maggi committed
434
			  dlg);
435
	g_signal_connect (dlg->split_checkbutton,
436
			  "toggled",
437
			  G_CALLBACK (wrap_mode_checkbutton_toggled),
Paolo Maggi's avatar
Paolo Maggi committed
438
			  dlg);
439 440 441 442
	g_signal_connect (dlg->display_grid_checkbutton,
			  "toggled",
			  G_CALLBACK (grid_checkbutton_toggled),
			  dlg);
443 444
}

Paolo Maggi's avatar
Paolo Maggi committed
445
static void
446
setup_font_colors_page_font_section (GeditPreferencesDialog *dlg)
447
{
448
	GeditSettings *settings;
449
	gchar *system_font = NULL;
450
	gchar *label;
Paolo Maggi's avatar
Paolo Maggi committed
451

Paolo Borelli's avatar
Paolo Borelli committed
452
	gedit_debug (DEBUG_PREFS);
Hema Seetharamaiah's avatar
Hema Seetharamaiah committed
453

454
	gtk_widget_set_tooltip_text (dlg->font_button,
455
			 _("Click on this button to select the font to be used by the editor"));
456

457
	/* Get values */
458
	settings = _gedit_app_get_settings (GEDIT_APP (g_application_get_default ()));
459
	system_font = gedit_settings_get_system_font (settings);
460 461

	label = g_strdup_printf(_("_Use the system fixed width font (%s)"),
462
				system_font);
463
	gtk_button_set_label (GTK_BUTTON (dlg->default_font_checkbutton),
464
			      label);
465
	g_free (system_font);
466
	g_free (label);
Paolo Maggi's avatar
Paolo Maggi committed
467

468
	/* Bind settings */
469
	g_settings_bind (dlg->editor,
470
			 GEDIT_SETTINGS_USE_DEFAULT_FONT,
471
			 dlg->default_font_checkbutton,
472 473
			 "active",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
474
	g_settings_bind (dlg->editor,
475
			 GEDIT_SETTINGS_USE_DEFAULT_FONT,
476
			 dlg->font_grid,
477 478
			 "sensitive",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET | G_SETTINGS_BIND_INVERT_BOOLEAN);
479
	g_settings_bind (dlg->editor,
480
			 GEDIT_SETTINGS_EDITOR_FONT,
481
			 dlg->font_button,
482 483
			 "font-name",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
484 485
}

486 487 488
static void
set_buttons_sensisitivity_according_to_scheme (GeditPreferencesDialog *dlg,
                                               GtkSourceStyleScheme   *scheme)
489
{
490
	gboolean editable = FALSE;
491 492 493 494 495 496 497 498

	if (scheme != NULL)
	{
		const gchar *filename;

		filename = gtk_source_style_scheme_get_filename (scheme);
		if (filename != NULL)
		{
499
			editable = g_str_has_prefix (filename, gedit_dirs_get_user_styles_dir ());
500 501 502
		}
	}

503
	gtk_widget_set_sensitive (dlg->uninstall_scheme_button,
504
	                          editable);
505 506 507
}

static void
508 509 510
style_scheme_changed (GtkSourceStyleSchemeChooser *chooser,
                      GParamSpec                  *pspec,
                      GeditPreferencesDialog      *dlg)
511
{
512 513
	GtkSourceStyleScheme *scheme;
	const gchar *id;
514

515 516
	scheme = gtk_source_style_scheme_chooser_get_style_scheme (chooser);
	id = gtk_source_style_scheme_get_id (scheme);
517

518
	g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME, id);
519
	set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
520 521
}

522 523
static GtkSourceStyleScheme *
get_default_color_scheme (GeditPreferencesDialog *dlg)
524
{
525
	GtkSourceStyleSchemeManager *manager;
526
	GtkSourceStyleScheme *scheme = NULL;
527
	gchar *pref_id;
528

529
	manager = gtk_source_style_scheme_manager_get_default ();
530

531
	pref_id = g_settings_get_string (dlg->editor,
532
	                                 GEDIT_SETTINGS_SCHEME);
533

534 535 536
	scheme = gtk_source_style_scheme_manager_get_scheme (manager,
	                                                     pref_id);
	g_free (pref_id);
537

538 539 540 541
	if (scheme == NULL)
	{
		/* Fall-back to classic style scheme */
		scheme = gtk_source_style_scheme_manager_get_scheme (manager,
542
		                                                     "classic");
543
	}
544

545
	return scheme;
546 547
}

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
/*
 * file_copy:
 * @name: a pointer to a %NULL-terminated string, that names
 * the file to be copied, in the GLib file name encoding
 * @dest_name: a pointer to a %NULL-terminated string, that is the
 * name for the destination file, in the GLib file name encoding
 * @error: return location for a #GError, or %NULL
 *
 * Copies file @name to @dest_name.
 *
 * If the call was successful, it returns %TRUE. If the call was not
 * successful, it returns %FALSE and sets @error. The error domain
 * is #G_FILE_ERROR. Possible error
 * codes are those in the #GFileError enumeration.
 *
 * Return value: %TRUE on success, %FALSE otherwise.
 */
static gboolean
file_copy (const gchar  *name,
	   const gchar  *dest_name,
	   GError      **error)
{
	gchar *contents;
	gsize length;
	gchar *dest_dir;

	/* FIXME - Paolo (Aug. 13, 2007):
	 * Since the style scheme files are relatively small, we can implement
	 * file copy getting all the content of the source file in a buffer and
	 * then write the content to the destination file. In this way we
	 * can use the g_file_get_contents and g_file_set_contents and avoid to
	 * write custom code to copy the file (with sane error management).
	 * If needed we can improve this code later. */

	g_return_val_if_fail (name != NULL, FALSE);
	g_return_val_if_fail (dest_name != NULL, FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	/* Note: we allow to copy a file to itself since this is not a problem
	 * in our use case */

	/* Ensure the destination directory exists */
	dest_dir = g_path_get_dirname (dest_name);

	errno = 0;
	if (g_mkdir_with_parents (dest_dir, 0755) != 0)
	{
		gint save_errno = errno;
		gchar *display_filename = g_filename_display_name (dest_dir);

		g_set_error (error,
			     G_FILE_ERROR,
			     g_file_error_from_errno (save_errno),
601
			     _("Directory “%s” could not be created: g_mkdir_with_parents() failed: %s"),
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
			     display_filename,
			     g_strerror (save_errno));

		g_free (dest_dir);
		g_free (display_filename);

		return FALSE;
	}

	g_free (dest_dir);

	if (!g_file_get_contents (name, &contents, &length, error))
		return FALSE;

	if (!g_file_set_contents (dest_name, contents, length, error))
617 618
	{
		g_free (contents);
619
		return FALSE;
620
	}
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641

	g_free (contents);

	return TRUE;
}

/*
 * install_style_scheme:
 * @manager: a #GtkSourceStyleSchemeManager
 * @fname: the file name of the style scheme to be installed
 *
 * Install a new user scheme.
 * This function copies @fname in #GEDIT_STYLES_DIR and ask the style manager to
 * recompute the list of available style schemes. It then checks if a style
 * scheme with the right file name exists.
 *
 * If the call was succesful, it returns the id of the installed scheme
 * otherwise %NULL.
 *
 * Return value: the id of the installed scheme, %NULL otherwise.
 */
642
static GtkSourceStyleScheme *
643 644 645 646 647 648 649 650
install_style_scheme (const gchar *fname)
{
	GtkSourceStyleSchemeManager *manager;
	gchar *new_file_name = NULL;
	gchar *dirname;
	const gchar *styles_dir;
	GError *error = NULL;
	gboolean copied = FALSE;
651
	const gchar * const *ids;
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671

	g_return_val_if_fail (fname != NULL, NULL);

	manager = gtk_source_style_scheme_manager_get_default ();

	dirname = g_path_get_dirname (fname);
	styles_dir = gedit_dirs_get_user_styles_dir ();

	if (strcmp (dirname, styles_dir) != 0)
	{
		gchar *basename;

		basename = g_path_get_basename (fname);
		new_file_name = g_build_filename (styles_dir, basename, NULL);
		g_free (basename);

		/* Copy the style scheme file into GEDIT_STYLES_DIR */
		if (!file_copy (fname, new_file_name, &error))
		{
			g_free (new_file_name);
672
			g_free (dirname);
673 674 675 676

			g_message ("Cannot install style scheme:\n%s",
				   error->message);

677 678
			g_error_free (error);

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
			return NULL;
		}

		copied = TRUE;
	}
	else
	{
		new_file_name = g_strdup (fname);
	}

	g_free (dirname);

	/* Reload the available style schemes */
	gtk_source_style_scheme_manager_force_rescan (manager);

	/* Check the new style scheme has been actually installed */
	ids = gtk_source_style_scheme_manager_get_scheme_ids (manager);

	while (*ids != NULL)
	{
		GtkSourceStyleScheme *scheme;
		const gchar *filename;

		scheme = gtk_source_style_scheme_manager_get_scheme (manager, *ids);

		filename = gtk_source_style_scheme_get_filename (scheme);

		if (filename && (strcmp (filename, new_file_name) == 0))
		{
			/* The style scheme has been correctly installed */
			g_free (new_file_name);

711
			return scheme;
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
		}
		++ids;
	}

	/* The style scheme has not been correctly installed */
	if (copied)
		g_unlink (new_file_name);

	g_free (new_file_name);

	return NULL;
}

/**
 * uninstall_style_scheme:
 * @manager: a #GtkSourceStyleSchemeManager
728
 * @scheme: a #GtkSourceStyleScheme
729 730 731 732 733 734 735 736 737
 *
 * Uninstall a user scheme.
 *
 * If the call was succesful, it returns %TRUE
 * otherwise %FALSE.
 *
 * Return value: %TRUE on success, %FALSE otherwise.
 */
static gboolean
738
uninstall_style_scheme (GtkSourceStyleScheme *scheme)
739 740 741 742
{
	GtkSourceStyleSchemeManager *manager;
	const gchar *filename;

743
	g_return_val_if_fail (GTK_SOURCE_IS_STYLE_SCHEME (scheme), FALSE);
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759

	manager = gtk_source_style_scheme_manager_get_default ();

	filename = gtk_source_style_scheme_get_filename (scheme);
	if (filename == NULL)
		return FALSE;

	if (g_unlink (filename) == -1)
		return FALSE;

	/* Reload the available style schemes */
	gtk_source_style_scheme_manager_force_rescan (manager);

	return TRUE;
}

760
static void
761
add_scheme_chooser_response_cb (GeditFileChooserDialog *chooser,
762 763 764
				gint                    res_id,
				GeditPreferencesDialog *dlg)
{
765 766
	GFile *file;
	gchar *filename;
767
	GtkSourceStyleScheme *scheme;
768

769 770
	if (res_id != GTK_RESPONSE_ACCEPT)
	{
771
		gedit_file_chooser_dialog_hide (chooser);
772 773
		return;
	}
774

775 776 777 778 779 780 781 782 783 784
	file = gedit_file_chooser_dialog_get_file (chooser);

	if (file == NULL)
	{
		return;
	}

	filename = g_file_get_path (file);
	g_object_unref (file);

785
	if (filename == NULL)
786
	{
787
		return;
788
	}
789

790
	gedit_file_chooser_dialog_hide (chooser);
791

792
	scheme = install_style_scheme (filename);
793
	g_free (filename);
794

795
	if (scheme == NULL)
796 797
	{
		gedit_warning (GTK_WINDOW (dlg),
798
		               _("The selected color scheme cannot be installed."));
799 800 801

		return;
	}
802

803
	g_settings_set_string (dlg->editor, GEDIT_SETTINGS_SCHEME,
804
	                       gtk_source_style_scheme_get_id (scheme));
805

806
	set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
807
}
808

809 810 811 812
static void
install_scheme_clicked (GtkButton              *button,
			GeditPreferencesDialog *dlg)
{
813
	GeditFileChooserDialog *chooser;
814

815
	if (dlg->install_scheme_file_schooser != NULL)
Garrett Regier's avatar
Garrett Regier committed
816
	{
817
		gedit_file_chooser_dialog_show (dlg->install_scheme_file_schooser);
818
		return;
819
	}
820

821 822 823 824 825 826
	chooser = gedit_file_chooser_dialog_create (_("Add Scheme"),
						    GTK_WINDOW (dlg),
						    GEDIT_FILE_CHOOSER_OPEN,
						    NULL,
						    _("_Cancel"), GTK_RESPONSE_CANCEL,
						    _("A_dd Scheme"), GTK_RESPONSE_ACCEPT);
827

828
	/* Filters */
829 830 831
	gedit_file_chooser_dialog_add_pattern_filter (chooser,
	                                              _("Color Scheme Files"),
	                                              "*.xml");
832

833 834 835
	gedit_file_chooser_dialog_add_pattern_filter (chooser,
	                                              _("All Files"),
	                                              "*");
836

837 838 839 840 841
	g_signal_connect (chooser,
			  "response",
			  G_CALLBACK (add_scheme_chooser_response_cb),
			  dlg);

842
	dlg->install_scheme_file_schooser = chooser;
843

844
	g_object_add_weak_pointer (G_OBJECT (chooser),
845
				   (gpointer) &dlg->install_scheme_file_schooser);
846

847
	gedit_file_chooser_dialog_show (chooser);
848
}
849

850
static void
851 852
uninstall_scheme_clicked (GtkButton              *button,
			  GeditPreferencesDialog *dlg)
853
{
854
	GtkSourceStyleScheme *scheme;
855

856
	scheme = gtk_source_style_scheme_chooser_get_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list));
857

858 859 860
	if (!uninstall_style_scheme (scheme))
	{
		gedit_warning (GTK_WINDOW (dlg),
861
		               _("Could not remove color scheme “%s”."),
862
		               gtk_source_style_scheme_get_name (scheme));
863 864 865 866 867 868
	}
}

static void
setup_font_colors_page_style_scheme_section (GeditPreferencesDialog *dlg)
{
869
	GtkStyleContext *context;
870
	GtkSourceStyleScheme *scheme;
871

872
	gedit_debug (DEBUG_PREFS);
873

874
	scheme = get_default_color_scheme (dlg);
875 876

	/* junction between the scrolled window and the toolbar */
877
	context = gtk_widget_get_style_context (dlg->schemes_scrolled_window);
878
	gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
879
	context = gtk_widget_get_style_context (dlg->schemes_toolbar);
880 881
	gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);

882
	/* Connect signals */
883
	g_signal_connect (dlg->schemes_list,
884 885 886
	                  "notify::style-scheme",
	                  G_CALLBACK (style_scheme_changed),
	                  dlg);
887
	g_signal_connect (dlg->install_scheme_button,
888
			  "clicked",
889
			  G_CALLBACK (install_scheme_clicked),
890
			  dlg);
891
	g_signal_connect (dlg->uninstall_scheme_button,
892
			  "clicked",
893
			  G_CALLBACK (uninstall_scheme_clicked),
894
			  dlg);
895

896
	gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (dlg->schemes_list),
897 898
	                                                  scheme);

899
	/* Set initial widget sensitivity */
900
	set_buttons_sensisitivity_according_to_scheme (dlg, scheme);
901 902 903 904 905 906 907
}

static void
setup_font_colors_page (GeditPreferencesDialog *dlg)
{
	setup_font_colors_page_font_section (dlg);
	setup_font_colors_page_style_scheme_section (dlg);
908
}
909

910
static void
Paolo Maggi's avatar
Paolo Maggi committed
911
setup_plugins_page (GeditPreferencesDialog *dlg)
912
{
913
	gtk_widget_show_all (dlg->plugin_manager);
914 915
}

Paolo Borelli's avatar
Paolo Borelli committed
916 917
static void
gedit_preferences_dialog_init (GeditPreferencesDialog *dlg)
Paolo Maggi's avatar
Paolo Maggi committed
918
{
Paolo Borelli's avatar
Paolo Borelli committed
919 920
	gedit_debug (DEBUG_PREFS);

921 922
	dlg->editor = g_settings_new ("org.gnome.gedit.preferences.editor");
	dlg->uisettings = g_settings_new ("org.gnome.gedit.preferences.ui");
Paolo Borelli's avatar
Paolo Borelli committed
923

924
	gtk_widget_init_template (GTK_WIDGET (dlg));
925

Paolo Borelli's avatar
Paolo Borelli committed
926 927 928 929
	setup_editor_page (dlg);
	setup_view_page (dlg);
	setup_font_colors_page (dlg);
	setup_plugins_page (dlg);
Paolo Maggi's avatar
Paolo Maggi committed
930
}
931

Paolo Maggi's avatar
Paolo Maggi committed
932
void
Paolo Borelli's avatar
Paolo Borelli committed
933
gedit_show_preferences_dialog (GeditWindow *parent)
934
{
Paolo Borelli's avatar
Paolo Borelli committed
935
	gedit_debug (DEBUG_PREFS);
936

Paolo Borelli's avatar
Paolo Borelli committed
937 938
	if (preferences_dialog == NULL)
	{
939 940 941
		preferences_dialog = GTK_WIDGET (g_object_new (GEDIT_TYPE_PREFERENCES_DIALOG,
							       "application", g_application_get_default (),
							       NULL));
Paolo Borelli's avatar
Paolo Borelli committed
942 943 944 945 946
		g_signal_connect (preferences_dialog,
				  "destroy",
				  G_CALLBACK (gtk_widget_destroyed),
				  &preferences_dialog);
	}
947

Paolo Borelli's avatar
Paolo Borelli committed
948 949 950 951 952
	if (GTK_WINDOW (parent) != gtk_window_get_transient_for (GTK_WINDOW (preferences_dialog)))
	{
		gtk_window_set_transient_for (GTK_WINDOW (preferences_dialog),
					      GTK_WINDOW (parent));
	}
953

Paolo Borelli's avatar
Paolo Borelli committed
954
	gtk_window_present (GTK_WINDOW (preferences_dialog));
955
}
Garrett Regier's avatar
Garrett Regier committed
956

957
/* ex:set ts=8 noet: */