~teejee2008/timeshift/trunk

« back to all changes in this revision

Viewing changes to src/Gtk/SettingsWindow.vala

  • Committer: Tony George
  • Date: 2016-08-13 04:16:47 UTC
  • Revision ID: tony.george.kol@gmail.com-20160813041647-ivf2g6rszt00xco5
Updated project structure

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SettingsWindow.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
 
 
27
using TeeJee.Logging;
 
28
using TeeJee.FileSystem;
 
29
using TeeJee.Devices;
 
30
using TeeJee.JsonHelper;
 
31
using TeeJee.ProcessHelper;
 
32
using TeeJee.GtkHelper;
 
33
using TeeJee.System;
 
34
using TeeJee.Misc;
 
35
 
 
36
public class SettingsWindow : Gtk.Dialog{
 
37
        private Box vbox_main;
 
38
        private Notebook notebook;
 
39
 
 
40
        //schedule
 
41
        private Label lbl_schedule;
 
42
        private Box vbox_schedule;
 
43
        private CheckButton chk_schedule;
 
44
        private TreeView tv_schedule;
 
45
        private ScrolledWindow sw_schedule;
 
46
        private TreeViewColumn col_sched_enable;
 
47
        private TreeViewColumn col_sched_level;
 
48
        private TreeViewColumn col_sched_desc;
 
49
 
 
50
        //auto_remove
 
51
        private Label lbl_auto_remove;
 
52
        private Box vbox_auto_remove;
 
53
        private TreeView tv_remove;
 
54
        private ScrolledWindow sw_remove;
 
55
        private TreeViewColumn col_remove_rule;
 
56
        private TreeViewColumn col_remove_limit;
 
57
        private TreeViewColumn col_remove_units;
 
58
 
 
59
        //exclude
 
60
        private Label lbl_exclude;
 
61
        private Box vbox_exclude;
 
62
        private LinkButton lnk_default_list;
 
63
        private TreeView tv_exclude;
 
64
        private ScrolledWindow sw_exclude;
 
65
        private TreeViewColumn col_exclude;
 
66
        private Toolbar toolbar_exclude;
 
67
        private ToolButton btn_remove;
 
68
        private ToolButton btn_warning;
 
69
        private ToolButton btn_reset_exclude_list;
 
70
 
 
71
        private MenuToolButton btn_exclude;
 
72
        private Gtk.Menu menu_exclude;
 
73
        private ImageMenuItem menu_exclude_add_file;
 
74
        private ImageMenuItem menu_exclude_add_folder;
 
75
        private ImageMenuItem menu_exclude_add_folder_contents;
 
76
 
 
77
        private MenuToolButton btn_include;
 
78
        private Gtk.Menu menu_include;
 
79
        private ImageMenuItem menu_include_add_file;
 
80
        private ImageMenuItem menu_include_add_folder;
 
81
 
 
82
        //actions
 
83
        private Button btn_save;
 
84
        private Button btn_cancel;
 
85
 
 
86
        private Gee.ArrayList<string> temp_exclude_list;
 
87
 
 
88
        public SettingsWindow () {
 
89
                this.deletable = false;
 
90
                this.title = _("Settings");
 
91
        this.window_position = WindowPosition.CENTER_ON_PARENT;
 
92
        this.set_destroy_with_parent (true);
 
93
                this.set_modal (true);
 
94
        this.set_default_size (450, 450);
 
95
                this.icon = get_app_icon(16);
 
96
 
 
97
            //vboxMain
 
98
        vbox_main = get_content_area ();
 
99
 
 
100
        //notebook
 
101
                notebook = new Notebook ();
 
102
                notebook.margin = 12;
 
103
                vbox_main.pack_start (notebook, true, true, 0);
 
104
 
 
105
        //schedule tab ---------------------------------------------
 
106
 
 
107
                //lbl_schedule
 
108
                lbl_schedule = new Label (_("Schedule"));
 
109
 
 
110
        //vbox_schedule
 
111
        vbox_schedule = new Box (Gtk.Orientation.VERTICAL, 6);
 
112
        vbox_schedule.margin = 6;
 
113
        notebook.append_page (vbox_schedule, lbl_schedule);
 
114
 
 
115
                //automatic snapshots ------------------------------
 
116
 
 
117
                //chk_schedule
 
118
        chk_schedule = new Gtk.CheckButton.with_label(_("Create scheduled/automatic snapshots"));
 
119
        chk_schedule.active = App.is_scheduled;
 
120
        vbox_schedule.pack_start(chk_schedule,false,false,0);
 
121
 
 
122
        chk_schedule.notify["active"].connect(chk_schedule_changed);
 
123
 
 
124
                //tv_schedule -----------------------------------------------
 
125
 
 
126
        //tv_schedule
 
127
                tv_schedule = new TreeView();
 
128
                tv_schedule.get_selection().mode = SelectionMode.MULTIPLE;
 
129
                tv_schedule.set_rules_hint (true);
 
130
 
 
131
                //sw_schedule
 
132
                sw_schedule = new ScrolledWindow(null, null);
 
133
                sw_schedule.set_shadow_type (ShadowType.ETCHED_IN);
 
134
                sw_schedule.add (tv_schedule);
 
135
                sw_schedule.expand = true;
 
136
                vbox_schedule.add(sw_schedule);
 
137
 
 
138
                //col_sched_enable
 
139
                col_sched_enable = new TreeViewColumn();
 
140
                col_sched_enable.title = " " + _("Enable") + " ";
 
141
                CellRendererToggle cell_sched_enable = new CellRendererToggle ();
 
142
                cell_sched_enable.activatable = true;
 
143
                cell_sched_enable.toggled.connect (cell_sched_enable_toggled);
 
144
                col_sched_enable.pack_start (cell_sched_enable, false);
 
145
                col_sched_enable.set_cell_data_func (cell_sched_enable, cell_sched_enable_render);
 
146
                tv_schedule.append_column(col_sched_enable);
 
147
 
 
148
                //col_sched_level
 
149
                col_sched_level = new TreeViewColumn();
 
150
                col_sched_level.title = " " + _("Backup Level") + " ";
 
151
                CellRendererText cell_sched_level = new CellRendererText ();
 
152
                col_sched_level.pack_start (cell_sched_level, false);
 
153
                col_sched_level.set_cell_data_func (cell_sched_level, cell_sched_level_render);
 
154
                tv_schedule.append_column(col_sched_level);
 
155
 
 
156
                //col_sched_desc
 
157
                col_sched_desc = new TreeViewColumn();
 
158
                col_sched_desc.title = " " + _("Description") + " ";
 
159
                col_sched_desc.expand = true;
 
160
                CellRendererText cell_sched_desc = new CellRendererText ();
 
161
                col_sched_desc.pack_start (cell_sched_desc, false);
 
162
                col_sched_desc.set_cell_data_func (cell_sched_desc, cell_sched_desc_render);
 
163
                tv_schedule.append_column(col_sched_desc);
 
164
 
 
165
                //auto-remove tab ------------------------------------------------------
 
166
 
 
167
                //lbl_auto_remove
 
168
                lbl_auto_remove = new Label (_("Auto-Remove"));
 
169
 
 
170
        //vbox_auto_remove
 
171
        vbox_auto_remove = new Box(Gtk.Orientation.VERTICAL, 6);
 
172
        vbox_auto_remove.margin = 6;
 
173
        notebook.append_page (vbox_auto_remove, lbl_auto_remove);
 
174
 
 
175
                //lbl_auto_remove_msg
 
176
                Label lbl_auto_remove_msg = new Label (_("Snapshots matching following rules will be removed automatically"));
 
177
                lbl_auto_remove_msg.xalign = (float) 0.0;
 
178
                vbox_auto_remove.add(lbl_auto_remove_msg);
 
179
 
 
180
                //tv_remove
 
181
                tv_remove = new TreeView();
 
182
                tv_remove.get_selection().mode = SelectionMode.MULTIPLE;
 
183
                tv_remove.set_rules_hint (true);
 
184
 
 
185
                //sw_remove
 
186
                sw_remove = new ScrolledWindow(null, null);
 
187
                sw_remove.set_shadow_type (ShadowType.ETCHED_IN);
 
188
                sw_remove.add (tv_remove);
 
189
                sw_remove.expand = true;
 
190
                vbox_auto_remove.add(sw_remove);
 
191
 
 
192
                //col_remove_rule
 
193
                col_remove_rule = new TreeViewColumn();
 
194
                col_remove_rule.title = " " + _("Rule") + " ";
 
195
                CellRendererText cell_remove_rule = new CellRendererText ();
 
196
                col_remove_rule.pack_start (cell_remove_rule, false);
 
197
                col_remove_rule.set_cell_data_func (cell_remove_rule, cell_remove_rule_render);
 
198
                tv_remove.append_column(col_remove_rule);
 
199
 
 
200
                //col_sched_desc
 
201
                col_remove_limit = new TreeViewColumn();
 
202
                col_remove_limit.title = " " + _("Limit") + " ";
 
203
                CellRendererText cell_remove_limit = new CellRendererText ();
 
204
                cell_remove_limit.xalign = (float) 0.5;
 
205
                cell_remove_limit.editable = true;
 
206
                cell_remove_limit.edited.connect (cell_remove_limit_edited);
 
207
                col_remove_limit.pack_start (cell_remove_limit, false);
 
208
                col_remove_limit.set_cell_data_func (cell_remove_limit, cell_remove_limit_render);
 
209
                tv_remove.append_column(col_remove_limit);
 
210
 
 
211
                //col_remove_rule
 
212
                col_remove_units = new TreeViewColumn();
 
213
                col_remove_units.title = "";
 
214
                CellRendererText cell_remove_units = new CellRendererText ();
 
215
                col_remove_units.pack_start (cell_remove_units, false);
 
216
                col_remove_units.set_cell_data_func (cell_remove_units, cell_remove_units_render);
 
217
                tv_remove.append_column(col_remove_units);
 
218
 
 
219
                tv_schedule.sensitive = chk_schedule.active;
 
220
 
 
221
        //Exclude tab ---------------------------------------------
 
222
 
 
223
                //lbl_exclude
 
224
                lbl_exclude = new Label (_("Advanced"));
 
225
 
 
226
        //vbox_exclude
 
227
        vbox_exclude = new Box(Gtk.Orientation.VERTICAL, 6);
 
228
        vbox_exclude.margin = 6;
 
229
        notebook.append_page (vbox_exclude, lbl_exclude);
 
230
 
 
231
                //toolbar_exclude ---------------------------------------------------
 
232
 
 
233
        //toolbar_exclude
 
234
                toolbar_exclude = new Gtk.Toolbar ();
 
235
                toolbar_exclude.toolbar_style = ToolbarStyle.BOTH_HORIZ;
 
236
                //toolbar_exclude.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
 
237
                //toolbar.set_size_request(-1,48);
 
238
                vbox_exclude.add(toolbar_exclude);
 
239
 
 
240
                string png_exclude = App.share_folder + "/timeshift/images/item-gray.png";
 
241
                string png_include = App.share_folder + "/timeshift/images/item-blue.png";
 
242
 
 
243
                //btn_exclude
 
244
                btn_exclude = new Gtk.MenuToolButton(null,"");
 
245
                toolbar_exclude.add(btn_exclude);
 
246
 
 
247
                btn_exclude.is_important = true;
 
248
                btn_exclude.label = _("Exclude");
 
249
                btn_exclude.set_tooltip_text (_("Exclude"));
 
250
                btn_exclude.set_icon_widget(new Gtk.Image.from_file (png_exclude));
 
251
 
 
252
                //btn_include
 
253
                btn_include = new Gtk.MenuToolButton(null,"");
 
254
                toolbar_exclude.add(btn_include);
 
255
 
 
256
                btn_include.is_important = true;
 
257
                btn_include.label = _("Include");
 
258
                btn_include.set_tooltip_text (_("Include"));
 
259
                btn_include.set_icon_widget(new Gtk.Image.from_file (png_include));
 
260
 
 
261
                //btn_remove
 
262
                btn_remove = new Gtk.ToolButton.from_stock("gtk-remove");
 
263
                toolbar_exclude.add(btn_remove);
 
264
 
 
265
                btn_remove.is_important = true;
 
266
                btn_remove.label = _("Remove");
 
267
                btn_remove.set_tooltip_text (_("Remove selected items"));
 
268
 
 
269
                btn_remove.clicked.connect (btn_remove_clicked);
 
270
 
 
271
                //btn_warning
 
272
                btn_warning = new Gtk.ToolButton.from_stock("gtk-dialog-warning");
 
273
                toolbar_exclude.add(btn_warning);
 
274
 
 
275
                btn_warning.is_important = true;
 
276
                btn_warning.label = _("Warning");
 
277
                btn_warning.set_tooltip_text (_("Warning"));
 
278
 
 
279
                btn_warning.clicked.connect (btn_warning_clicked);
 
280
 
 
281
                //separator
 
282
                var separator = new Gtk.SeparatorToolItem();
 
283
                separator.set_draw (false);
 
284
                separator.set_expand (true);
 
285
                toolbar_exclude.add(separator);
 
286
 
 
287
                //btn_reset_exclude_list
 
288
                btn_reset_exclude_list = new Gtk.ToolButton.from_stock("gtk-refresh");
 
289
                toolbar_exclude.add(btn_reset_exclude_list);
 
290
 
 
291
                btn_reset_exclude_list.is_important = false;
 
292
                btn_reset_exclude_list.label = _("Reset");
 
293
                btn_reset_exclude_list.set_tooltip_text (_("Clear the list"));
 
294
 
 
295
                btn_reset_exclude_list.clicked.connect (btn_reset_exclude_list_clicked);
 
296
 
 
297
        //menu_exclude
 
298
                menu_exclude = new Gtk.Menu();
 
299
                btn_exclude.set_menu(menu_exclude);
 
300
 
 
301
                //menu_exclude_add_file
 
302
                menu_exclude_add_file = new ImageMenuItem.with_label ("");
 
303
                menu_exclude_add_file.label = _("Exclude File(s)");
 
304
                menu_exclude_add_file.set_image(new Gtk.Image.from_file (png_exclude));
 
305
                menu_exclude.append(menu_exclude_add_file);
 
306
 
 
307
                menu_exclude_add_file.activate.connect (menu_exclude_add_files_clicked);
 
308
 
 
309
                //menu_exclude_add_folder
 
310
                menu_exclude_add_folder = new ImageMenuItem.with_label ("");
 
311
                menu_exclude_add_folder.label = _("Exclude Directory");
 
312
                menu_exclude_add_folder.set_image(new Gtk.Image.from_file (png_exclude));
 
313
                menu_exclude.append(menu_exclude_add_folder);
 
314
 
 
315
                menu_exclude_add_folder.activate.connect (menu_exclude_add_folder_clicked);
 
316
 
 
317
                //menu_exclude_add_folder_contents
 
318
                menu_exclude_add_folder_contents = new ImageMenuItem.with_label ("");
 
319
                menu_exclude_add_folder_contents.label = _("Exclude Directory Contents");
 
320
                menu_exclude_add_folder_contents.set_image(new Gtk.Image.from_file (png_exclude));
 
321
                menu_exclude.append(menu_exclude_add_folder_contents);
 
322
 
 
323
                menu_exclude_add_folder_contents.activate.connect (menu_exclude_add_folder_contents_clicked);
 
324
 
 
325
                //menu_include
 
326
                menu_include = new Gtk.Menu();
 
327
                btn_include.set_menu(menu_include);
 
328
 
 
329
                //menu_include_add_file
 
330
                menu_include_add_file = new ImageMenuItem.with_label ("");
 
331
                menu_include_add_file.label = _("Include File(s)");
 
332
                menu_include_add_file.set_image(new Gtk.Image.from_file (png_include));
 
333
                menu_include.append(menu_include_add_file);
 
334
 
 
335
                menu_include_add_file.activate.connect (menu_include_add_files_clicked);
 
336
 
 
337
                //menu_include_add_folder
 
338
                menu_include_add_folder = new ImageMenuItem.with_label ("");
 
339
                menu_include_add_folder.label = _("Include Directory");
 
340
                menu_include_add_folder.set_image(new Gtk.Image.from_file (png_include));
 
341
                menu_include.append(menu_include_add_folder);
 
342
 
 
343
                menu_include_add_folder.activate.connect (menu_include_add_folder_clicked);
 
344
 
 
345
                menu_exclude.show_all();
 
346
                menu_include.show_all();
 
347
 
 
348
                //tv_exclude-----------------------------------------------
 
349
 
 
350
                //tv_exclude
 
351
                tv_exclude = new TreeView();
 
352
                tv_exclude.get_selection().mode = SelectionMode.MULTIPLE;
 
353
                tv_exclude.headers_visible = true;
 
354
                tv_exclude.set_rules_hint (true);
 
355
                //tv_exclude.row_activated.connect(tv_exclude_row_activated);
 
356
 
 
357
                //sw_exclude
 
358
                sw_exclude = new ScrolledWindow(null, null);
 
359
                sw_exclude.set_shadow_type (ShadowType.ETCHED_IN);
 
360
                sw_exclude.add (tv_exclude);
 
361
                sw_exclude.expand = true;
 
362
                vbox_exclude.add(sw_exclude);
 
363
 
 
364
        //col_exclude
 
365
                col_exclude = new TreeViewColumn();
 
366
                col_exclude.title = _("File Pattern");
 
367
                col_exclude.expand = true;
 
368
 
 
369
                CellRendererText cell_exclude_margin = new CellRendererText ();
 
370
                cell_exclude_margin.text = "";
 
371
                col_exclude.pack_start (cell_exclude_margin, false);
 
372
 
 
373
                CellRendererPixbuf cell_exclude_icon = new CellRendererPixbuf ();
 
374
                col_exclude.pack_start (cell_exclude_icon, false);
 
375
                col_exclude.set_attributes(cell_exclude_icon, "pixbuf", 1);
 
376
 
 
377
                CellRendererText cell_exclude_text = new CellRendererText ();
 
378
                col_exclude.pack_start (cell_exclude_text, false);
 
379
                col_exclude.set_cell_data_func (cell_exclude_text, cell_exclude_text_render);
 
380
                cell_exclude_text.editable = true;
 
381
                tv_exclude.append_column(col_exclude);
 
382
 
 
383
                cell_exclude_text.edited.connect (cell_exclude_text_edited);
 
384
 
 
385
                //lnk_default_list
 
386
                lnk_default_list = new LinkButton.with_label("",_("Some locations are excluded by default"));
 
387
                lnk_default_list.xalign = (float) 0.0;
 
388
                lnk_default_list.activate_link.connect(lnk_default_list_activate);
 
389
                vbox_exclude.add(lnk_default_list);
 
390
 
 
391
                //initialize ------------------
 
392
 
 
393
                temp_exclude_list = new Gee.ArrayList<string>();
 
394
 
 
395
                foreach(string path in App.exclude_list_user){
 
396
                        if (!temp_exclude_list.contains(path)){
 
397
                                temp_exclude_list.add(path);
 
398
                        }
 
399
                }
 
400
 
 
401
                refresh_tv_exclude();
 
402
                refresh_tv_schedule();
 
403
                refresh_tv_remove();
 
404
 
 
405
                // Actions ----------------------------------------------
 
406
 
 
407
                var vbox_action = get_action_area();
 
408
                vbox_action.margin = 12;
 
409
                vbox_action.margin_top = 0;
 
410
                
 
411
        //btn_save
 
412
        btn_save = (Button) add_button ("gtk-save", Gtk.ResponseType.ACCEPT);
 
413
        btn_save.clicked.connect (btn_save_clicked);
 
414
 
 
415
        //btn_cancel
 
416
        btn_cancel = (Button) add_button ("gtk-cancel", Gtk.ResponseType.CANCEL);
 
417
        btn_cancel.clicked.connect (btn_cancel_clicked);
 
418
        }
 
419
 
 
420
 
 
421
        private void cell_sched_enable_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
422
                bool val;
 
423
                model.get (iter, 0, out val, -1);
 
424
                (cell as Gtk.CellRendererToggle).active = val;
 
425
        }
 
