1 /* Copyright (C) 2005 Emmanuele Bassi
2 * Copyright (C) 2012-2021 MATE Developers
3 *
4 * This file is part of MATE Utils.
5 *
6 * MATE Utils is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * MATE Utils is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with MATE Utils. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include <glib/gi18n.h>
34 #include <gio/gio.h>
35
36 #include "gdict-source-dialog.h"
37 #include "gdict-common.h"
38
39 #define GDICT_SOURCE_UI PKGDATADIR "/mate-dictionary-source.ui"
40 #define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (dialog->builder, (x))))
41 #define GET_EDITABLE(x) (GTK_EDITABLE (gtk_builder_get_object (dialog->builder, (x))))
42
43 /*********************
44 * GdictSourceDialog *
45 *********************/
46
47 struct _GdictSourceDialog
48 {
49 GtkDialog parent_instance;
50
51 GtkBuilder *builder;
52
53 GSettings *settings;
54
55 GdictSourceLoader *loader;
56 GdictSource *source;
57 gchar *source_name;
58 GdictContext *context;
59
60 GdictSourceDialogAction action;
61
62 GdictSourceTransport transport;
63
64 GtkWidget *add_button;
65 GtkWidget *close_button;
66 GtkWidget *cancel_button;
67 GtkWidget *help_button;
68
69 GtkWidget *db_chooser;
70 GtkWidget *strat_chooser;
71
72 GtkWidget *transport_combo;
73 };
74
75 struct _GdictSourceDialogClass
76 {
77 GtkDialogClass parent_class;
78 };
79
80 enum
81 {
82 PROP_0,
83
84 PROP_SOURCE_LOADER,
85 PROP_SOURCE_NAME,
86 PROP_ACTION
87 };
88
89 G_DEFINE_TYPE (GdictSourceDialog, gdict_source_dialog, GTK_TYPE_DIALOG);
90
91 static void
set_source_loader(GdictSourceDialog * dialog,GdictSourceLoader * loader)92 set_source_loader (GdictSourceDialog *dialog,
93 GdictSourceLoader *loader)
94 {
95 if (dialog->loader)
96 g_object_unref (dialog->loader);
97
98 dialog->loader = g_object_ref (loader);
99 }
100
101 static void
transport_combo_changed_cb(GtkWidget * widget,gpointer user_data)102 transport_combo_changed_cb (GtkWidget *widget,
103 gpointer user_data)
104 {
105 GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (user_data);
106 gint transport;
107
108 transport = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
109 if (transport == dialog->transport)
110 return;
111
112 if (transport == GDICT_SOURCE_TRANSPORT_DICTD)
113 {
114 gtk_widget_show (GET_WIDGET ("hostname_label"));
115 gtk_widget_show (GET_WIDGET ("hostname_entry"));
116 gtk_widget_show (GET_WIDGET ("port_label"));
117 gtk_widget_show (GET_WIDGET ("port_entry"));
118
119 if (dialog->action == GDICT_SOURCE_DIALOG_CREATE)
120 {
121 gtk_widget_set_sensitive (dialog->add_button, TRUE);
122
123 dialog->transport = GDICT_SOURCE_TRANSPORT_DICTD;
124 }
125 }
126 else
127 {
128 gtk_widget_hide (GET_WIDGET ("hostname_label"));
129 gtk_widget_hide (GET_WIDGET ("hostname_entry"));
130 gtk_widget_hide (GET_WIDGET ("port_label"));
131 gtk_widget_hide (GET_WIDGET ("port_entry"));
132
133 if (dialog->action == GDICT_SOURCE_DIALOG_CREATE)
134 {
135 gtk_widget_set_sensitive (dialog->add_button, FALSE);
136
137 dialog->transport = GDICT_SOURCE_TRANSPORT_INVALID;
138 }
139 }
140 }
141
142 static gchar *
get_text_from_entry(GdictSourceDialog * dialog,const gchar * entry_name)143 get_text_from_entry (GdictSourceDialog *dialog,
144 const gchar *entry_name)
145 {
146 GtkWidget *entry;
147 gchar *retval;
148
149 entry = GET_WIDGET (entry_name);
150 if (!entry)
151 return NULL;
152
153 retval = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
154
155 return retval;
156 }
157
158 static void
set_text_to_entry(GdictSourceDialog * dialog,const gchar * entry_name,const gchar * text)159 set_text_to_entry (GdictSourceDialog *dialog,
160 const gchar *entry_name,
161 const gchar *text)
162 {
163 GtkWidget *entry;
164
165 entry = GET_WIDGET (entry_name);
166 if (!entry)
167 return;
168
169 gtk_entry_set_text (GTK_ENTRY (entry), text);
170 }
171
172 static void
set_transport_settings(GdictSourceDialog * dialog)173 set_transport_settings (GdictSourceDialog *dialog)
174 {
175 switch (dialog->transport)
176 {
177 case GDICT_SOURCE_TRANSPORT_DICTD:
178 {
179 GdictClientContext *context;
180 const gchar *hostname;
181 gchar *port_str;
182 guint port;
183
184 context = GDICT_CLIENT_CONTEXT (dialog->context);
185 hostname = gdict_client_context_get_hostname (context);
186 port = gdict_client_context_get_port (context);
187 port_str = g_strdup_printf ("%d", port);
188
189 set_text_to_entry (dialog, "hostname_entry", hostname);
190 set_text_to_entry (dialog, "port_entry", port_str);
191
192 gtk_widget_show (GET_WIDGET ("hostname_label"));
193 gtk_widget_show (GET_WIDGET ("hostname_entry"));
194 gtk_widget_show (GET_WIDGET ("port_label"));
195 gtk_widget_show (GET_WIDGET ("port_entry"));
196
197 g_free (port_str);
198 }
199 break;
200 case GDICT_SOURCE_TRANSPORT_INVALID:
201 default:
202 break;
203 }
204 }
205
206 static void
update_dialog_ui(GdictSourceDialog * dialog)207 update_dialog_ui (GdictSourceDialog *dialog)
208 {
209 GdictSource *source;
210
211 /* TODO - add code to update the contents of the dialog depending
212 * on the action; if we are in _CREATE, no action is needed
213 */
214 switch (dialog->action)
215 {
216 case GDICT_SOURCE_DIALOG_VIEW:
217 case GDICT_SOURCE_DIALOG_EDIT:
218 if (!dialog->source_name)
219 {
220 g_warning ("Attempting to retrieve source, but no "
221 "source name has been defined. Aborting...");
222 return;
223 }
224
225 source = gdict_source_loader_get_source (dialog->loader,
226 dialog->source_name);
227 if (!source)
228 {
229 g_warning ("Attempting to retrieve source, but no "
230 "source named `%s' was found. Aborting...",
231 dialog->source_name);
232 return;
233 }
234
235 g_object_ref (source);
236
237 dialog->source = source;
238 set_text_to_entry (dialog, "description_entry",
239 gdict_source_get_description (source));
240
241 dialog->transport = gdict_source_get_transport (source);
242 gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->transport_combo),
243 (gint) dialog->transport);
244
245 /* set the context for the database and strategy choosers */
246 dialog->context = gdict_source_get_context (source);
247 if (!dialog->context)
248 {
249 g_warning ("Attempting to retrieve the context, but "
250 "none was found for source `%s'.",
251 dialog->source_name);
252 return;
253 }
254
255 set_transport_settings (dialog);
256
257 gdict_database_chooser_set_context (GDICT_DATABASE_CHOOSER (dialog->db_chooser),
258 dialog->context);
259 gdict_database_chooser_refresh (GDICT_DATABASE_CHOOSER (dialog->db_chooser));
260 gdict_strategy_chooser_set_context (GDICT_STRATEGY_CHOOSER (dialog->strat_chooser),
261 dialog->context);
262 gdict_strategy_chooser_refresh (GDICT_STRATEGY_CHOOSER (dialog->strat_chooser));
263 break;
264 case GDICT_SOURCE_DIALOG_CREATE:
265 /* DICTD transport is default */
266 gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->transport_combo), 0);
267 g_signal_emit_by_name (dialog->transport_combo, "changed");
268 break;
269 default:
270 g_assert_not_reached ();
271 break;
272 }
273 }
274
275 static void
build_new_source(GdictSourceDialog * dialog)276 build_new_source (GdictSourceDialog *dialog)
277 {
278 GdictSource *source;
279 gchar *name, *text;
280 GdictSourceTransport transport;
281 gchar *host, *port;
282 gchar *data;
283 gsize length;
284 GError *error;
285 gchar *filename;
286 GdictDatabaseChooser *db_chooser;
287 GdictStrategyChooser *strat_chooser;
288
289 source = gdict_source_new ();
290
291 /* use the timestamp and the pid to get a unique name */
292 name = g_strdup_printf ("source-%lu-%u",
293 (gulong) time (NULL),
294 (guint) getpid ());
295 gdict_source_set_name (source, name);
296 g_free (name);
297
298 text = get_text_from_entry (dialog, "description_entry");
299 gdict_source_set_description (source, text);
300 g_free (text);
301
302 db_chooser = GDICT_DATABASE_CHOOSER (dialog->db_chooser);
303 text = gdict_database_chooser_get_current_database (db_chooser);
304 gdict_source_set_database (source, text);
305 g_free (text);
306
307 strat_chooser = GDICT_STRATEGY_CHOOSER (dialog->strat_chooser);
308 text = gdict_strategy_chooser_get_current_strategy (strat_chooser);
309 gdict_source_set_strategy (source, text);
310 g_free (text);
311
312 /* get the selected transport id */
313 transport = dialog->transport;
314 switch (transport)
315 {
316 case GDICT_SOURCE_TRANSPORT_DICTD:
317 host = get_text_from_entry (dialog, "hostname_entry");
318 port = get_text_from_entry (dialog, "port_entry");
319
320 gdict_source_set_transport (source, GDICT_SOURCE_TRANSPORT_DICTD,
321 "hostname", host,
322 "port", atoi (port),
323 NULL);
324
325 g_free (host);
326 g_free (port);
327 break;
328 case GDICT_SOURCE_TRANSPORT_INVALID:
329 default:
330 g_warning ("Invalid transport");
331 return;
332 }
333
334 error = NULL;
335 data = gdict_source_to_data (source, &length, &error);
336 if (error)
337 {
338 gdict_show_gerror_dialog (GTK_WINDOW (dialog),
339 _("Unable to create a source file"),
340 error);
341
342 g_object_unref (source);
343 return;
344 }
345
346 name = g_strdup_printf ("%s.desktop", gdict_source_get_name (source));
347 filename = g_build_filename (g_get_user_config_dir (),
348 "mate",
349 "mate-dictionary",
350 name,
351 NULL);
352 g_free (name);
353
354 g_file_set_contents (filename, data, length, &error);
355 if (error)
356 gdict_show_gerror_dialog (GTK_WINDOW (dialog),
357 _("Unable to save source file"),
358 error);
359
360 g_free (filename);
361 g_free (data);
362 g_object_unref (source);
363 }
364
365 static void
save_source(GdictSourceDialog * dialog)366 save_source (GdictSourceDialog *dialog)
367 {
368 GdictSource *source;
369 GdictDatabaseChooser *db_chooser;
370 GdictStrategyChooser *strat_chooser;
371 gchar *name, *text;
372 GdictSourceTransport transport;
373 gchar *host, *port;
374 gchar *data;
375 gsize length;
376 GError *error;
377 gchar *filename;
378
379 source = gdict_source_loader_get_source (dialog->loader,
380 dialog->source_name);
381 if (!source)
382 {
383 g_warning ("Attempting to save source `%s', but no "
384 "source for that name was found.",
385 dialog->source_name);
386
387 return;
388 }
389
390 text = get_text_from_entry (dialog, "description_entry");
391 gdict_source_set_description (source, text);
392 g_free (text);
393
394 db_chooser = GDICT_DATABASE_CHOOSER (dialog->db_chooser);
395 text = gdict_database_chooser_get_current_database (db_chooser);
396 gdict_source_set_database (source, text);
397 g_free (text);
398
399 strat_chooser = GDICT_STRATEGY_CHOOSER (dialog->strat_chooser);
400 text = gdict_strategy_chooser_get_current_strategy (strat_chooser);
401 gdict_source_set_strategy (source, text);
402 g_free (text);
403
404
405 /* get the selected transport id */
406 transport = dialog->transport;
407 switch (transport)
408 {
409 case GDICT_SOURCE_TRANSPORT_DICTD:
410 host = get_text_from_entry (dialog, "hostname_entry");
411 port = get_text_from_entry (dialog, "port_entry");
412
413 gdict_source_set_transport (source, GDICT_SOURCE_TRANSPORT_DICTD,
414 "hostname", host,
415 "port", atoi (port),
416 NULL);
417
418 g_free (host);
419 g_free (port);
420 break;
421 case GDICT_SOURCE_TRANSPORT_INVALID:
422 default:
423 g_warning ("Invalid transport");
424 return;
425 }
426
427 error = NULL;
428 data = gdict_source_to_data (source, &length, &error);
429 if (error)
430 {
431 gdict_show_gerror_dialog (GTK_WINDOW (dialog),
432 _("Unable to create a source file"),
433 error);
434
435 g_object_unref (source);
436 return;
437 }
438
439 name = g_strdup_printf ("%s.desktop", gdict_source_get_name (source));
440 filename = g_build_filename (g_get_user_config_dir (),
441 "mate",
442 "mate-dictionary",
443 name,
444 NULL);
445 g_free (name);
446
447 g_file_set_contents (filename, data, length, &error);
448 if (error)
449 gdict_show_gerror_dialog (GTK_WINDOW (dialog),
450 _("Unable to save source file"),
451 error);
452
453 g_free (filename);
454 g_free (data);
455 g_object_unref (source);
456 }
457
458 static void
gdict_source_dialog_response_cb(GtkDialog * dialog,gint response_id,gpointer user_data)459 gdict_source_dialog_response_cb (GtkDialog *dialog,
460 gint response_id,
461 gpointer user_data)
462 {
463 GError *err = NULL;
464
465 switch (response_id)
466 {
467 case GTK_RESPONSE_ACCEPT:
468 build_new_source (GDICT_SOURCE_DIALOG (dialog));
469 break;
470 case GTK_RESPONSE_HELP:
471 gtk_show_uri_on_window (GTK_WINDOW (dialog),
472 "help:mate-dictionary/mate-dictionary-add-source",
473 gtk_get_current_event_time (), &err);
474 if (err)
475 {
476 gdict_show_gerror_dialog (GTK_WINDOW (dialog),
477 _("There was an error while displaying help"),
478 err);
479 }
480
481 /* we don't want the dialog to close itself */
482 g_signal_stop_emission_by_name (dialog, "response");
483 break;
484 case GTK_RESPONSE_CLOSE:
485 save_source (GDICT_SOURCE_DIALOG (dialog));
486 break;
487 case GTK_RESPONSE_CANCEL:
488 break;
489 default:
490 break;
491 }
492 }
493
494 static void
gdict_source_dialog_finalize(GObject * object)495 gdict_source_dialog_finalize (GObject *object)
496 {
497 GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);
498
499 if (dialog->settings)
500 g_object_unref (dialog->settings);
501
502 if (dialog->builder)
503 g_object_unref (dialog->builder);
504
505 if (dialog->source_name)
506 g_free (dialog->source_name);
507
508 if (dialog->source)
509 g_object_unref (dialog->source);
510
511 if (dialog->loader)
512 g_object_unref (dialog->loader);
513
514 G_OBJECT_CLASS (gdict_source_dialog_parent_class)->finalize (object);
515 }
516
517 static void
gdict_source_dialog_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)518 gdict_source_dialog_set_property (GObject *object,
519 guint prop_id,
520 const GValue *value,
521 GParamSpec *pspec)
522 {
523 GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);
524
525 switch (prop_id)
526 {
527 case PROP_SOURCE_LOADER:
528 set_source_loader (dialog, g_value_get_object (value));
529 break;
530 case PROP_SOURCE_NAME:
531 g_free (dialog->source_name);
532 dialog->source_name = g_strdup (g_value_get_string (value));
533 break;
534 case PROP_ACTION:
535 dialog->action = (GdictSourceDialogAction) g_value_get_int (value);
536 break;
537 default:
538 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
539 break;
540 }
541 }
542
543 static void
gdict_source_dialog_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)544 gdict_source_dialog_get_property (GObject *object,
545 guint prop_id,
546 GValue *value,
547 GParamSpec *pspec)
548 {
549 GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);
550
551 switch (prop_id)
552 {
553 case PROP_SOURCE_LOADER:
554 g_value_set_object (value, dialog->loader);
555 break;
556 case PROP_SOURCE_NAME:
557 g_value_set_string (value, dialog->source_name);
558 break;
559 case PROP_ACTION:
560 g_value_set_int (value, dialog->action);
561 break;
562 default:
563 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
564 break;
565 }
566 }
567
568 static GObject *
gdict_source_dialog_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_params)569 gdict_source_dialog_constructor (GType type,
570 guint n_construct_properties,
571 GObjectConstructParam *construct_params)
572 {
573 GObject *object;
574 GdictSourceDialog *dialog;
575 GError *error = NULL;
576
577 object = G_OBJECT_CLASS (gdict_source_dialog_parent_class)->constructor (type,
578 n_construct_properties,
579 construct_params);
580 dialog = GDICT_SOURCE_DIALOG (object);
581
582 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
583 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
584
585 /* get the UI from the GtkBuilder file */
586 dialog->builder = gtk_builder_new ();
587 gtk_builder_add_from_file (dialog->builder, GDICT_SOURCE_UI, &error);
588
589 if (error) {
590 g_critical ("Unable to load the user interface definition file: %s",
591 error->message);
592 g_error_free (error);
593 g_assert_not_reached ();
594 }
595
596 /* the main widget */
597 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
598 GET_WIDGET ("source_root"));
599
600 /* the transport combo changes the UI by changing the visible widgets
601 * bound to the transport's own options.
602 */
603 dialog->transport_combo = GET_WIDGET ("transport_combo");
604 g_signal_connect (dialog->transport_combo, "changed",
605 G_CALLBACK (transport_combo_changed_cb),
606 dialog);
607
608 /* the help button is always visible */
609 dialog->help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
610 "gtk-help",
611 GTK_RESPONSE_HELP);
612
613 dialog->db_chooser = gdict_database_chooser_new ();
614 gtk_box_pack_start (GTK_BOX (GET_WIDGET ("db-box")), dialog->db_chooser, TRUE, TRUE, 0);
615 gtk_widget_show (dialog->db_chooser);
616
617 dialog->strat_chooser = gdict_strategy_chooser_new ();
618 gtk_box_pack_start (GTK_BOX (GET_WIDGET ("strat-box")), dialog->strat_chooser, TRUE, TRUE, 0);
619 gtk_widget_show (dialog->strat_chooser);
620
621 /* the UI changes depending on the action that the source dialog
622 * should perform
623 */
624 switch (dialog->action)
625 {
626 case GDICT_SOURCE_DIALOG_VIEW:
627 /* disable every editable widget */
628 gtk_editable_set_editable (GET_EDITABLE ("name_entry"), FALSE);
629 gtk_editable_set_editable (GET_EDITABLE ("description_entry"), FALSE);
630 gtk_editable_set_editable (GET_EDITABLE ("hostname_entry"), FALSE);
631 gtk_editable_set_editable (GET_EDITABLE ("port_entry"), FALSE);
632
633 gtk_widget_set_sensitive (dialog->transport_combo, FALSE);
634
635 /* we just allow closing the dialog */
636 dialog->close_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
637 "gtk-close",
638 GTK_RESPONSE_CLOSE);
639 break;
640 case GDICT_SOURCE_DIALOG_CREATE:
641 dialog->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
642 "gtk-cancel",
643 GTK_RESPONSE_CANCEL);
644 dialog->add_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
645 "gtk-add",
646 GTK_RESPONSE_ACCEPT);
647 /* the "add" button sensitivity is controlled by the transport_combo
648 * since it's the only setting that makes a source usable.
649 */
650 gtk_widget_set_sensitive (dialog->add_button, FALSE);
651 break;
652 case GDICT_SOURCE_DIALOG_EDIT:
653 dialog->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
654 "gtk-cancel",
655 GTK_RESPONSE_CANCEL);
656 dialog->close_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
657 "gtk-close",
658 GTK_RESPONSE_CLOSE);
659 break;
660 default:
661 g_assert_not_reached ();
662 break;
663 }
664
665 /* this will take care of updating the contents of the dialog
666 * based on the action
667 */
668 update_dialog_ui (dialog);
669
670 return object;
671 }
672
673 static void
gdict_source_dialog_class_init(GdictSourceDialogClass * klass)674 gdict_source_dialog_class_init (GdictSourceDialogClass *klass)
675 {
676 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
677
678 gobject_class->constructor = gdict_source_dialog_constructor;
679 gobject_class->set_property = gdict_source_dialog_set_property;
680 gobject_class->get_property = gdict_source_dialog_get_property;
681 gobject_class->finalize = gdict_source_dialog_finalize;
682
683 g_object_class_install_property (gobject_class,
684 PROP_SOURCE_LOADER,
685 g_param_spec_object ("source-loader",
686 "Source Loader",
687 "The GdictSourceLoader used by the application",
688 GDICT_TYPE_SOURCE_LOADER,
689 (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
690 g_object_class_install_property (gobject_class,
691 PROP_SOURCE_NAME,
692 g_param_spec_string ("source-name",
693 "Source Name",
694 "The source name",
695 NULL,
696 (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
697 g_object_class_install_property (gobject_class,
698 PROP_ACTION,
699 g_param_spec_int ("action",
700 "Action",
701 "The action the source dialog should perform",
702 -1,
703 GDICT_SOURCE_DIALOG_EDIT,
704 GDICT_SOURCE_DIALOG_VIEW,
705 (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
706 }
707
708 static void
gdict_source_dialog_init(GdictSourceDialog * dialog)709 gdict_source_dialog_init (GdictSourceDialog *dialog)
710 {
711 gtk_widget_set_size_request (GTK_WIDGET (dialog), 400, 300);
712 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
713
714 dialog->transport = GDICT_SOURCE_TRANSPORT_INVALID;
715
716 g_signal_connect (dialog, "response",
717 G_CALLBACK (gdict_source_dialog_response_cb),
718 NULL);
719 }
720
721 GtkWidget *
gdict_source_dialog_new(GtkWindow * parent,const gchar * title,GdictSourceDialogAction action,GdictSourceLoader * loader,const gchar * source_name)722 gdict_source_dialog_new (GtkWindow *parent,
723 const gchar *title,
724 GdictSourceDialogAction action,
725 GdictSourceLoader *loader,
726 const gchar *source_name)
727 {
728 GtkWidget *retval;
729
730 g_return_val_if_fail ((parent == NULL || GTK_IS_WINDOW (parent)), NULL);
731 g_return_val_if_fail (GDICT_IS_SOURCE_LOADER (loader), NULL);
732
733 retval = g_object_new (GDICT_TYPE_SOURCE_DIALOG,
734 "source-loader", loader,
735 "source-name", source_name,
736 "action", action,
737 "title", title,
738 NULL);
739
740 if (parent)
741 {
742 gtk_window_set_transient_for (GTK_WINDOW (retval), parent);
743 gtk_window_set_destroy_with_parent (GTK_WINDOW (retval), TRUE);
744 gtk_window_set_screen (GTK_WINDOW (retval),
745 gtk_widget_get_screen (GTK_WIDGET (parent)));
746 }
747
748 return retval;
749 }
750