~teejee2008/timeshift/trunk

« back to all changes in this revision

Viewing changes to src/RestoreWindow.vala

  • Committer: Tony George
  • Date: 2013-10-05 05:34:20 UTC
  • Revision ID: teejee2008@gmail.com-20131005053420-7hbek2g1gf9hhafz
Initial release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MainWindow.vala
 
3
 * 
 
4
 * Copyright 2013 Tony George <teejee2008@gmail.com>
 
5
 * 
 
6
 * This program 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
 * This program 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 this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
19
 * MA 02110-1301, USA.
 
20
 * 
 
21
 * 
 
22
 */
 
23
 
 
24
using Gtk;
 
25
using Gee;
 
26
using Utility;
 
27
 
 
28
public class RestoreWindow : Gtk.Dialog{
 
29
        private Box vbox_main;
 
30
        private Box hbox_action;
 
31
        private Notebook notebook;
 
32
 
 
33
    //target device
 
34
    private Label lbl_header_partitions;
 
35
    private TreeView tv_partitions;
 
36
        private ScrolledWindow sw_partitions;
 
37
        private TreeViewColumn col_device_target;
 
38
        private TreeViewColumn col_fs;
 
39
        private TreeViewColumn col_size;
 
40
        private TreeViewColumn col_used;
 
41
        private TreeViewColumn col_label;
 
42
        private TreeViewColumn col_dist;
 
43
        
 
44
        //bootloader
 
45
        private Label lbl_header_bootloader;
 
46
        private CheckButton chk_restore_grub2;
 
47
        private ComboBox cmb_boot_device;
 
48
        
 
49
        //exclude
 
50
        private Label lbl_exclude;
 
51
        private Box vbox_exclude;
 
52
        private LinkButton lnk_default_list;
 
53
        private TreeView tv_exclude;
 
54
        private ScrolledWindow sw_exclude;
 
55
        private TreeViewColumn col_exclude;
 
56
        private Toolbar toolbar_exclude;
 
57
        private ToolButton btn_remove;
 
58
        private ToolButton btn_warning;
 
59
        private ToolButton btn_reset_exclude_list;
 
60
        
 
61
        private MenuToolButton btn_exclude;
 
62
        private Gtk.Menu menu_exclude;
 
63
        private ImageMenuItem menu_exclude_add_file;
 
64
        private ImageMenuItem menu_exclude_add_folder;
 
65
        private ImageMenuItem menu_exclude_add_folder_contents;
 
66
        
 
67
        private MenuToolButton btn_include;
 
68
        private Gtk.Menu menu_include;
 
69
        private ImageMenuItem menu_include_add_file;
 
70
        private ImageMenuItem menu_include_add_folder;
 
71
        
 
72
        private Gee.ArrayList<string> temp_exclude_list;
 
73
        
 
74
        //actions
 
75
        private Button btn_cancel;
 
76
        private Button btn_restore;
 
77
 
 
78
        public RestoreWindow () {
 
79
                this.title = _("Restore");
 
80
        this.window_position = WindowPosition.CENTER_ON_PARENT;
 
81
        this.set_destroy_with_parent (true);
 
82
                this.set_modal (true);
 
83
        this.set_default_size (500, 400);
 
84
 
 
85
        //set app icon
 
86
                try{
 
87
                        this.icon = new Gdk.Pixbuf.from_file (App.share_folder + """/pixmaps/timeshift.png""");
 
88
                }
 
89
        catch(Error e){
 
90
                log_error (e.message);
 
91
            }
 
92
            
 
93
            //vbox_main
 
94
        vbox_main = get_content_area ();
 
95
 
 
96
                //notebook
 
97
                notebook = new Notebook ();
 
98
                notebook.margin = 6;
 
99
                vbox_main.pack_start (notebook, true, true, 0);
 
100
 
 
101
                //target device tab -------------------------------------------------
 
102
                
 
103
                //lbl_exclude
 
104
                lbl_exclude = new Label (_("Target"));
 
105
 
 
106
        //vbox_target
 
107
        Box vbox_target = new Box (Orientation.VERTICAL, 6);
 
108
        vbox_target.margin = 6;
 
109
        notebook.append_page (vbox_target, lbl_exclude);
 
110
        
 
111
                //lbl_header_partitions
 
112
                lbl_header_partitions = new Gtk.Label("<b>" + _("Target Device") + ":</b>");
 
113
                lbl_header_partitions.xalign = (float) 0.0;
 
114
                lbl_header_partitions.set_use_markup(true);
 
115
                vbox_target.add(lbl_header_partitions);
 
116
                
 
117
                //tv_partitions
 
118
                tv_partitions = new TreeView();
 
119
                tv_partitions.get_selection().mode = SelectionMode.SINGLE;
 
120
                tv_partitions.set_rules_hint (true);
 
121
                tv_partitions.button_release_event.connect(tv_partitions_button_press_event);
 
122
                
 
123
                //sw_partitions
 
124
                sw_partitions = new ScrolledWindow(null, null);
 
125
                sw_partitions.set_shadow_type (ShadowType.ETCHED_IN);
 
126
                sw_partitions.add (tv_partitions);
 
127
                sw_partitions.expand = true;
 
128
                vbox_target.add(sw_partitions);
 
129
                
 
130
                //col_device
 
131
                col_device_target = new TreeViewColumn();
 
132
                col_device_target.title = _("Device");
 
133
                col_device_target.spacing = 1;
 
134
 
 
135
                CellRendererPixbuf cell_device_icon = new CellRendererPixbuf ();
 
136
                cell_device_icon.stock_id = Stock.HARDDISK;
 
137
                cell_device_icon.xpad = 1;
 
138
                col_device_target.pack_start (cell_device_icon, false);
 
139
 
 
140
                CellRendererText cell_device_target = new CellRendererText ();
 
141
                col_device_target.pack_start (cell_device_target, false);
 
142
                col_device_target.set_cell_data_func (cell_device_target, cell_device_target_render);
 
143
                
 
144
                tv_partitions.append_column(col_device_target);
 
145
                
 
146
                //col_fs
 
147
                col_fs = new TreeViewColumn();
 
148
                col_fs.title = _("Type");
 
149
                CellRendererText cell_fs = new CellRendererText ();
 
150
                cell_fs.xalign = (float) 0.5;
 
151
                col_fs.pack_start (cell_fs, false);
 
152
                col_fs.set_cell_data_func (cell_fs, cell_fs_render);
 
153
                tv_partitions.append_column(col_fs);
 
154
 
 
155
                //col_size
 
156
                col_size = new TreeViewColumn();
 
157
                col_size.title = _("Size");
 
158
                CellRendererText cell_size = new CellRendererText ();
 
159
                cell_size.xalign = (float) 1.0;
 
160
                col_size.pack_start (cell_size, false);
 
161
                col_size.set_cell_data_func (cell_size, cell_size_render);
 
162
                tv_partitions.append_column(col_size);
 
163
                
 
164
                //col_used
 
165
                col_used = new TreeViewColumn();
 
166
                col_used.title = _("Used");
 
167
                CellRendererText cell_used = new CellRendererText ();
 
168
                cell_used.xalign = (float) 1.0;
 
169
                col_used.pack_start (cell_used, false);
 
170
                col_used.set_cell_data_func (cell_used, cell_used_render);
 
171
                tv_partitions.append_column(col_used);
 
172
                
 
173
                //col_label
 
174
                col_label = new TreeViewColumn();
 
175
                col_label.title = _("Label");
 
176
                CellRendererText cell_label = new CellRendererText ();
 
177
                col_label.pack_start (cell_label, false);
 
178
                col_label.set_cell_data_func (cell_label, cell_label_render);
 
179
                tv_partitions.append_column(col_label);
 
180
                
 
181
                //col_dist
 
182
                col_dist = new TreeViewColumn();
 
183
                col_dist.title = _("System");
 
184
                CellRendererText cell_dist = new CellRendererText ();
 
185
                col_dist.pack_start (cell_dist, false);
 
186
                col_dist.set_cell_data_func (cell_dist, cell_dist_render);
 
187
                tv_partitions.append_column(col_dist);
 
188
                
 
189
                //bootloader options -------------------------------------------
 
190
                
 
191
                //lbl_header_bootloader
 
192
                lbl_header_bootloader = new Gtk.Label("<b>" +_("Bootloader") + ":</b>");
 
193
                lbl_header_bootloader.set_use_markup(true);
 
194
                lbl_header_bootloader.xalign = (float) 0.0;
 
195
                vbox_target.add(lbl_header_bootloader);
 
196
                
 
197
                //hbox_grub
 
198
                Box hbox_grub = new Box (Orientation.HORIZONTAL, 6);
 
199
                hbox_grub.margin_right = 6;
 
200
        hbox_grub.margin_bottom = 6;
 
201
        vbox_target.add (hbox_grub);
 
202
                
 
203
                string grub_msg = _("Re-install GRUB2 bootloader on the target device (recommended)");
 
204
                
 
205
                //chk_restore_grub2
 
206
                chk_restore_grub2 = new CheckButton.with_label(_("Re-install GRUB2") + ":");
 
207
                chk_restore_grub2.active = true;
 
208
                chk_restore_grub2.set_tooltip_markup(grub_msg);
 
209
                hbox_grub.add(chk_restore_grub2);
 
210
 
 
211
                chk_restore_grub2.toggled.connect(()=>{
 
212
                        cmb_boot_device.sensitive = chk_restore_grub2.active;
 
213
                });
 
214
 
 
215
                //cmb_boot_device
 
216
                cmb_boot_device = new ComboBox ();
 
217
                cmb_boot_device.hexpand = true;
 
218
                hbox_grub.add(cmb_boot_device);
 
219
                
 
220
                CellRendererText cell_dev_margin = new CellRendererText ();
 
221
                cell_dev_margin.text = "";
 
222
                cmb_boot_device.pack_start (cell_dev_margin, false);
 
223
                
 
224
                CellRendererPixbuf cell_dev_icon = new CellRendererPixbuf ();
 
225
                cell_dev_icon.stock_id = Stock.HARDDISK;
 
226
                cmb_boot_device.pack_start (cell_dev_icon, false);
 
227
                
 
228
                CellRendererText cell_device_grub = new CellRendererText();
 
229
        cmb_boot_device.pack_start(cell_device_grub, false );
 
230
        cmb_boot_device.set_cell_data_func (cell_device_grub, cell_device_grub_render);
 
231
        
 
232
        //Exclude tab ---------------------------------------------
 
233
                
 
234
                //lbl_exclude
 
235
                lbl_exclude = new Label (_("Advanced"));
 
236
 
 
237
        //vbox_exclude
 
238
        vbox_exclude = new Box(Gtk.Orientation.VERTICAL, 6);
 
239
        vbox_exclude.margin = 6;
 
240
        notebook.append_page (vbox_exclude, lbl_exclude);
 
241
 
 
242
                //toolbar_exclude ---------------------------------------------------
 
243
        
 
244
        //toolbar_exclude
 
245
                toolbar_exclude = new Gtk.Toolbar ();
 
246
                toolbar_exclude.toolbar_style = ToolbarStyle.BOTH_HORIZ;
 
247
                vbox_exclude.add(toolbar_exclude);
 
248
                
 
249
                string png_exclude = App.share_folder + "/timeshift/images/item-gray.png";
 
250
                string png_include = App.share_folder + "/timeshift/images/item-blue.png";
 
251
                
 
252
                //btn_exclude
 
253
                btn_exclude = new Gtk.MenuToolButton(null,"");
 
254
                toolbar_exclude.add(btn_exclude);
 
255
                
 
256
                btn_exclude.is_important = true;
 
257
                btn_exclude.label = _("Exclude");
 
258
                btn_exclude.set_tooltip_text (_("Exclude"));
 
259
                btn_exclude.set_icon_widget(new Gtk.Image.from_file (png_exclude));
 
260
                
 
261
                //btn_include
 
262
                btn_include = new Gtk.MenuToolButton(null,"");
 
263
                toolbar_exclude.add(btn_include);
 
264
                
 
265
                btn_include.is_important = true;
 
266
                btn_include.label = _("Include");
 
267
                btn_include.set_tooltip_text (_("Include"));
 
268
                btn_include.set_icon_widget(new Gtk.Image.from_file (png_include));
 
269
                
 
270
                //btn_remove
 
271
                btn_remove = new Gtk.ToolButton.from_stock(Gtk.Stock.REMOVE);
 
272
                toolbar_exclude.add(btn_remove);
 
273
                
 
274
                btn_remove.is_important = true;
 
275
                btn_remove.label = _("Remove");
 
276
                btn_remove.set_tooltip_text (_("Remove selected items"));
 
277
 
 
278
                btn_remove.clicked.connect (btn_remove_clicked);
 
279
 
 
280
                //btn_warning
 
281
                btn_warning = new Gtk.ToolButton.from_stock(Gtk.Stock.DIALOG_WARNING);
 
282
                toolbar_exclude.add(btn_warning);
 
283
                
 
284
                btn_warning.is_important = true;
 
285
                btn_warning.label = _("Warning");
 
286
                btn_warning.set_tooltip_text (_("Warning"));
 
287
 
 
288
                btn_warning.clicked.connect (btn_warning_clicked);
 
289
 
 
290
                //separator
 
291
                var separator = new Gtk.SeparatorToolItem();
 
292
                separator.set_draw (false);
 
293
                separator.set_expand (true);
 
294
                toolbar_exclude.add(separator);
 
295
                
 
296
                //btn_reset_exclude_list
 
297
                btn_reset_exclude_list = new Gtk.ToolButton.from_stock(Gtk.Stock.REFRESH);
 
298
                toolbar_exclude.add(btn_reset_exclude_list);
 
299
                
 
300
                btn_reset_exclude_list.is_important = false;
 
301
                btn_reset_exclude_list.label = _("Reset");
 
302
                btn_reset_exclude_list.set_tooltip_text (_("Reset this list to default state"));
 
303
 
 
304
                btn_reset_exclude_list.clicked.connect (btn_reset_exclude_list_clicked);
 
305
                
 
306
                //menu --------------------------------------------------
 
307
                
 
308
        //menu_exclude
 
309
                menu_exclude = new Gtk.Menu();
 
310
                btn_exclude.set_menu(menu_exclude);
 
311
                
 
312
                //menu_exclude_add_file
 
313
                menu_exclude_add_file = new ImageMenuItem.with_label ("");
 
314
                menu_exclude_add_file.label = _("Exclude File(s)");
 
315
                menu_exclude_add_file.set_image(new Gtk.Image.from_file (png_exclude));
 
316
                menu_exclude.append(menu_exclude_add_file);
 
317
                
 
318
                menu_exclude_add_file.activate.connect (menu_exclude_add_files_clicked);
 
319
 
 
320
                //menu_exclude_add_folder
 
321
                menu_exclude_add_folder = new ImageMenuItem.with_label ("");
 
322
                menu_exclude_add_folder.label = _("Exclude Directory");
 
323
                menu_exclude_add_folder.set_image(new Gtk.Image.from_file (png_exclude));
 
324
                menu_exclude.append(menu_exclude_add_folder);
 
325
                
 
326
                menu_exclude_add_folder.activate.connect (menu_exclude_add_folder_clicked);
 
327
 
 
328
                //menu_exclude_add_folder_contents
 
329
                menu_exclude_add_folder_contents = new ImageMenuItem.with_label ("");
 
330
                menu_exclude_add_folder_contents.label = _("Exclude Directory Contents");
 
331
                menu_exclude_add_folder_contents.set_image(new Gtk.Image.from_file (png_exclude));
 
332
                menu_exclude.append(menu_exclude_add_folder_contents);
 
333
                
 
334
                menu_exclude_add_folder_contents.activate.connect (menu_exclude_add_folder_contents_clicked);
 
335
                
 
336
                //menu_include
 
337
                menu_include = new Gtk.Menu();
 
338
                btn_include.set_menu(menu_include);
 
339
                
 
340
                //menu_include_add_file
 
341
                menu_include_add_file = new ImageMenuItem.with_label ("");
 
342
                menu_include_add_file.label = _("Include File(s)");
 
343
                menu_include_add_file.set_image(new Gtk.Image.from_file (png_include));
 
344
                menu_include.append(menu_include_add_file);
 
345
                
 
346
                menu_include_add_file.activate.connect (menu_include_add_files_clicked);
 
347
 
 
348
                //menu_include_add_folder
 
349
                menu_include_add_folder = new ImageMenuItem.with_label ("");
 
350
                menu_include_add_folder.label = _("Include Directory");
 
351
                menu_include_add_folder.set_image(new Gtk.Image.from_file (png_include));
 
352
                menu_include.append(menu_include_add_folder);
 
353
                
 
354
                menu_include_add_folder.activate.connect (menu_include_add_folder_clicked);
 
355
                
 
356
                menu_exclude.show_all();
 
357
                menu_include.show_all();
 
358
                
 
359
                //tv_exclude-----------------------------------------------
 
360
                
 
361
                //tv_exclude
 
362
                tv_exclude = new TreeView();
 
363
                tv_exclude.get_selection().mode = SelectionMode.MULTIPLE;
 
364
                tv_exclude.headers_visible = true;
 
365
                tv_exclude.set_rules_hint (true);
 
366
                //tv_exclude.row_activated.connect(tv_exclude_row_activated);
 
367
                
 
368
                //sw_exclude
 
369
                sw_exclude = new ScrolledWindow(null, null);
 
370
                sw_exclude.set_shadow_type (ShadowType.ETCHED_IN);
 
371
                sw_exclude.add (tv_exclude);
 
372
                sw_exclude.expand = true;
 
373
                vbox_exclude.add(sw_exclude);
 
374
 
 
375
        //col_exclude
 
376
                col_exclude = new TreeViewColumn();
 
377
                col_exclude.title = _("File Pattern");
 
378
                col_exclude.expand = true;
 
379
                
 
380
                CellRendererText cell_exclude_margin = new CellRendererText ();
 
381
                cell_exclude_margin.text = "";
 
382
                col_exclude.pack_start (cell_exclude_margin, false);
 
383
                
 
384
                CellRendererPixbuf cell_exclude_icon = new CellRendererPixbuf ();
 
385
                col_exclude.pack_start (cell_exclude_icon, false);
 
386
                col_exclude.set_attributes(cell_exclude_icon, "pixbuf", 1);
 
387
                
 
388
                CellRendererText cell_exclude_text = new CellRendererText ();
 
389
                col_exclude.pack_start (cell_exclude_text, false);
 
390
                col_exclude.set_cell_data_func (cell_exclude_text, cell_exclude_text_render);
 
391
                cell_exclude_text.editable = true;
 
392
                tv_exclude.append_column(col_exclude);
 
393
        
 
394
                cell_exclude_text.edited.connect (cell_exclude_text_edited);
 
395
                
 
396
                //lnk_default_list
 
397
                lnk_default_list = new LinkButton.with_label("",_("Some locations are excluded by default"));
 
398
                lnk_default_list.xalign = (float) 0.0;
 
399
                lnk_default_list.activate_link.connect(lnk_default_list_activate);
 
400
                vbox_exclude.add(lnk_default_list);
 
401
                
 
402
                //Actions ----------------------------------------------
 
403
                
 
404
                //hbox_action
 
405
        hbox_action = (Box) get_action_area ();
 
406
 
 
407
        //btn_restore
 
408
        btn_restore = new Button();
 
409
        hbox_action.add(btn_restore);
 
410
        
 
411
        btn_restore.set_label (" " + _("Restore"));
 
412
        btn_restore.set_tooltip_text (_("Restore"));
 
413
        Gtk.Image img_restore = new Image.from_stock(Gtk.Stock.GO_FORWARD, Gtk.IconSize.BUTTON);
 
414
                btn_restore.set_image(img_restore);
 
415
        btn_restore.clicked.connect (btn_restore_clicked);
 
416
 
 
417
        //btn_cancel
 
418
        btn_cancel = new Button();
 
419
        hbox_action.add(btn_cancel);
 
420
        
 
421
        btn_cancel.set_label (" " + _("Cancel"));
 
422
        btn_cancel.set_tooltip_text (_("Cancel"));
 
423
        Gtk.Image img_cancel = new Image.from_stock(Gtk.Stock.CANCEL, Gtk.IconSize.BUTTON);
 
424
                btn_cancel.set_image(img_cancel);
 
425
        btn_cancel.clicked.connect (btn_cancel_clicked);
 
426
 
 
427
                //initialize -----------------------------------------
 
428
                
 
429
                refresh_tv_partitions();
 
430
                refresh_cmb_boot_device();
 
431
                
 
432
                btn_reset_exclude_list_clicked();
 
433
 
 
434
                chk_restore_grub2.active = true; //keep enabled always
 
435
                chk_restore_grub2.sensitive = false; //don't allow user to disable
 
436
                cmb_boot_device.sensitive = chk_restore_grub2.active;
 
437
        }
 
438
 
 
439
 
 
440
        private void cell_device_target_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
441
                PartitionInfo pi;
 
442
                model.get (iter, 0, out pi, -1);
 
443
                if ((App.root_device != null) && (pi.device == App.root_device.device)){
 
444
                        (cell as Gtk.CellRendererText).text = pi.device_name_sdaX + " (" + _("sys") + ")";
 
445
                }
 
446
                else{
 
447
                        (cell as Gtk.CellRendererText).text = pi.device_name_sdaX;
 
448
                }
 
449
        }
 