426
 
 
427
        private void cell_sched_level_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
428
                string val;
 
429
                model.get (iter, 1, out val, -1);
 
430
                (cell as Gtk.CellRendererText).text = val;
 
431
        }
 
432
 
 
433
        private void cell_sched_desc_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
434
                string val;
 
435
                model.get (iter, 2, out val, -1);
 
436
                (cell as Gtk.CellRendererText).text = val;
 
437
        }
 
438
 
 
439
        private void cell_remove_rule_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
440
                string val;
 
441
                model.get (iter, 0, out val, -1);
 
442
                (cell as Gtk.CellRendererText).markup = val;
 
443
        }
 
444
 
 
445
        private void cell_remove_limit_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
446
                int val;
 
447
                string units;
 
448
                model.get (iter, 1, out val, 2, out units, -1);
 
449
                (cell as Gtk.CellRendererText).text = (units == "GB") ? "%.0f".printf(val/1024.0) : val.to_string();
 
450
                (cell as Gtk.CellRendererText).background = "#F2F5A9";
 
451
        }
 
452
 
 
453
        private void cell_remove_units_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
454
                string val;
 
455
                model.get (iter, 2, out val, -1);
 
456
                (cell as Gtk.CellRendererText).text = val;
 
457
        }
 
458
 
 
459
        private void cell_sched_enable_toggled (string path){
 
460
                TreeIter iter;
 
461
                var model = (Gtk.ListStore)tv_schedule.model;
 
462
                bool enabled;
 
463
                int count;
 
464
 
 
465
                model.get_iter_from_string (out iter, path);
 
466
                model.get (iter, 0, out enabled, 2, out count,-1);
 
467
                model.set (iter, 0, !enabled);
 
468
 
 
469
                //update switch_auto_backups
 
470
                bool atleast_one_enabled = false;
 
471
                for(int k = 0; k<5; k++){
 
472
                        model.get_iter_from_string (out iter, k.to_string());
 
473
                        model.get (iter, 0, out enabled, -1);
 
474
                        if (enabled){
 
475
                                atleast_one_enabled = true;
 
476
                                break;
 
477
                        }
 
478
                }
 
479
 
 
480
                chk_schedule.active = atleast_one_enabled;
 
481
        }
 
