1 /*
2 * pluma-close-confirmation-dialog.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2004-2005 GNOME Foundation
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 /*
25 * Modified by the pluma Team, 2004-2005. See the AUTHORS file for a
26 * list of people on the pluma Team.
27 * See the ChangeLog files for a list of changes.
28 *
29 * $Id$
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <glib/gi18n.h>
37
38 #include "pluma-close-confirmation-dialog.h"
39 #include <pluma/pluma-app.h>
40 #include <pluma/pluma-utils.h>
41 #include <pluma/pluma-window.h>
42
43
44 /* Properties */
45 enum
46 {
47 PROP_0,
48 PROP_UNSAVED_DOCUMENTS,
49 PROP_LOGOUT_MODE
50 };
51
52 /* Mode */
53 enum
54 {
55 SINGLE_DOC_MODE,
56 MULTIPLE_DOCS_MODE
57 };
58
59 /* Columns */
60 enum
61 {
62 SAVE_COLUMN,
63 NAME_COLUMN,
64 DOC_COLUMN, /* a handy pointer to the document */
65 N_COLUMNS
66 };
67
68 struct _PlumaCloseConfirmationDialogPrivate
69 {
70 gboolean logout_mode;
71
72 GList *unsaved_documents;
73
74 GList *selected_documents;
75
76 GtkTreeModel *list_store;
77
78 gboolean disable_save_to_disk;
79 };
80
81 #define GET_MODE(priv) (((priv->unsaved_documents != NULL) && \
82 (priv->unsaved_documents->next == NULL)) ? \
83 SINGLE_DOC_MODE : MULTIPLE_DOCS_MODE)
84
85 G_DEFINE_TYPE_WITH_PRIVATE (PlumaCloseConfirmationDialog, pluma_close_confirmation_dialog, GTK_TYPE_DIALOG)
86
87 static void set_unsaved_document (PlumaCloseConfirmationDialog *dlg,
88 const GList *list);
89
90 static GList *get_selected_docs (GtkTreeModel *store);
91
92 /* Since we connect in the costructor we are sure this handler will be called
93 * before the user ones
94 */
95 static void
response_cb(PlumaCloseConfirmationDialog * dlg,gint response_id,gpointer data)96 response_cb (PlumaCloseConfirmationDialog *dlg,
97 gint response_id,
98 gpointer data)
99 {
100 PlumaCloseConfirmationDialogPrivate *priv;
101
102 g_return_if_fail (PLUMA_IS_CLOSE_CONFIRMATION_DIALOG (dlg));
103
104 priv = dlg->priv;
105
106 if (priv->selected_documents != NULL)
107 g_list_free (priv->selected_documents);
108
109 if (response_id == GTK_RESPONSE_YES)
110 {
111 if (GET_MODE (priv) == SINGLE_DOC_MODE)
112 {
113 priv->selected_documents =
114 g_list_copy (priv->unsaved_documents);
115 }
116 else
117 {
118 g_return_if_fail (priv->list_store);
119
120 priv->selected_documents =
121 get_selected_docs (priv->list_store);
122 }
123 }
124 else
125 priv->selected_documents = NULL;
126 }
127
128 static void
set_logout_mode(PlumaCloseConfirmationDialog * dlg,gboolean logout_mode)129 set_logout_mode (PlumaCloseConfirmationDialog *dlg,
130 gboolean logout_mode)
131 {
132 dlg->priv->logout_mode = logout_mode;
133
134 if (logout_mode)
135 {
136 gtk_dialog_add_button (GTK_DIALOG (dlg),
137 _("Log Out _without Saving"),
138 GTK_RESPONSE_NO);
139
140 pluma_dialog_add_button (GTK_DIALOG (dlg),
141 _("_Cancel Logout"),
142 "process-stop",
143 GTK_RESPONSE_CANCEL);
144 }
145 else
146 {
147 gtk_dialog_add_button (GTK_DIALOG (dlg),
148 _("Close _without Saving"),
149 GTK_RESPONSE_NO);
150
151 pluma_dialog_add_button (GTK_DIALOG (dlg),
152 _("_Cancel"),
153 "process-stop",
154 GTK_RESPONSE_CANCEL);
155 }
156
157 if (dlg->priv->disable_save_to_disk)
158 {
159 gtk_dialog_set_default_response (GTK_DIALOG (dlg),
160 GTK_RESPONSE_NO);
161 }
162 else
163 {
164 const gchar *icon_id = "document-save";
165
166 if (GET_MODE (dlg->priv) == SINGLE_DOC_MODE)
167 {
168 PlumaDocument *doc;
169
170 doc = PLUMA_DOCUMENT (dlg->priv->unsaved_documents->data);
171
172 if (pluma_document_get_readonly (doc) ||
173 pluma_document_is_untitled (doc))
174 icon_id = "document-save-as";
175 }
176
177 if (g_strcmp0 (icon_id, "document-save") == 0)
178 pluma_dialog_add_button (GTK_DIALOG (dlg),
179 _("_Save"),
180 icon_id,
181 GTK_RESPONSE_YES);
182 else
183 pluma_dialog_add_button (GTK_DIALOG (dlg),
184 _("Save _As"),
185 icon_id,
186 GTK_RESPONSE_YES);
187
188 gtk_dialog_set_default_response (GTK_DIALOG (dlg),
189 GTK_RESPONSE_YES);
190 }
191 }
192
193 static void
pluma_close_confirmation_dialog_init(PlumaCloseConfirmationDialog * dlg)194 pluma_close_confirmation_dialog_init (PlumaCloseConfirmationDialog *dlg)
195 {
196 AtkObject *atk_obj;
197
198 dlg->priv = pluma_close_confirmation_dialog_get_instance_private (dlg);
199
200 dlg->priv->disable_save_to_disk =
201 pluma_app_get_lockdown (pluma_app_get_default ())
202 & PLUMA_LOCKDOWN_SAVE_TO_DISK;
203
204 gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
205 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
206 14);
207 gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
208 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dlg), TRUE);
209
210 gtk_window_set_title (GTK_WINDOW (dlg), "");
211
212 gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
213 gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
214
215 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dlg));
216 atk_object_set_role (atk_obj, ATK_ROLE_ALERT);
217 atk_object_set_name (atk_obj, _("Question"));
218
219 g_signal_connect (dlg,
220 "response",
221 G_CALLBACK (response_cb),
222 NULL);
223 }
224
225 static void
pluma_close_confirmation_dialog_finalize(GObject * object)226 pluma_close_confirmation_dialog_finalize (GObject *object)
227 {
228 PlumaCloseConfirmationDialogPrivate *priv;
229
230 priv = PLUMA_CLOSE_CONFIRMATION_DIALOG (object)->priv;
231
232 if (priv->unsaved_documents != NULL)
233 g_list_free (priv->unsaved_documents);
234
235 if (priv->selected_documents != NULL)
236 g_list_free (priv->selected_documents);
237
238 /* Call the parent's destructor */
239 G_OBJECT_CLASS (pluma_close_confirmation_dialog_parent_class)->finalize (object);
240 }
241
242 static void
pluma_close_confirmation_dialog_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)243 pluma_close_confirmation_dialog_set_property (GObject *object,
244 guint prop_id,
245 const GValue *value,
246 GParamSpec *pspec)
247 {
248 PlumaCloseConfirmationDialog *dlg;
249
250 dlg = PLUMA_CLOSE_CONFIRMATION_DIALOG (object);
251
252 switch (prop_id)
253 {
254 case PROP_UNSAVED_DOCUMENTS:
255 set_unsaved_document (dlg, g_value_get_pointer (value));
256 break;
257
258 case PROP_LOGOUT_MODE:
259 set_logout_mode (dlg, g_value_get_boolean (value));
260 break;
261
262 default:
263 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
264 break;
265 }
266 }
267
268 static void
pluma_close_confirmation_dialog_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)269 pluma_close_confirmation_dialog_get_property (GObject *object,
270 guint prop_id,
271 GValue *value,
272 GParamSpec *pspec)
273 {
274 PlumaCloseConfirmationDialogPrivate *priv;
275
276 priv = PLUMA_CLOSE_CONFIRMATION_DIALOG (object)->priv;
277
278 switch( prop_id )
279 {
280 case PROP_UNSAVED_DOCUMENTS:
281 g_value_set_pointer (value, priv->unsaved_documents);
282 break;
283
284 case PROP_LOGOUT_MODE:
285 g_value_set_boolean (value, priv->logout_mode);
286 break;
287
288 default:
289 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
290 break;
291 }
292 }
293
294 static void
pluma_close_confirmation_dialog_class_init(PlumaCloseConfirmationDialogClass * klass)295 pluma_close_confirmation_dialog_class_init (PlumaCloseConfirmationDialogClass *klass)
296 {
297 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
298
299 gobject_class->set_property = pluma_close_confirmation_dialog_set_property;
300 gobject_class->get_property = pluma_close_confirmation_dialog_get_property;
301 gobject_class->finalize = pluma_close_confirmation_dialog_finalize;
302
303 g_object_class_install_property (gobject_class,
304 PROP_UNSAVED_DOCUMENTS,
305 g_param_spec_pointer ("unsaved_documents",
306 "Unsaved Documents",
307 "List of Unsaved Documents",
308 (G_PARAM_READWRITE |
309 G_PARAM_CONSTRUCT_ONLY)));
310
311 g_object_class_install_property (gobject_class,
312 PROP_LOGOUT_MODE,
313 g_param_spec_boolean ("logout_mode",
314 "Logout Mode",
315 "Whether the dialog is in logout mode",
316 FALSE,
317 (G_PARAM_READWRITE |
318 G_PARAM_CONSTRUCT_ONLY)));
319 }
320
321 static GList *
get_selected_docs(GtkTreeModel * store)322 get_selected_docs (GtkTreeModel *store)
323 {
324 GList *list;
325 gboolean valid;
326 GtkTreeIter iter;
327
328 list = NULL;
329 valid = gtk_tree_model_get_iter_first (store, &iter);
330
331 while (valid)
332 {
333 gboolean to_save;
334 PlumaDocument *doc;
335
336 gtk_tree_model_get (store, &iter,
337 SAVE_COLUMN, &to_save,
338 DOC_COLUMN, &doc,
339 -1);
340 if (to_save)
341 list = g_list_prepend (list, doc);
342
343 valid = gtk_tree_model_iter_next (store, &iter);
344 }
345
346 list = g_list_reverse (list);
347
348 return list;
349 }
350
351 GList *
pluma_close_confirmation_dialog_get_selected_documents(PlumaCloseConfirmationDialog * dlg)352 pluma_close_confirmation_dialog_get_selected_documents (PlumaCloseConfirmationDialog *dlg)
353 {
354 g_return_val_if_fail (PLUMA_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
355
356 return g_list_copy (dlg->priv->selected_documents);
357 }
358
359 GtkWidget *
pluma_close_confirmation_dialog_new(GtkWindow * parent,GList * unsaved_documents,gboolean logout_mode)360 pluma_close_confirmation_dialog_new (GtkWindow *parent,
361 GList *unsaved_documents,
362 gboolean logout_mode)
363 {
364 GtkWidget *dlg;
365 g_return_val_if_fail (unsaved_documents != NULL, NULL);
366
367 dlg = GTK_WIDGET (g_object_new (PLUMA_TYPE_CLOSE_CONFIRMATION_DIALOG,
368 "unsaved_documents", unsaved_documents,
369 "logout_mode", logout_mode,
370 NULL));
371 g_return_val_if_fail (dlg != NULL, NULL);
372
373 if (parent != NULL)
374 {
375 gtk_window_group_add_window (pluma_window_get_group (PLUMA_WINDOW (parent)),
376 GTK_WINDOW (dlg));
377
378 gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
379 }
380
381 return dlg;
382 }
383
384 GtkWidget *
pluma_close_confirmation_dialog_new_single(GtkWindow * parent,PlumaDocument * doc,gboolean logout_mode)385 pluma_close_confirmation_dialog_new_single (GtkWindow *parent,
386 PlumaDocument *doc,
387 gboolean logout_mode)
388 {
389 GtkWidget *dlg;
390 GList *unsaved_documents;
391 g_return_val_if_fail (doc != NULL, NULL);
392
393 unsaved_documents = g_list_prepend (NULL, doc);
394
395 dlg = pluma_close_confirmation_dialog_new (parent,
396 unsaved_documents,
397 logout_mode);
398
399 g_list_free (unsaved_documents);
400
401 return dlg;
402 }
403
404 static gchar *
get_text_secondary_label(PlumaDocument * doc)405 get_text_secondary_label (PlumaDocument *doc)
406 {
407 glong seconds;
408 gchar *secondary_msg;
409
410 seconds = MAX (1, _pluma_document_get_seconds_since_last_save_or_load (doc));
411
412 if (seconds < 55)
413 {
414 secondary_msg = g_strdup_printf (
415 ngettext ("If you don't save, changes from the last %ld second "
416 "will be permanently lost.",
417 "If you don't save, changes from the last %ld seconds "
418 "will be permanently lost.",
419 seconds),
420 seconds);
421 }
422 else if (seconds < 75) /* 55 <= seconds < 75 */
423 {
424 secondary_msg = g_strdup (_("If you don't save, changes from the last minute "
425 "will be permanently lost."));
426 }
427 else if (seconds < 110) /* 75 <= seconds < 110 */
428 {
429 secondary_msg = g_strdup_printf (
430 ngettext ("If you don't save, changes from the last minute and %ld "
431 "second will be permanently lost.",
432 "If you don't save, changes from the last minute and %ld "
433 "seconds will be permanently lost.",
434 seconds - 60 ),
435 seconds - 60);
436 }
437 else if (seconds < 3600)
438 {
439 secondary_msg = g_strdup_printf (
440 ngettext ("If you don't save, changes from the last %ld minute "
441 "will be permanently lost.",
442 "If you don't save, changes from the last %ld minutes "
443 "will be permanently lost.",
444 seconds / 60),
445 seconds / 60);
446 }
447 else if (seconds < 7200)
448 {
449 gint minutes;
450 seconds -= 3600;
451
452 minutes = seconds / 60;
453 if (minutes < 5)
454 {
455 secondary_msg = g_strdup (_("If you don't save, changes from the last hour "
456 "will be permanently lost."));
457 }
458 else
459 {
460 secondary_msg = g_strdup_printf (
461 ngettext ("If you don't save, changes from the last hour and %d "
462 "minute will be permanently lost.",
463 "If you don't save, changes from the last hour and %d "
464 "minutes will be permanently lost.",
465 minutes),
466 minutes);
467 }
468 }
469 else
470 {
471 gint hours;
472
473 hours = seconds / 3600;
474
475 secondary_msg = g_strdup_printf (
476 ngettext ("If you don't save, changes from the last %d hour "
477 "will be permanently lost.",
478 "If you don't save, changes from the last %d hours "
479 "will be permanently lost.",
480 hours),
481 hours);
482 }
483
484 return secondary_msg;
485 }
486
487 static void
build_single_doc_dialog(PlumaCloseConfirmationDialog * dlg)488 build_single_doc_dialog (PlumaCloseConfirmationDialog *dlg)
489 {
490 GtkWidget *hbox;
491 GtkWidget *vbox;
492 GtkWidget *primary_label;
493 GtkWidget *secondary_label;
494 GtkWidget *image;
495 PlumaDocument *doc;
496 gchar *doc_name;
497 gchar *str;
498 gchar *markup_str;
499
500 g_return_if_fail (dlg->priv->unsaved_documents->data != NULL);
501 doc = PLUMA_DOCUMENT (dlg->priv->unsaved_documents->data);
502
503 /* Image */
504 image = gtk_image_new_from_icon_name ("dialog-warning",
505 GTK_ICON_SIZE_DIALOG);
506 gtk_widget_set_halign (image, GTK_ALIGN_START);
507 gtk_widget_set_valign (image, GTK_ALIGN_END);
508
509 /* Primary label */
510 primary_label = gtk_label_new (NULL);
511 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
512 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
513 gtk_label_set_xalign (GTK_LABEL (primary_label), 0.0);
514 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
515 gtk_widget_set_can_focus (GTK_WIDGET (primary_label), FALSE);
516 gtk_label_set_max_width_chars (GTK_LABEL (primary_label), 72);
517
518 doc_name = pluma_document_get_short_name_for_display (doc);
519
520 if (dlg->priv->disable_save_to_disk)
521 {
522 str = g_markup_printf_escaped (_("Changes to document \"%s\" will be permanently lost."),
523 doc_name);
524 }
525 else
526 {
527 str = g_markup_printf_escaped (_("Save changes to document \"%s\" before closing?"),
528 doc_name);
529 }
530
531 g_free (doc_name);
532
533 markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
534 g_free (str);
535
536 gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
537 g_free (markup_str);
538
539 /* Secondary label */
540 if (dlg->priv->disable_save_to_disk)
541 str = g_strdup (_("Saving has been disabled by the system administrator."));
542 else
543 str = get_text_secondary_label (doc);
544 secondary_label = gtk_label_new (str);
545 g_free (str);
546 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
547 gtk_label_set_xalign (GTK_LABEL (secondary_label), 0.0);
548 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
549 gtk_widget_set_can_focus (GTK_WIDGET (secondary_label), FALSE);
550 gtk_label_set_max_width_chars (GTK_LABEL (secondary_label), 72);
551
552 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
553 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
554
555 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
556
557 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
558
559 gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
560
561 gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
562
563 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, FALSE, FALSE, 0);
564
565 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
566 hbox,
567 FALSE,
568 FALSE,
569 0);
570
571 gtk_widget_show_all (hbox);
572 }
573
574 static void
populate_model(GtkTreeModel * store,GList * docs)575 populate_model (GtkTreeModel *store, GList *docs)
576 {
577 GtkTreeIter iter;
578
579 while (docs != NULL)
580 {
581 PlumaDocument *doc;
582 gchar *name;
583
584 doc = PLUMA_DOCUMENT (docs->data);
585
586 name = pluma_document_get_short_name_for_display (doc);
587
588 gtk_list_store_append (GTK_LIST_STORE (store), &iter);
589 gtk_list_store_set (GTK_LIST_STORE (store), &iter,
590 SAVE_COLUMN, TRUE,
591 NAME_COLUMN, name,
592 DOC_COLUMN, doc,
593 -1);
594
595 g_free (name);
596
597 docs = g_list_next (docs);
598 }
599 }
600
601 static void
save_toggled(GtkCellRendererToggle * renderer,gchar * path_str,GtkTreeModel * store)602 save_toggled (GtkCellRendererToggle *renderer, gchar *path_str, GtkTreeModel *store)
603 {
604 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
605 GtkTreeIter iter;
606 gboolean active;
607
608 gtk_tree_model_get_iter (store, &iter, path);
609 gtk_tree_model_get (store, &iter, SAVE_COLUMN, &active, -1);
610
611 active ^= 1;
612
613 gtk_list_store_set (GTK_LIST_STORE (store), &iter,
614 SAVE_COLUMN, active, -1);
615
616 gtk_tree_path_free (path);
617 }
618
619 static GtkWidget *
create_treeview(PlumaCloseConfirmationDialogPrivate * priv)620 create_treeview (PlumaCloseConfirmationDialogPrivate *priv)
621 {
622 GtkListStore *store;
623 GtkWidget *treeview;
624 GtkCellRenderer *renderer;
625 GtkTreeViewColumn *column;
626
627 treeview = gtk_tree_view_new ();
628 gtk_widget_set_size_request (treeview, 260, 120);
629 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
630 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
631
632 /* Create and populate the model */
633 store = gtk_list_store_new (N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
634 populate_model (GTK_TREE_MODEL (store), priv->unsaved_documents);
635
636 /* Set model to the treeview */
637 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
638 g_object_unref (store);
639
640 priv->list_store = GTK_TREE_MODEL (store);
641
642 /* Add columns */
643 if (!priv->disable_save_to_disk)
644 {
645 renderer = gtk_cell_renderer_toggle_new ();
646 g_signal_connect (renderer, "toggled",
647 G_CALLBACK (save_toggled), store);
648
649 column = gtk_tree_view_column_new_with_attributes ("Save?",
650 renderer,
651 "active",
652 SAVE_COLUMN,
653 NULL);
654 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
655 }
656
657 renderer = gtk_cell_renderer_text_new ();
658 column = gtk_tree_view_column_new_with_attributes ("Name",
659 renderer,
660 "text",
661 NAME_COLUMN,
662 NULL);
663 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
664
665 return treeview;
666 }
667
668 static void
build_multiple_docs_dialog(PlumaCloseConfirmationDialog * dlg)669 build_multiple_docs_dialog (PlumaCloseConfirmationDialog *dlg)
670 {
671 PlumaCloseConfirmationDialogPrivate *priv;
672 GtkWidget *hbox;
673 GtkWidget *image;
674 GtkWidget *vbox;
675 GtkWidget *primary_label;
676 GtkWidget *vbox2;
677 GtkWidget *select_label;
678 GtkWidget *scrolledwindow;
679 GtkWidget *treeview;
680 GtkWidget *secondary_label;
681 GdkDisplay *display;
682 GdkRectangle mon_geo;
683 gchar *str;
684 gchar *markup_str;
685 gint new_width;
686 gint new_height;
687 gint max_height;
688
689 priv = dlg->priv;
690
691 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
692 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
693 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
694 hbox, TRUE, TRUE, 0);
695
696 /* Image */
697 image = gtk_image_new_from_icon_name ("dialog-warning",
698 GTK_ICON_SIZE_DIALOG);
699 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
700 gtk_widget_set_valign (image, GTK_ALIGN_START);
701 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
702
703 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
704 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
705
706 /* Primary label */
707 primary_label = gtk_label_new (NULL);
708 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
709 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
710 gtk_label_set_xalign (GTK_LABEL (primary_label), 0.0);
711 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
712 gtk_widget_set_can_focus (GTK_WIDGET (primary_label), FALSE);
713 gtk_label_set_max_width_chars (GTK_LABEL (primary_label), 72);
714
715 if (priv->disable_save_to_disk)
716 str = g_strdup_printf (
717 ngettext ("Changes to %d document will be permanently lost.",
718 "Changes to %d documents will be permanently lost.",
719 g_list_length (priv->unsaved_documents)),
720 g_list_length (priv->unsaved_documents));
721 else
722 str = g_strdup_printf (
723 ngettext ("There is %d document with unsaved changes. "
724 "Save changes before closing?",
725 "There are %d documents with unsaved changes. "
726 "Save changes before closing?",
727 g_list_length (priv->unsaved_documents)),
728 g_list_length (priv->unsaved_documents));
729
730 markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
731 g_free (str);
732
733 gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
734 g_free (markup_str);
735 gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
736
737 vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
738 gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
739
740 if (priv->disable_save_to_disk)
741 select_label = gtk_label_new_with_mnemonic (_("Docum_ents with unsaved changes:"));
742 else
743 select_label = gtk_label_new_with_mnemonic (_("S_elect the documents you want to save:"));
744
745 gtk_box_pack_start (GTK_BOX (vbox2), select_label, FALSE, FALSE, 0);
746 gtk_label_set_line_wrap (GTK_LABEL (select_label), TRUE);
747 gtk_label_set_max_width_chars (GTK_LABEL (select_label), 72);
748 gtk_label_set_xalign (GTK_LABEL (select_label), 0.0);
749 gtk_label_set_selectable (GTK_LABEL (select_label), TRUE);
750 gtk_widget_set_can_focus (GTK_WIDGET (select_label), FALSE);
751
752 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
753 gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (scrolledwindow), TRUE);
754 gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow, TRUE, TRUE, 0);
755 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
756 GTK_POLICY_AUTOMATIC,
757 GTK_POLICY_AUTOMATIC);
758 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
759 GTK_SHADOW_IN);
760
761 treeview = create_treeview (priv);
762 gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview);
763
764 /* Secondary label */
765 if (priv->disable_save_to_disk)
766 secondary_label = gtk_label_new (_("Saving has been disabled by the system administrator."));
767 else
768 secondary_label = gtk_label_new (_("If you don't save, "
769 "all your changes will be permanently lost."));
770
771 gtk_box_pack_start (GTK_BOX (vbox2), secondary_label, FALSE, FALSE, 0);
772 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
773 gtk_label_set_xalign (GTK_LABEL (secondary_label), 0.0);
774 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
775 gtk_widget_set_can_focus (GTK_WIDGET (secondary_label), FALSE);
776 gtk_label_set_max_width_chars (GTK_LABEL (secondary_label), 72);
777
778 gtk_label_set_mnemonic_widget (GTK_LABEL (select_label), treeview);
779
780 gtk_widget_show_all (hbox);
781
782 gtk_window_get_size (GTK_WINDOW (GTK_DIALOG (dlg)), &new_width, &new_height);
783
784 display = gtk_widget_get_display (scrolledwindow);
785
786 gdk_monitor_get_geometry (gdk_display_get_primary_monitor (display), &mon_geo);
787
788 max_height = mon_geo.height * 40 / 100;
789
790 if (new_height > max_height)
791 {
792 gtk_window_set_resizable (GTK_WINDOW (GTK_DIALOG (dlg)), TRUE);
793 gtk_window_resize (GTK_WINDOW (GTK_DIALOG (dlg)), new_width, max_height);
794 }
795 else
796 gtk_window_set_default_size (GTK_WINDOW (GTK_DIALOG (dlg)), new_width, new_height);
797 }
798
799 static void
set_unsaved_document(PlumaCloseConfirmationDialog * dlg,const GList * list)800 set_unsaved_document (PlumaCloseConfirmationDialog *dlg,
801 const GList *list)
802 {
803 PlumaCloseConfirmationDialogPrivate *priv;
804
805 g_return_if_fail (list != NULL);
806
807 priv = dlg->priv;
808 g_return_if_fail (priv->unsaved_documents == NULL);
809
810 priv->unsaved_documents = g_list_copy ((GList *)list);
811
812 if (GET_MODE (priv) == SINGLE_DOC_MODE)
813 {
814 build_single_doc_dialog (dlg);
815 }
816 else
817 {
818 build_multiple_docs_dialog (dlg);
819 }
820 }
821
822 const GList *
pluma_close_confirmation_dialog_get_unsaved_documents(PlumaCloseConfirmationDialog * dlg)823 pluma_close_confirmation_dialog_get_unsaved_documents (PlumaCloseConfirmationDialog *dlg)
824 {
825 g_return_val_if_fail (PLUMA_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
826
827 return dlg->priv->unsaved_documents;
828 }
829