450
 
 
451
        private void cell_fs_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
452
                PartitionInfo pi;
 
453
                model.get (iter, 0, out pi, -1);
 
454
                (cell as Gtk.CellRendererText).text = pi.type;
 
455
        }
 
456
        
 
457
        private void cell_size_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
458
                PartitionInfo pi;
 
459
                model.get (iter, 0, out pi, -1);
 
460
                (cell as Gtk.CellRendererText).text = pi.size;
 
461
        }
 
462
        
 
463
        private void cell_used_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
464
                PartitionInfo pi;
 
465
                model.get (iter, 0, out pi, -1);
 
466
                (cell as Gtk.CellRendererText).text = pi.used;
 
467
        }
 
468
        
 
469
        private void cell_label_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
470
                PartitionInfo pi;
 
471
                model.get (iter, 0, out pi, -1);
 
472
                (cell as Gtk.CellRendererText).text = pi.label;
 
473
        }
 
474
 
 
475
        private void cell_dist_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
476
                PartitionInfo pi;
 
477
                model.get (iter, 0, out pi, -1);
 
478
                (cell as Gtk.CellRendererText).text = pi.dist_info;
 
479
        }
 
480
        
 
481
        private void cell_device_grub_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
482
                DeviceInfo info;
 
483
                model.get (iter, 0, out info, -1);
 