482
 
 
483
        private void cell_remove_limit_edited (string path, string new_text) {
 
484
                int count = 0;
 
485
                string units;
 
486
 
 
487
                TreeIter iter;
 
488
                var model = (Gtk.ListStore)tv_remove.model;
 
489
                model.get_iter_from_string (out iter, path);
 
490
                model.get (iter, 2, out units,-1);
 
491
                count = int.parse(new_text);
 
492
                if (units == "GB"){
 
493
                        count = count * 1024;
 
494
                }
 
495
                model.set (iter, 1, count);
 
496
        }
 
497
 
 
498
        private void cell_exclude_text_render (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter){
 
499
                string pattern;
 
500
                model.get (iter, 0, out pattern, -1);
 
501
                (cell as Gtk.CellRendererText).text = pattern.has_prefix("+ ") ? pattern[2:pattern.length] : pattern;
 
502
        }
 
503
 
 
504
        private void cell_exclude_text_edited (string path, string new_text) {
 
505
                string old_pattern;
 
506
                string new_pattern;
 
507
 
 
508
                TreeIter iter;
 
509
                var model = (Gtk.ListStore) tv_exclude.model;
 
510
                model.get_iter_from_string (out iter, path);
 
511
                model.get (iter, 0, out old_pattern, -1);
 
512
 
 
513
                if (old_pattern.has_prefix("+ ")){
 
514
                        new_pattern = "+ " + new_text;
 
515
                }
 
516
                else{
 
517
                        new_pattern = new_text;
 
518
                }
 
519
                model.set (iter, 0, new_pattern);
 
520
 
 
521
                int index = temp_exclude_list.index_of(old_pattern);
 
522
                temp_exclude_list.insert(index, new_pattern);
 
523
                temp_exclude_list.remove(old_pattern);
 
524
        }
 
