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