484
                (cell as Gtk.CellRendererText).text = info.description;
 
485
        }
 
486
 
 
487
        private void cell_exclude_text_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
488
                string pattern, color;
 
489
                model.get (iter, 0, out pattern, 2, out color, -1);
 
490
                (cell as Gtk.CellRendererText).text = pattern.has_prefix("+ ") ? pattern[2:pattern.length] : pattern;
 
491
                (cell as Gtk.CellRendererText).foreground = color;
 
492
        }
 
493
 
 
494
        private void cell_exclude_text_edited (string path, string new_text) {
 
495
                string entry;
 
496
 
 
497
                TreeIter iter;
 
498
                ListStore model = (ListStore) tv_exclude.model;
 
499
                model.get_iter_from_string (out iter, path);
 
500
                model.get (iter, 0, out entry, -1);
 
501
                model.set (iter, 0, new_text);
 
502
        }
 
503
 
 
504
 
 
505
        private void refresh_cmb_boot_device(){
 
506
                ListStore store = new ListStore(1, typeof(DeviceInfo));
 
507
 
 
508
                TreeIter iter;
 
509
 
 
510
                int index = -1;
 
511
                int selected_index = -1;
 
512
                int default_index = -1;
 
513
                
 
514
                foreach(DeviceInfo di in get_block_devices()) {
 
515
                        store.append(out iter);
 
516
                        store.set (iter, 0, di);
 
517
 
 
518
                        index++;
 
519
                        if ((App.restore_target != null) && (di.device == App.restore_target.device[0:-1])){
 
520
                                selected_index = index;
 
521
                        }
 
522
                }
 
523
                
 
524
                if (selected_index == -1){
 
525
                        selected_index = default_index;
 
526
                }
 
527
                
 
528
                cmb_boot_device.set_model (store);
 
529
                cmb_boot_device.active = selected_index;
 
530
        }
 