525
 
 
526
        private void refresh_tv_schedule(){
 
527
 
 
528
                var model = new Gtk.ListStore(3, typeof(bool), typeof(string), typeof(string));
 
529
 
 
530
                TreeIter iter;
 
531
                model.append(out iter);
 
532
                model.set (iter, 0, App.schedule_monthly);
 
533
                model.set (iter, 1, _("Monthly"));
 
534
                model.set (iter, 2, _("Create one snapshot every month"));
 
535
 
 
536
                model.append(out iter);
 
537
                model.set (iter, 0, App.schedule_weekly);
 
538
                model.set (iter, 1, _("Weekly"));
 
539
                model.set (iter, 2, _("Create one snapshot every week"));
 
540
 
 
541
                model.append(out iter);
 
542
                model.set (iter, 0, App.schedule_daily);
 
543
                model.set (iter, 1, _("Daily"));
 
544
                model.set (iter, 2, _("Create one snapshot every day"));
 
545
 
 
546
                model.append(out iter);
 
547
                model.set (iter, 0, App.schedule_hourly);
 
548
                model.set (iter, 1, _("Hourly"));
 
549
                model.set (iter, 2, _("Create one snapshot every hour"));
 
550
 
 
551
                model.append(out iter);
 
552
                model.set (iter, 0, App.schedule_boot);
 
553
                model.set (iter, 1, _("Boot"));
 
554
                model.set (iter, 2, _("Create one snapshot every boot"));
 
555
 
 
556
                tv_schedule.set_model (model);
 
557
                tv_schedule.columns_autosize ();
 
558
        }
 