531
        
 
532
        private void refresh_tv_partitions(){
 
533
                
 
534
                App.update_partition_list();
 
535
                
 
536
                ListStore model = new ListStore(1, typeof(PartitionInfo));
 
537
                
 
538
                var list = App.partition_list;
 
539
                list.sort((a,b) => { 
 
540
                                        PartitionInfo p1 = (PartitionInfo) a;
 
541
                                        PartitionInfo p2 = (PartitionInfo) b;
 
542
                                        
 
543
                                        return strcmp(p1.device,p2.device);
 
544
                                });
 
545
 
 
546
                TreeIter iter;
 
547
                TreePath path_selected = null;
 
548
                
 
549
                foreach(PartitionInfo pi in list) {
 
550
                        if (!pi.has_linux_filesystem()) { continue; }
 
551
                        
 
552
                        model.append(out iter);
 
553
                        model.set (iter, 0, pi);
 
554
                        
 
555
                        if ((App.restore_target != null) && (App.restore_target.device == pi.device)){
 
556
                                path_selected = model.get_path(iter);
 
557
                        }
 
558
                }
 
559
                        
 
560
                tv_partitions.set_model (model);
 
561
                if (path_selected != null){
 
562
                        tv_partitions.get_selection().select_path(path_selected);
 
563
                }
 
564
                //tv_partitions.columns_autosize ();
 
565
        }
 