559
 
 
560
        private void refresh_tv_remove(){
 
561
 
 
562
                var model = new Gtk.ListStore(3, typeof(string), typeof(int), typeof(string));
 
563
 
 
564
                string span = "<span foreground=\"#2E2E2E\">";
 
565
                if (chk_schedule.active){
 
566
                        span = "<span foreground=\"blue\">";
 
567
                }
 
568
                else{
 
569
                        span = "<span>";
 
570
                }
 
571
 
 
572
                TreeIter iter;
 
573
                model.append(out iter);
 
574
                model.set (iter, 0, span + _("Monthly") + "</span> " + _("snapshots older than"));
 
575
                model.set (iter, 1, App.count_monthly);
 
576
                model.set (iter, 2, "months");
 
577
 
 
578
                model.append(out iter);
 
579
                model.set (iter, 0, span + _("Weekly") + "</span> " + _("snapshots older than"));
 
580
                model.set (iter, 1, App.count_weekly);
 
581
                model.set (iter, 2, "weeks");
 
582
 
 
583
                model.append(out iter);
 
584
                model.set (iter, 0, span + _("Daily") + "</span> " + _("snapshots older than"));
 
585
                model.set (iter, 1, App.count_daily);
 
586
                model.set (iter, 2, "days");
 
587
 
 
588
                model.append(out iter);
 
589
                model.set (iter, 0, span + _("Hourly") + "</span> " + _("snapshots older than"));
 
590
                model.set (iter, 1, App.count_hourly);
 
591
                model.set (iter, 2, "hours");
 
592
 
 
593
                model.append(out iter);
 
594
                model.set (iter, 0, span + _("Boot") + "</span> " + _("snapshots older than"));
 
595
                model.set (iter, 1, App.count_boot);
 
596
                model.set (iter, 2, "reboots");
 
597
 
 
598
                model.append(out iter);
 
599
                model.set (iter, 0, _("All snapshots older than"));
 
600
                model.set (iter, 1, App.retain_snapshots_max_days);
 
601
                model.set (iter, 2, "days");
 
602
 
 
603
                model.append(out iter);
 
604
                model.set (iter, 0, _("When free space less than"));
 
605
                model.set (iter, 1, ((int) (App.minimum_free_disk_space / GB)));
 
606
                model.set (iter, 2, "GB");
 
607
 
 
608
                tv_remove.set_model (model);
 
609
                //tv_remove.columns_autosize ();
 
610
        }
 
611
 
 
612
        private void refresh_tv_exclude(){
 
613
                var model = new Gtk.ListStore(2, typeof(string), typeof(Gdk.Pixbuf));
 
614
                tv_exclude.model = model;
 
615
 
 
616
                foreach(string path in temp_exclude_list){
 
617
                        tv_exclude_add_item(path);
 
618
                }
 
619
        }
 
620
 
 
621
        private void tv_exclude_add_item(string path){
 
622
                Gdk.Pixbuf pix_exclude = null;
 
623
                Gdk.Pixbuf pix_include = null;
 
624
                Gdk.Pixbuf pix_selected = null;
 
625
 
 
626
                try{
 
627
                        pix_exclude = new Gdk.Pixbuf.from_file (App.share_folder + "/timeshift/images/item-gray.png");
 
628
                        pix_include = new Gdk.Pixbuf.from_file (App.share_folder + "/timeshift/images/item-blue.png");
 
629
                }
 
630
        catch(Error e){
 
631
                log_error (e.message);
 
632
            }
 
633
 
 
634
                TreeIter iter;
 
635
                var model = (Gtk.ListStore) tv_exclude.model;
 
636
                model.append(out iter);
 
637
 
 
638
                if (path.has_prefix("+ ")){
 
639
                        pix_selected = pix_include;
 
640
                }
 
641
                else{
 
642
                        pix_selected = pix_exclude;
 
643
                }
 
644
 
 
645
                model.set (iter, 0, path, 1, pix_selected, -1);
 
646
 
 
647
                Adjustment adj = tv_exclude.get_hadjustment();
 
648
                adj.value = adj.upper;
 
649
        }
 
650
 
 
651
 
 
652
        private void chk_schedule_changed(){
 
653
                tv_schedule.sensitive = chk_schedule.active;
 
654
 
 
655
                if (chk_schedule.active){
 
656
 
 
657
                        bool atleast_one_enabled = App.schedule_boot
 
658
                        || App.schedule_hourly
 
659
                        || App.schedule_daily
 
660
                        || App.schedule_weekly
 
661
                        || App.schedule_monthly;
 
662
 
 
663
                        if(!atleast_one_enabled){
 
664
                                TreeIter iter;
 
665
                                var store = (Gtk.ListStore) tv_schedule.model;
 
666
                                bool enabled;
 
667
                                int index = -1;
 
668
 
 
669
                                bool iterExists = store.get_iter_first (out iter);
 
670
                                while (iterExists) {
 
671
                                        store.get (iter, 0, out enabled,-1);
 
672
                                        switch(++index){
 
673
                                                case 4:
 
674
                                                        store.set (iter, 0, true);
 
675
                                                        break;
 
676
                                        }
 
677
                                        iterExists = store.iter_next (ref iter);
 
678
                                }
 
679
                        }
 
680
                }
 
681
                else{
 
682
                        tv_schedule.get_selection().unselect_all();
 
683
                        tv_remove.get_selection().unselect_all();
 
684
                }
 
685
 
 
686
                refresh_tv_remove(); //refresh the item colors
 
687
        }
 