566
        
 
567
        private void refresh_tv_exclude(){
 
568
                ListStore model = new ListStore(3, typeof(string), typeof(Gdk.Pixbuf), typeof(string));
 
569
                tv_exclude.model = model;
 
570
                
 
571
                foreach(string path in temp_exclude_list){
 
572
                        tv_exclude_add_item(path);
 
573
                }
 
574
        }
 
575
 
 
576
        private void tv_exclude_add_item(string path){
 
577
                Gdk.Pixbuf pix_exclude = null;
 
578
                Gdk.Pixbuf pix_include = null;
 
579
                Gdk.Pixbuf pix_selected = null;
 
580
                string text_color;
 
581
                
 
582
                try{
 
583
                        pix_exclude = new Gdk.Pixbuf.from_file (App.share_folder + "/timeshift/images/item-gray.png");
 
584
                        pix_include = new Gdk.Pixbuf.from_file (App.share_folder + "/timeshift/images/item-blue.png");
 
585
                }
 
586
        catch(Error e){
 
587
                log_error (e.message);
 
588
            }
 
589
 
 
590
                TreeIter iter;
 
591
                ListStore model = (ListStore) tv_exclude.model;
 
592
                model.append(out iter);
 
593
                        
 
594
                if (path.has_prefix("+ ")){
 
595
                        pix_selected = pix_include;
 
596
                }
 
597
                else{
 
598
                        pix_selected = pix_exclude;
 
599
                }
 
600
                        
 
601
                if (App.exclude_list_default.contains(path)){
 
602
                        text_color = "#0B610B";
 
603
                }
 
604
                else{
 
605
                        text_color = "#000000";
 
606
                }
 
607
                
 
608
                model.set (iter, 0, path, 1, pix_selected, 2, text_color, -1);
 
609
                
 
610
                Adjustment adj = tv_exclude.get_hadjustment();
 
611
                adj.value = adj.upper;
 
612
        }
 
613
                        
 
614
        private bool lnk_default_list_activate(){
 
615
                string msg = "";
 
616
                msg += "<b>" + _("Exclude List") + ":</b>\n\n";
 
617
                msg += _("Files matching the following patterns will be <i>excluded</i>") + ":\n\n";
 
618
                
 
619
                foreach(string path in App.exclude_list_default){
 
620
                        msg += path + "\n";
 
621
                }
 
622
                msg += "\n";
 
623
                
 
624
                msg += "<b>" + _("Home Directory") + ":</b>\n\n";
 
625
                msg += _("Hidden files and folders are included by default since \nthey contain user-specific configuration files.") + "\n";
 
626
                msg += _("All other files and folders are excluded.") + "\n";
 
627
 
 
628
                var dialog = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, msg);
 
629
                dialog.set_title(_("Default Entries"));
 
630
                dialog.set_default_size (200, -1);
 
631
                dialog.set_transient_for(this);
 
632
                dialog.set_modal(true);
 
633
                dialog.run();
 
634
                dialog.destroy();
 
635
 
 
636
                return true;
 
637
        }
 
638
 
 
639
        private bool tv_partitions_button_press_event(Gdk.EventButton event){
 
640
                TreeIter iter;
 
641
                ListStore store;
 
642
                TreeSelection sel;
 
643
                bool iterExists;
 
644
                
 
645
                //get selected target device
 
646
                PartitionInfo restore_target = null;
 
647
                sel = tv_partitions.get_selection ();
 
648
                store = (ListStore) tv_partitions.model;
 
649
                iterExists = store.get_iter_first (out iter);
 
650
                while (iterExists) { 
 
651
                        if (sel.iter_is_selected (iter)){
 
652
                                store.get (iter, 0, out restore_target);
 
653
                                break;
 
654
                        }
 
655
                        iterExists = store.iter_next (ref iter);
 
656
                }
 
657
                App.restore_target = restore_target;
 
658
 
 
659
                //select grub target device
 
660
                refresh_cmb_boot_device(); 
 
661
 
 
662
                return false;
 
663
        }
 
664
 
 
665
 
 
666
        private void menu_exclude_add_files_clicked(){
 
667
                
 
668
                var list = browse_files();
 
669
                
 
670
                if (list.length() > 0){
 
671
                        foreach(string path in list){
 
672
                                if (!temp_exclude_list.contains(path)){
 
673
                                        temp_exclude_list.add(path);
 
674
                                        tv_exclude_add_item(path);
 
675
                                        App.first_snapshot_size = 0; //re-calculate
 
676
                                }
 
677
                        }
 
678
                }
 
679
        }
 
680
 
 
681
        private void menu_exclude_add_folder_clicked(){
 
682
                
 
683
                var list = browse_folder();
 
684
                
 
685
                if (list.length() > 0){
 
686
                        foreach(string path in list){
 
687
                                
 
688
                                path = path + "/";
 
689
                                
 
690
                                if (!temp_exclude_list.contains(path)){
 
691
                                        temp_exclude_list.add(path);
 
692
                                        tv_exclude_add_item(path);
 
693
                                        App.first_snapshot_size = 0; //re-calculate
 
694
                                }
 
695
                        }
 
696
                }
 
697
        }
 
698
 
 
699
        private void menu_exclude_add_folder_contents_clicked(){
 
700
                
 
701
                var list = browse_folder();
 
702
                
 
703
                if (list.length() > 0){
 
704
                        foreach(string path in list){
 
705
                                
 
706
                                path = path + "/*";
 
707
                                
 
708
                                if (!temp_exclude_list.contains(path)){
 
709
                                        temp_exclude_list.add(path);
 
710
                                        tv_exclude_add_item(path);
 
711
                                        App.first_snapshot_size = 0; //re-calculate
 
712
                                }
 
713
                        }
 
714
                }
 
715
        }
 