688
 
 
689
        private bool lnk_default_list_activate(){
 
690
                //show message window -----------------
 
691
                var dialog = new ExcludeMessageWindow();
 
692
                dialog.set_transient_for (this);
 
693
                dialog.show_all();
 
694
                dialog.run();
 
695
                dialog.destroy();
 
696
                return true;
 
697
        }
 
698
 
 
699
 
 
700
        private void menu_exclude_add_files_clicked(){
 
701
 
 
702
                var list = browse_files();
 
703
 
 
704
                if (list.length() > 0){
 
705
                        foreach(string path in list){
 
706
                                if (!temp_exclude_list.contains(path)){
 
707
                                        temp_exclude_list.add(path);
 
708
                                        tv_exclude_add_item(path);
 
709
                                        App.first_snapshot_size = 0; //re-calculate
 
710
                                }
 
711
                        }
 
712
                }
 
713
        }
 
714
 
 
715
        private void menu_exclude_add_folder_clicked(){
 
716
 
 
717
                var list = browse_folder();
 
718
 
 
719
                if (list.length() > 0){
 
720
                        foreach(string path in list){
 
721
 
 
722
                                path = path + "/";
 
723
 
 
724
                                if (!temp_exclude_list.contains(path)){
 
725
                                        temp_exclude_list.add(path);
 
726
                                        tv_exclude_add_item(path);
 
727
                                        App.first_snapshot_size = 0; //re-calculate
 
728
                                }
 
729
                        }
 
730
                }
 
731
        }
 
732
 
 
733
        private void menu_exclude_add_folder_contents_clicked(){
 
734
 
 
735
                var list = browse_folder();
 
736
 
 
737
                if (list.length() > 0){
 
738
                        foreach(string path in list){
 
739
 
 
740
                                path = path + "/*";
 
741
 
 
742
                                if (!temp_exclude_list.contains(path)){
 
743
                                        temp_exclude_list.add(path);
 
744
                                        tv_exclude_add_item(path);
 
745
                                        App.first_snapshot_size = 0; //re-calculate
 
746
                                }
 
747
                        }
 
748
                }
 
749
        }
 
750
 
 
751
        private void menu_include_add_files_clicked(){
 
752
 
 
753
                var list = browse_files();
 
754
 
 
755
                if (list.length() > 0){
 
756
                        foreach(string path in list){
 
757
 
 
758
                                path = path.has_prefix("+ ") ? path : "+ " + path;
 
759
 
 
760
                                if (!temp_exclude_list.contains(path)){
 
761
                                        temp_exclude_list.add(path);
 
762
                                        tv_exclude_add_item(path);
 
763
                                        App.first_snapshot_size = 0; //re-calculate
 
764
                                }
 
765
                        }
 
766
                }
 
767
        }
 
768
 
 
769
        private void menu_include_add_folder_clicked(){
 
770
 
 
771
                var list = browse_folder();
 
772
 
 
773
                if (list.length() > 0){
 
774
                        foreach(string path in list){
 
775
 
 
776
                                path = path.has_prefix("+ ") ? path : "+ " + path;
 
777
                                path = path + "/***";
 
778
 
 
779
                                if (!temp_exclude_list.contains(path)){
 
780
                                        temp_exclude_list.add(path);
 
781
                                        tv_exclude_add_item(path);
 
782
                                        App.first_snapshot_size = 0; //re-calculate
 
783
                                }
 
784
                        }
 
785
                }
 
786
        }
 
787
 
 
788
        private SList<string> browse_files(){
 
789
                var dialog = new Gtk.FileChooserDialog(_("Select file(s)"), this, Gtk.FileChooserAction.OPEN,
 
790
                                                        "gtk-cancel", Gtk.ResponseType.CANCEL,
 
791
                                                        "gtk-open", Gtk.ResponseType.ACCEPT);
 
792
                dialog.action = FileChooserAction.OPEN;
 
793
                dialog.set_transient_for(this);
 
794
                dialog.local_only = true;
 
795
                dialog.set_modal (true);
 
796
                dialog.set_select_multiple (true);
 
797
 
 
798
                dialog.run();
 
799
                var list = dialog.get_filenames();
 
800
                dialog.destroy ();
 
801
 
 
802
                return list;
 
803
        }
 
804
 
 
805
        private SList<string> browse_folder(){
 
806
                var dialog = new Gtk.FileChooserDialog(_("Select directory"), this, Gtk.FileChooserAction.OPEN,
 
807
                                                        "gtk-cancel", Gtk.ResponseType.CANCEL,
 
808
                                                        "gtk-open", Gtk.ResponseType.ACCEPT);
 
809
                dialog.action = FileChooserAction.SELECT_FOLDER;
 
810
                dialog.local_only = true;
 
811
                dialog.set_transient_for(this);
 
812
                dialog.set_modal (true);
 
813
                dialog.set_select_multiple (false);
 
814
 
 
815
                dialog.run();
 
816
                var list = dialog.get_filenames();
 
817
                dialog.destroy ();
 
818
 
 
819
                return list;
 
820
        }
 