716
 
 
717
        private void menu_include_add_files_clicked(){
 
718
                
 
719
                var list = browse_files();
 
720
                
 
721
                if (list.length() > 0){
 
722
                        foreach(string path in list){
 
723
                                
 
724
                                path = path.has_prefix("+ ") ? path : "+ " + path;
 
725
                                
 
726
                                if (!temp_exclude_list.contains(path)){
 
727
                                        temp_exclude_list.add(path);
 
728
                                        tv_exclude_add_item(path);
 
729
                                        App.first_snapshot_size = 0; //re-calculate
 
730
                                }
 
731
                        }
 
732
                }
 
733
        }
 
734
 
 
735
        private void menu_include_add_folder_clicked(){
 
736
                
 
737
                var list = browse_folder();
 
738
                
 
739
                if (list.length() > 0){
 
740
                        foreach(string path in list){
 
741
                                
 
742
                                path = path.has_prefix("+ ") ? path : "+ " + path;
 
743
                                path = path + "/***";
 
744
                                
 
745
                                if (!temp_exclude_list.contains(path)){
 
746
                                        temp_exclude_list.add(path);
 
747
                                        tv_exclude_add_item(path);
 
748
                                        App.first_snapshot_size = 0; //re-calculate
 
749
                                }
 
750
                        }
 
751
                }
 
752
        }
 
753
 
 
754
        private SList<string> browse_files(){
 
755
                var dialog = new Gtk.FileChooserDialog(_("Select file(s)"), this, Gtk.FileChooserAction.OPEN,
 
756
                                                        Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,
 
757
                                                        Gtk.Stock.OPEN, Gtk.ResponseType.ACCEPT);
 
758
                dialog.action = FileChooserAction.OPEN;
 
759
                dialog.set_transient_for(this);
 
760
                dialog.local_only = true;
 
761
                dialog.set_modal (true);
 
762
                dialog.set_select_multiple (true);
 
763
 
 
764
                dialog.run();
 
765
                var list = dialog.get_filenames();
 
766
                dialog.destroy ();
 
767
                
 
768
                return list;
 
769
        }
 
770
 
 
771
        private SList<string> browse_folder(){
 
772
                var dialog = new Gtk.FileChooserDialog(_("Select directory"), this, Gtk.FileChooserAction.OPEN,
 
773
                                                        Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,
 
774
                                                        Gtk.Stock.OPEN, Gtk.ResponseType.ACCEPT);
 
775
                dialog.action = FileChooserAction.SELECT_FOLDER;
 
776
                dialog.local_only = true;
 
777
                dialog.set_transient_for(this);
 
778
                dialog.set_modal (true);
 
779
                dialog.set_select_multiple (false);
 
780
                
 
781
                dialog.run();
 
782
                var list = dialog.get_filenames();
 
783
                dialog.destroy ();
 
784
                
 
785
                return list;
 
786
        }
 
787
 
 
788
 
 
789
        private void btn_remove_clicked(){
 
790
                TreeSelection sel = tv_exclude.get_selection ();
 
791
                TreeIter iter;
 
792
                bool iterExists = tv_exclude.model.get_iter_first (out iter);
 
793
                while (iterExists) { 
 
794
                        if (sel.iter_is_selected (iter)){
 
795
                                string path;
 
796
                                tv_exclude.model.get (iter, 0, out path);
 
797
                                temp_exclude_list.remove(path);
 
798
                                App.first_snapshot_size = 0; //re-calculate
 
799
                        }
 
800
                        iterExists = tv_exclude.model.iter_next (ref iter);
 
801
                }
 
802
 
 
803
                refresh_tv_exclude();
 
804
        }
 
805
 
 
806
        private void btn_warning_clicked(){
 
807
                string msg = "";
 
808
                msg += _("Please do NOT modify this list unless you have a very good reason for doing so.") + " ";
 
809
                msg += _("By default, any item that was included/excluded at the time of taking the snapshot will be included/excluded.") + " ";
 
810
                msg += _("Any exclude patterns in the current exclude list will also be excluded.") + " ";
 
811
                msg += _("To see which files are included in the snapshot use the 'Browse' button on the main window.");
 
812
                
 
813
                var dialog = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, msg);
 
814
                dialog.set_title("Warning");
 
815
                dialog.set_default_size (200, -1);
 
816
                dialog.set_transient_for(this);
 
817
                dialog.set_modal(true);
 
818
                dialog.run();
 
819
                dialog.destroy();
 
820
        }
 
821
        
 
822
        private void btn_reset_exclude_list_clicked(){
 
823
                //create a temp exclude list ----------------------------
 
824
                
 
825
                temp_exclude_list = new Gee.ArrayList<string>();
 
826
                
 
827
                //add all include/exclude items from snapshot list
 
828
                foreach(string path in App.snapshot_to_restore.exclude_list){
 
829
                        if (!temp_exclude_list.contains(path) && !App.exclude_list_default.contains(path) && !App.exclude_list_home.contains(path)){
 
830
                                temp_exclude_list.add(path);
 
831
                        }
 
832
                }
 
833
                
 
834
                //add all exclude items from current list
 
835
                foreach(string path in App.exclude_list_user){
 
836
                        if (!temp_exclude_list.contains(path) && !App.exclude_list_default.contains(path) && !App.exclude_list_home.contains(path)){
 
837
                                
 
838
                                if (!path.has_prefix("+ ")){            //don't add include entries from current exclude list
 
839
                                        temp_exclude_list.add(path);
 
840
                                }
 
841
                        }
 
842
                }               
 
843
                
 
844
                //refresh treeview --------------------------
 
845
                
 
846
                refresh_tv_exclude();
 
847
        }
 
848
        
 
849
 
 
850
        private void btn_restore_clicked(){
 
851
                
 
852
                //Note: A successful restore will reboot the system if target device is same as system device
 
853
                
 
854
                TreeIter iter;
 
855
                ListStore store;
 
856
                TreeSelection sel;
 
857
                bool iterExists;
 
858
                
 
859
                //check single target partition selected ---------------
 
860
                
 
861
                sel = tv_partitions.get_selection ();
 
862
                if (sel.count_selected_rows() != 1){ 
 
863
                        messagebox_show(_("Select Target Device"),_("Please select the target device from the list"), true);
 
864
                        return; 
 
865
                }
 
866
 
 
867
                //get selected target partition ------------------
 
868
                
 
869
                PartitionInfo restore_target = null;
 
870
                sel = tv_partitions.get_selection ();
 
871
                store = (ListStore) tv_partitions.model;
 
872
                iterExists = store.get_iter_first (out iter);
 
873
                while (iterExists) { 
 
874
                        if (sel.iter_is_selected (iter)){
 
875
                                store.get (iter, 0, out restore_target);
 
876
                                break;
 
877
                        }
 
878
                        iterExists = store.iter_next (ref iter);
 
879
                }
 
880
                App.restore_target = restore_target;
 
881
                
 
882
                //save modified exclude list ----------------------
 
883
                
 
884
                App.exclude_list_restore.clear();
 
885
                
 
886
                //add default entries
 
887
                foreach(string path in App.exclude_list_default){
 
888
                        if (!App.exclude_list_restore.contains(path)){
 
889
                                App.exclude_list_restore.add(path);
 
890
                        }
 
891
                }
 
892
                
 
893
                //add modified user entries
 
894
                foreach(string path in temp_exclude_list){
 
895
                        if (!App.exclude_list_restore.contains(path) && !App.exclude_list_home.contains(path)){
 
896
                                App.exclude_list_restore.add(path);
 
897
                        }
 
898
                }
 
899
 
 
900
                //add home entries
 
901
                foreach(string path in App.exclude_list_home){
 
902
                        if (!App.exclude_list_restore.contains(path)){
 
903
                                App.exclude_list_restore.add(path);
 
904
                        }
 
905
                }
 
906
                
 
907
                string timeshift_path = "/timeshift/*";
 
908
                if (!App.exclude_list_restore.contains(timeshift_path)){
 
909
                        App.exclude_list_restore.add(timeshift_path);
 
910
                }
 
911
                
 
912
                //save grub install options ----------------------
 
913
                
 
914
                App.reinstall_grub2 = chk_restore_grub2.active;
 
915
                
 
916
                if (App.reinstall_grub2){
 
917
                        DeviceInfo dev;
 
918
                        cmb_boot_device.get_active_iter (out iter);
 
919
                        TreeModel model = (TreeModel) cmb_boot_device.model;
 
920
                        model.get(iter, 0, out dev);
 
921
                        App.grub_device = dev;
 
922
                }
 
923
                
 
924
                //last option to quit - show disclaimer ------------
 
925
                
 
926
                if (show_disclaimer() == Gtk.ResponseType.YES){
 
927
                        this.response(Gtk.ResponseType.OK);
 
928
                }
 
929
                else{
 
930
                        this.response(Gtk.ResponseType.CANCEL);
 
931
                }
 
932
        }
 
933
 
 
934
        private int show_disclaimer(){
 
935
                string msg = "";
 
936
                msg += "<b>" + _("WARNING") + ":</b>\n\n";
 
937
                msg += _("Files will be overwritten on the target device!") + "\n";
 
938
                msg += _("If the restore fails for any reason and you are unable to boot the system, \nplease boot from the Ubuntu Live CD and try again.") + "\n";
 
939
                
 
940
                if ((App.root_device != null) && (App.restore_target.device == App.root_device.device)){
 
941
                        msg += "\n<b>" + _("Please save your work and close all applications.") + "\n";
 
942
                        msg += _("System will reboot to complete the restore process.") + "</b>\n";
 
943
                }
 
944
                
 
945
                msg += "\n";
 
946
                msg += "<b>" + _("DISCLAIMER") + ":</b>\n\n";
 
947
                msg += _("This software comes without absolutely NO warranty and the author takes no responsibility for any damage arising from the use of this program.");
 
948
                msg += " " + _("If these terms are not acceptable to you, please do not proceed beyond this point!") + "\n";
 
949
                msg += "\n";
 
950
                msg += "<b>" + _("Continue with restore?") + "</b>\n";
 
951
                
 
952
                var dialog = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, msg);
 
953
                dialog.set_title(_("DISCLAIMER"));
 
954
                dialog.set_default_size (200, -1);
 
955
                dialog.set_transient_for(this);
 
956
                dialog.set_modal(true);
 
957
                int response = dialog.run();
 
958
                dialog.destroy();
 
959
                return response;
 
960
        }
 
961
 
 
962
        private void btn_cancel_clicked(){
 
963
                this.response(Gtk.ResponseType.CANCEL);
 
964
                return; 
 
965
        }
 
966
 
 
967
}