821
 
 
822
 
 
823
        private void btn_remove_clicked(){
 
824
                TreeSelection sel = tv_exclude.get_selection ();
 
825
                TreeIter iter;
 
826
                bool iterExists = tv_exclude.model.get_iter_first (out iter);
 
827
                while (iterExists) {
 
828
                        if (sel.iter_is_selected (iter)){
 
829
                                string path;
 
830
                                tv_exclude.model.get (iter, 0, out path);
 
831
                                temp_exclude_list.remove(path);
 
832
                                App.first_snapshot_size = 0; //re-calculate
 
833
                        }
 
834
                        iterExists = tv_exclude.model.iter_next (ref iter);
 
835
                }
 
836
 
 
837
                refresh_tv_exclude();
 
838
        }
 
839
 
 
840
        private void btn_warning_clicked(){
 
841
                string msg = "";
 
842
                msg += _("Documents, music and other folders in your home directory are excluded by default.") + " ";
 
843
                msg += _("Please do NOT include these folders in your snapshot unless you have a very good reason for doing so.") + " ";
 
844
                msg += _("If you include any specific folders then these folders will get overwritten with previous contents when you restore a snapshot.");
 
845
 
 
846
                var dialog = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, msg);
 
847
                dialog.set_title("Warning");
 
848
                dialog.set_default_size (200, -1);
 
849
                dialog.set_transient_for(this);
 
850
                dialog.set_modal(true);
 
851
                dialog.run();
 
852
                dialog.destroy();
 
853
        }
 
854
 
 
855
        private void btn_reset_exclude_list_clicked(){
 
856
                //create a temp exclude list ----------------------------
 
857
 
 
858
                temp_exclude_list = new Gee.ArrayList<string>();
 
859
 
 
860
                //refresh treeview --------------------------
 
861
 
 
862
                refresh_tv_exclude();
 
863
        }
 
864
 
 
865
 
 
866
        private void btn_save_clicked(){
 
867
                tv_schedule_save_changes();
 
868
                tv_remove_save_changes();
 
869
                tv_exclude_save_changes();
 
870
 
 
871
                App.save_app_config();
 
872
                App.cron_job_update();
 
873
 
 
874
                this.destroy();
 
875
        }
 
876
 
 
877
        private void tv_schedule_save_changes(){
 
878
                TreeIter iter;
 
879
                TreeModel store = tv_schedule.model;
 
880
                bool enabled;
 
881
                int index = -1;
 
882
 
 
883
                bool iterExists = store.get_iter_first (out iter);
 
884
 
 
885
                while (iterExists) {
 
886
 
 
887
                        store.get (iter, 0, out enabled,-1);
 
888
 
 
889
                        switch(++index){
 
890
                                case 0:
 
891
                                        App.schedule_monthly = enabled;
 
892
                                        break;
 
893
                                case 1:
 
894
                                        App.schedule_weekly = enabled;
 
895
                                        break;
 
896
                                case 2:
 
897
                                        App.schedule_daily = enabled;
 
898
                                        break;
 
899
                                case 3:
 
900
                                        App.schedule_hourly = enabled;
 
901
                                        break;
 
902
                                case 4:
 
903
                                        App.schedule_boot = enabled;
 
904
                                        break;
 
905
                        }
 
906
                        iterExists = store.iter_next (ref iter);
 
907
                }
 
908
 
 
909
                if (!App.live_system()){
 
910
                        App.is_scheduled = chk_schedule.active;
 
911
                }
 
912
        }
 
913
 
 
914
        private void tv_remove_save_changes(){
 
915
                TreeIter iter;
 
916
                TreeModel store = tv_remove.model;
 
917
                int count = -1;
 
918
                int index = -1;
 
919
 
 
920
                bool iterExists = store.get_iter_first (out iter);
 
921
 
 
922
                while (iterExists) {
 
923
 
 
924
                        store.get (iter, 1, out count, -1);
 
925
 
 
926
                        switch(++index){
 
927
                                case 0:
 
928
                                        App.count_monthly = count;
 
929
                                        break;
 
930
                                case 1:
 
931
                                        App.count_weekly = count;
 
932
                                        break;
 
933
                                case 2:
 
934
                                        App.count_daily = count;
 
935
                                        break;
 
936
                                case 3:
 
937
                                        App.count_hourly = count;
 
938
                                        break;
 
939
                                case 4:
 
940
                                        App.count_boot = count;
 
941
                                        break;
 
942
                                case 5:
 
943
                                        App.retain_snapshots_max_days = count;
 
944
                                        break;
 
945
                                case 6:
 
946
                                        App.minimum_free_disk_space = count * 1000;
 
947
                                        break;
 
948
                        }
 
949
                        iterExists = store.iter_next (ref iter);
 
950
                }
 
951
        }
 
952
 
 
953
        private void tv_exclude_save_changes(){
 
954
                App.exclude_list_user.clear();
 
955
                foreach(string path in temp_exclude_list){
 
956
                        if (!App.exclude_list_user.contains(path) && !App.exclude_list_default.contains(path) && !App.exclude_list_home.contains(path)){
 
957
                                App.exclude_list_user.add(path);
 
958
                        }
 
959
                }
 
960
        }
 
961
 
 
962
        private void btn_cancel_clicked(){
 
963
                this.destroy();
 
964
        }
 
965
 
 
966
}