~ubuntu-branches/ubuntu/saucy/activity-log-manager/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/05_fix_userdirs.patch/src/files-widget.vala

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher, Margarita Manterola
  • Date: 2012-11-26 15:45:31 UTC
  • Revision ID: package-import@ubuntu.com-20121126154531-j5av6vafrl5i2l1l
Tags: 0.9.4-0ubuntu6.1
* debian/patches/06_add_unity_dash_privacy.patch:
  - drop trailing period from the online result label (lp: #1061930)

[ Margarita Manterola ]
* 05_fix_userdirs.patch:
  - Verify that a user directory exists before adding it to the hash map.
    (LP: #1024057)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: vala; tab-width: 4; intend-tabs-mode: t -*- */
 
2
/* alm
 
3
 *
 
4
 * Copyright (C) 2012 Seif Lotfy <seif@lotfy.com>
 
5
 * Copyright (C) 2012 Manish Sinha <manishsinha@ubuntu.com>
 
6
 * Copyright (C) 2012 Intel Corp.
 
7
 *               Authored by: Seif Lotfy <seif.lotfy@collabora.co.uk>
 
8
 * Copyright (C) 2012 Stefano Candori <stefano.candori@gmail.com>
 
9
 *
 
10
 * alm is free software: you can redistribute it and/or modify it
 
11
 * under the terms of the GNU Lesser General Public License as published
 
12
 * by the Free Software Foundation, either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * alm is distributed in the hope that it will be useful, but
 
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
18
 * See the GNU Lesser General Public License for more details.
 
19
 * 
 
20
 * You should have received a copy of the GNU Lesser General Public License
 
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 
22
 */
 
23
 
 
24
using Gtk;
 
25
using Gee;
 
26
using Zeitgeist;
 
27
 
 
28
namespace Alm {
 
29
 
 
30
        public class FileTypeBlacklist {
 
31
                private Blacklist blacklist_interface;
 
32
                private HashMap<string, CheckButton> checkboxes;
 
33
 
 
34
                public static string interpretation_prefix = "interpretation-";
 
35
                
 
36
                public FileTypeBlacklist (Blacklist blacklist_inter,
 
37
                                        HashMap<string, CheckButton> all_checkboxes) {
 
38
                        blacklist_interface = blacklist_inter;
 
39
                        checkboxes = all_checkboxes;
 
40
                }
 
41
 
 
42
                private string get_name(string interpretation) {
 
43
                        var names = interpretation.split("#");
 
44
                        var name = names[names.length-1].down();
 
45
                        return "%s%s".printf(interpretation_prefix, name);
 
46
                }
 
47
 
 
48
                public void populate_file_types() {
 
49
 
 
50
                        foreach(string key in blacklist_interface.all_templates.get_keys()) {
 
51
                                if(key.has_prefix(this.interpretation_prefix))
 
52
                                {
 
53
                                        var inter = blacklist_interface.all_templates[key].get_subject(0).get_interpretation ();
 
54
                                        if(checkboxes.has_key(inter))
 
55
                                                checkboxes.get(inter).active = true;
 
56
                                }
 
57
                        }
 
58
                }
 
59
 
 
60
                public void block(string interpretation) {
 
61
                        Event ev = new Event();
 
62
                        Subject sub = new Subject();
 
63
                        sub.set_interpretation(interpretation);
 
64
                        ev.add_subject(sub);
 
65
 
 
66
                        blacklist_interface.add_template(
 
67
                                        this.get_name(interpretation), ev);
 
68
                }
 
69
 
 
70
                public void unblock(string interpretation) {
 
71
                        blacklist_interface.remove_template(
 
72
                                        this.get_name(interpretation));
 
73
                }
 
74
        }
 
75
 
 
76
        public class PathBlacklist {
 
77
                private Blacklist blacklist_interface;
 
78
 
 
79
                public static string folder_prefix = "dir-";
 
80
                private static string suffix = "/*";
 
81
 
 
82
                private HashSet<string> all_blocked_folder;
 
83
 
 
84
                public signal void folder_added(string path);
 
85
 
 
86
                public signal void folder_removed(string path);
 
87
                
 
88
                public PathBlacklist (Blacklist blacklist_inter) {
 
89
                        blacklist_interface = blacklist_inter;
 
90
                        this.blacklist_interface.template_added.connect(on_blacklist_added);
 
91
                        this.blacklist_interface.template_removed.connect(on_blacklist_removed);
 
92
 
 
93
                        this.get_blocked_folder ();
 
94
                }
 
95
 
 
96
                public HashSet<string> all_folders {
 
97
                        get {
 
98
                                return all_blocked_folder;
 
99
                        }
 
100
                }
 
101
 
 
102
                public bool is_duplicate (string path) {
 
103
                        return all_blocked_folder.contains (path);
 
104
                }
 
105
 
 
106
                private void get_blocked_folder () {
 
107
                        all_blocked_folder = new HashSet<string>();
 
108
 
 
109
                        foreach(string key in blacklist_interface.all_templates.get_keys()) {
 
110
                                if(key.has_prefix(folder_prefix))
 
111
                                {
 
112
                                        string folder = get_folder(blacklist_interface.all_templates.get(key));
 
113
                                        if(folder != null)
 
114
                                                all_blocked_folder.add(folder);
 
115
                                }
 
116
                        }
 
117
                }
 
118
 
 
119
                private void on_blacklist_added (string blacklist_id, Event ev) {
 
120
                        if(blacklist_id.has_prefix(folder_prefix))
 
121
                        {
 
122
                                string uri = get_folder(ev);
 
123
                                if(uri != null)
 
124
                                {
 
125
                                        folder_added(uri);
 
126
                                        if(!all_blocked_folder.contains(uri))
 
127
                                                all_blocked_folder.add(uri);
 
128
                                }
 
129
                        }
 
130
                }
 
131
 
 
132
                private void on_blacklist_removed (string blacklist_id, Event ev) {
 
133
                        if(blacklist_id.has_prefix(folder_prefix))
 
134
                        {
 
135
                                string uri = get_folder(ev);
 
136
                                if(uri != null)
 
137
                                {
 
138
                                        folder_removed(uri);
 
139
                                        if(all_blocked_folder.contains(uri))
 
140
                                                all_blocked_folder.remove(uri);
 
141
                                }
 
142
                        }
 
143
                }
 
144
 
 
145
                private string get_folder(Event ev) {
 
146
                        Subject sub = ev.get_subject(0);
 
147
                        string uri = sub.get_uri ();
 
148
                        uri = uri.replace(suffix, "");
 
149
                        File blocked_uri = File.new_for_uri(uri);
 
150
                        
 
151
                        string final_path = blocked_uri.query_exists(null)? blocked_uri.get_path(): null;
 
152
 
 
153
                        return final_path;
 
154
                }
 
155
 
 
156
                public void block(string folder) {
 
157
                        Event ev = new Event ();
 
158
                        Subject sub = new Subject ();
 
159
                        
 
160
                        File block_path = File.new_for_path(folder);
 
161
                        string uri = "%s%s".printf(block_path.get_uri(), suffix);
 
162
                        sub.set_uri(uri);
 
163
                        ev.add_subject(sub);
 
164
 
 
165
                        blacklist_interface.add_template(
 
166
                                        "%s%s".printf(folder_prefix, folder), ev);
 
167
 
 
168
                        if(!all_blocked_folder.contains(folder))
 
169
                                        all_blocked_folder.add(folder);
 
170
                }
 
171
 
 
172
                public void unblock(string folder) {
 
173
                        blacklist_interface.remove_template(
 
174
                                        "%s%s".printf(folder_prefix, folder));
 
175
 
 
176
                        if(all_blocked_folder.contains(folder))
 
177
                                        all_blocked_folder.remove(folder);
 
178
                }
 
179
        }
 
180
 
 
181
 
 
182
        public class FilesWidget : Gtk.Box {
 
183
 
 
184
                private FileTypeBlacklist files_type_blacklist;
 
185
                private PathBlacklist path_blacklist;
 
186
                private TreeView folder_list;
 
187
                private ListStore folder_list_store;
 
188
 
 
189
                private HashMap<string, string> mime_dict;
 
190
                private HashMap<string, CheckButton> checkboxes;
 
191
                private HashSet<CheckButton> button_list;
 
192
 
 
193
                private HashMap<string, UserDirectory> defined_dirs;
 
194
 
 
195
                private Blacklist blacklist;
 
196
                private bool file_type_fire_signal = true;
 
197
 
 
198
                private IconTheme icon_theme;
 
199
                private Gdk.Pixbuf? stock_folder_icon;
 
200
 
 
201
                enum TreeViewCols
 
202
                {
 
203
                        APP_NAME,
 
204
                        ICON,
 
205
                        DESKTOP_FILE,
 
206
                        N_COLS
 
207
                }
 
208
 
 
209
                public FilesWidget (Blacklist blacklist_interface) {
 
210
                        Object (orientation: Orientation.VERTICAL);
 
211
 
 
212
                        this.blacklist = blacklist_interface;
 
213
                        this.checkboxes = new HashMap<string, CheckButton>();
 
214
                        this.button_list = new HashSet<CheckButton>();
 
215
                        this.icon_theme = new IconTheme();
 
216
 
 
217
                        this.files_type_blacklist = new FileTypeBlacklist(blacklist_interface, 
 
218
                                                                                                this.checkboxes);
 
219
                        this.path_blacklist = new PathBlacklist(blacklist_interface);
 
220
 
 
221
                        blacklist_interface.template_added.connect(
 
222
                                (blacklist_id, blacklist_template) => {
 
223
                                        if(blacklist_id.has_prefix(FileTypeBlacklist.interpretation_prefix))
 
224
                                        {
 
225
                                                file_type_fire_signal = false;
 
226
                                                var inter = blacklist_template.get_subject(0).get_interpretation ();
 
227
                                                if(checkboxes.has_key(inter))
 
228
                                                        checkboxes.get(inter).active = true;
 
229
                                                file_type_fire_signal = true;
 
230
                                        }
 
231
                                });
 
232
                        blacklist_interface.template_removed.connect(
 
233
                                (blacklist_id, blacklist_template) => {
 
234
                                        if(blacklist_id.has_prefix(FileTypeBlacklist.interpretation_prefix))
 
235
                                        {
 
236
                                                file_type_fire_signal = false;
 
237
                                                var inter = blacklist_template.get_subject(0).get_interpretation ();
 
238
                                                if(checkboxes.has_key(inter))
 
239
                                                        checkboxes.get(inter).active = false;
 
240
                                                file_type_fire_signal = true;
 
241
                                        }
 
242
                                });
 
243
 
 
244
                        this.path_blacklist.folder_added.connect((folder) => {
 
245
                                if(!this.path_blacklist.is_duplicate(folder))
 
246
                                        add_folder_to_view(folder);
 
247
                        });
 
248
 
 
249
                        this.path_blacklist.folder_removed.connect((folder) => {
 
250
                                remove_folder_from_view(folder);
 
251
                        });
 
252
 
 
253
                        mime_dict = new HashMap<string, string>(str_hash, str_equal);
 
254
                        mime_dict.set(_("Audio"), NFO_AUDIO);
 
255
                mime_dict.set(_("Video"), NFO_VIDEO);
 
256
                mime_dict.set(_("Image"), NFO_IMAGE);
 
257
                mime_dict.set(_("Text"), NFO_DOCUMENT);
 
258
                mime_dict.set(_("Presentation"), NFO_PRESENTATION);
 
259
                mime_dict.set(_("Spreadsheet"), NFO_SPREADSHEET);
 
260
                mime_dict.set(_("Instant Messaging"), NMO_IMMESSAGE);
 
261
                mime_dict.set(_("E-mail"), NMO_EMAIL);
 
262
                mime_dict.set(_("Website"), NFO_WEBSITE);
 
263
 
 
264
                        defined_dirs = new HashMap<string, UserDirectory>(str_hash, str_equal);
 
265
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.DESKTOP), UserDirectory.DESKTOP);
 
266
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.DOCUMENTS), UserDirectory.DOCUMENTS);
 
267
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.DOWNLOAD), UserDirectory.DOWNLOAD);
 
268
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.MUSIC), UserDirectory.MUSIC);
 
269
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.PICTURES), UserDirectory.PICTURES);
 
270
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.PUBLIC_SHARE), UserDirectory.PUBLIC_SHARE);
 
271
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.TEMPLATES), UserDirectory.TEMPLATES);
 
272
                        defined_dirs.set(Environment.get_user_special_dir(UserDirectory.VIDEOS), UserDirectory.VIDEOS);
 
273
                
 
274
                        //FIXME: Not sure if the correct icon is being fetched for stock folder
 
275
                        stock_folder_icon = this.render_icon_pixbuf(Stock.DIRECTORY, IconSize.LARGE_TOOLBAR);
 
276
 
 
277
                        this.setup_ui();
 
278
                }
 
279
 
 
280
                private void setup_ui() {
 
281
 
 
282
                        this.set_border_width(12);
 
283
 
 
284
                        var vbox_file_types = new Box(Orientation.VERTICAL, 6);
 
285
                        this.pack_start(vbox_file_types, false, false);
 
286
 
 
287
                        // Label for Checkbox list
 
288
                        var file_type_label = new Label(null);
 
289
                        file_type_label.set_markup("<b>%s</b>".printf(_("Don't record activity for following type of files:")));
 
290
                        file_type_label.set_alignment(0.0f, 0.5f);
 
291
                        vbox_file_types.pack_start(file_type_label, false);
 
292
 
 
293
                        // Checkbox Table
 
294
                        var checkbox_table = new Table(3, 3, true);
 
295
 
 
296
                        string[] keys = mime_dict.keys.to_array();
 
297
                        for(int i=0,row=0,col=0; i < keys.length; i++, col++) {
 
298
                        //foreach (var entry in mime_dict.entries) {
 
299
                        var check_button = new CheckButton.with_label (keys[i]);
 
300
                                
 
301
                                this.button_list.add(check_button);
 
302
                                this.checkboxes.set(mime_dict[keys[i]], check_button);
 
303
 
 
304
                                if(col > 2) {
 
305
                                        row++;
 
306
                                        col = col % 3;
 
307
                                }
 
308
 
 
309
                                checkbox_table.attach_defaults(check_button, col, col+1, row, row+1);
 
310
                }
 
311
                
 
312
                        vbox_file_types.pack_start(checkbox_table, false);
 
313
 
 
314
                        this.files_type_blacklist.populate_file_types();
 
315
 
 
316
                        foreach(CheckButton check_button in this.button_list)
 
317
                        {
 
318
                                check_button.toggled.connect(() => {
 
319
                                        if(file_type_fire_signal)
 
320
                                        {
 
321
                                                file_type_fire_signal = false;
 
322
                                                if(check_button.active)
 
323
                                                        files_type_blacklist.block(mime_dict[check_button.label]);
 
324
                                                else
 
325
                                                        files_type_blacklist.unblock(mime_dict[check_button.label]);
 
326
                                                file_type_fire_signal = true;
 
327
                                        }
 
328
                        });
 
329
                        }
 
330
 
 
331
                        // Horizontal Line
 
332
                        var hoz_line = new HSeparator();
 
333
                        this.pack_start(hoz_line, false, false, 12);
 
334
 
 
335
                        // Folders
 
336
                        var vbox_folders = new Box(Orientation.VERTICAL, 6);
 
337
                        this.pack_start(vbox_folders, true, true);
 
338
 
 
339
                        // Label for Folder list list
 
340
                        var folders_label = new Label(null);
 
341
                        folders_label.set_markup("<b>%s</b>".printf(_("Don't record activity in the following folders:")));
 
342
                        folders_label.set_alignment(0.0f, 0.5f);
 
343
                        vbox_folders.pack_start(folders_label, false);
 
344
 
 
345
                        var file_chooser_vbox = new Box(Orientation.VERTICAL, 0);
 
346
                        vbox_folders.pack_start(file_chooser_vbox, true, true);
 
347
 
 
348
                        // Folder list TreeView
 
349
                        this.folder_list_store = new ListStore (3, typeof(string), typeof(Gdk.Pixbuf?), typeof(string));
 
350
                        this.folder_list = new TreeView.with_model (this.folder_list_store);
 
351
                        this.folder_list.set_headers_visible (false);
 
352
                        this.folder_list.set_rules_hint (true);
 
353
 
 
354
                        var column_pix_name = new TreeViewColumn ();
 
355
                        column_pix_name.set_title (_("Name"));
 
356
                        this.folder_list.append_column (column_pix_name);
 
357
                        
 
358
                        var pix_rend = new FilesCellRenderer ();
 
359
                        column_pix_name.pack_start (pix_rend, false);
 
360
                        column_pix_name.add_attribute (pix_rend, "pixbuf", 1);
 
361
                        column_pix_name.add_attribute (pix_rend, "text", 2);
 
362
                        column_pix_name.add_attribute (pix_rend, "path", 0);
 
363
                        
 
364
                        var scroll = new ScrolledWindow(null, null);
 
365
                        scroll.add(this.folder_list);
 
366
                        scroll.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);
 
367
                        scroll.set_shadow_type (ShadowType.IN);
 
368
                        scroll.set_border_width (1);
 
369
                        file_chooser_vbox.pack_start(scroll, true, true);
 
370
 
 
371
                        // Add Remove buttons
 
372
                        var folder_toolbar = new Toolbar();
 
373
                        folder_toolbar.toolbar_style = ToolbarStyle.ICONS;
 
374
                        folder_toolbar.icon_size = 1;
 
375
                        folder_toolbar.icon_size_set = true;
 
376
                        folder_toolbar.visible = true;
 
377
                        
 
378
                        scroll.get_style_context().set_junction_sides(Gtk.JunctionSides.BOTTOM);
 
379
                        folder_toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
 
380
                    folder_toolbar.get_style_context().set_junction_sides(Gtk.JunctionSides.TOP);
 
381
 
 
382
                        var folder_add = new ToolButton(null, _("Add Folder"));
 
383
                        folder_add.set_icon_name("list-add-symbolic");
 
384
                        folder_add.clicked.connect(on_add_folder);
 
385
 
 
386
                        var folder_remove = new ToolButton(null, _("Remove Folder"));
 
387
                        folder_remove.set_icon_name("list-remove-symbolic");
 
388
                        folder_remove.clicked.connect(on_remove_folder);
 
389
 
 
390
                        folder_toolbar.insert(folder_add, 0);
 
391
                        folder_toolbar.insert(folder_remove, 1);
 
392
 
 
393
                        file_chooser_vbox.pack_start(folder_toolbar, false, false);
 
394
                        this.folders_populate ();
 
395
                }
 
396
 
 
397
                private void folders_populate () {
 
398
                        foreach(string folder in path_blacklist.all_folders)
 
399
                        {
 
400
                                add_folder_to_view(folder);
 
401
                        }
 
402
                }
 
403
 
 
404
                private void on_add_folder() {
 
405
                        var chooser = new FileChooserDialog(
 
406
                                _("Select a directory to blacklist"), 
 
407
                                null, FileChooserAction.SELECT_FOLDER);
 
408
                        chooser.add_buttons (Stock.OK, ResponseType.OK, Stock.CANCEL, ResponseType.CANCEL);
 
409
                        int res = chooser.run();
 
410
                        chooser.hide();
 
411
                        if(res == ResponseType.OK)
 
412
                        {
 
413
                                string folder = chooser.get_filename ();
 
414
                                if(!this.path_blacklist.is_duplicate(folder))
 
415
                                {
 
416
                                        add_folder_to_view(folder);
 
417
                                        this.path_blacklist.block(folder);
 
418
                                }
 
419
                        }
 
420
                }
 
421
 
 
422
                private void on_remove_folder () {
 
423
                        TreeSelection sel = this.folder_list.get_selection ();
 
424
                        if(sel != null)
 
425
                        {
 
426
                                TreeModel model;
 
427
                                TreeIter iter;
 
428
                                if(sel.get_selected(out model, out iter))
 
429
                                {
 
430
                                        string folder;
 
431
                                        model.get(iter, 0, out folder);
 
432
                                        if(folder != null)
 
433
                                        {
 
434
                                                folder_list_store.remove(iter);
 
435
                                                this.path_blacklist.unblock(folder);
 
436
                                        }
 
437
                                }
 
438
                        }
 
439
                }
 
440
 
 
441
                private void add_folder_to_view (string folder) {
 
442
 
 
443
                        Gdk.Pixbuf? icon = stock_folder_icon;
 
444
                        ThemedIcon? nautilus_icon = null;
 
445
                        if(defined_dirs.has_key(folder))
 
446
                        {
 
447
                                UserDirectory dir = defined_dirs.get(folder);
 
448
                                if (dir.to_string() == "G_USER_DIRECTORY_DOCUMENTS")
 
449
                                        nautilus_icon = new ThemedIcon("folder-documents");
 
450
                                else if (dir.to_string() == "G_USER_DIRECTORY_DOWNLOAD")
 
451
                                        nautilus_icon = new ThemedIcon("folder-download");
 
452
                                else if (dir.to_string() == "G_USER_DIRECTORY_MUSIC")
 
453
                                        nautilus_icon = new ThemedIcon("folder-music");
 
454
                                else if (dir.to_string() == "G_USER_DIRECTORY_DESKTOP")
 
455
                                        nautilus_icon = new ThemedIcon("user-desktop");
 
456
                                else if (dir.to_string() == "G_USER_DIRECTORY_PICTURES")
 
457
                                        nautilus_icon = new ThemedIcon("folder-pictures");
 
458
                                else if (dir.to_string() == "G_USER_DIRECTORY_VIDEOS")
 
459
                                        nautilus_icon = new ThemedIcon("folder-videos");
 
460
                                else if (dir.to_string() == "G_USER_DIRECTORY_TEMPLATES")
 
461
                                        nautilus_icon = new ThemedIcon("folder-templates");
 
462
                                else if (dir.to_string() == "G_USER_DIRECTORY_PUBLIC_SHARE")
 
463
                                        nautilus_icon = new ThemedIcon("folder-publicshare");
 
464
                                if(nautilus_icon != null) {
 
465
                                        var pixbuf = ApplicationsTreeView.get_pixbuf_from_gio_icon(nautilus_icon, 24);
 
466
                                        if (pixbuf != null)
 
467
                                                icon = pixbuf;
 
468
                                }
 
469
                        }
 
470
                        
 
471
                        string name = Path.get_basename(folder.strip());
 
472
                        TreeIter iter;
 
473
                        this.folder_list_store.append(out iter);
 
474
                        // First element is full path, second is icon and third is just the path basename
 
475
                        this.folder_list_store.set(iter, 0, folder, 1, icon, 2, name, -1);
 
476
                }
 
477
 
 
478
                private bool remove_folder_from_view (string folder) {
 
479
                        var model = this.folder_list.get_model ();
 
480
                        TreeIter iter;
 
481
                        model.get_iter_first (out iter);
 
482
                        while (true)
 
483
                        {
 
484
                                Value can_app_value;
 
485
                                model.get_value(iter, 0, out can_app_value);
 
486
                                string cand_folder = can_app_value.get_string();
 
487
                                if(folder == cand_folder)
 
488
                                {
 
489
                                        this.folder_list_store.remove(iter);
 
490
                                        return true;
 
491
                                }
 
492
                                bool more_entires = model.iter_next(ref iter);
 
493
                                if(!more_entires)
 
494
                                {
 
495
                                        return false;
 
496
                                }
 
497
                        }
 
498
                }
 
499
        }
 
500
 
 
501
//Based on gnome-contacts contacts-cell-renderer-shape.vala
 
502
public class FilesCellRenderer : CellRenderer {
 
503
 
 
504
        private const int PIXBUF_SIZE = 24;
 
505
        private const int xspacing = 3; 
 
506
        
 
507
        private const int default_width = 60;
 
508
        private const int renderer_height = 50;
 
509
        
 
510
        private Widget current_widget;
 
511
        
 
512
        private Gdk.Pixbuf pixbuf_;
 
513
        private string text_;
 
514
        private string path_;
 
515
        
 
516
        public Gdk.Pixbuf pixbuf {
 
517
                        get {
 
518
                                return pixbuf_;
 
519
                        }
 
520
                        set {
 
521
                                pixbuf_ = value;
 
522
                        }
 
523
        }
 
524
        
 
525
        public string text {
 
526
                        get {
 
527
                                return text_;
 
528
                        }
 
529
                        set {
 
530
                                text_ = value;
 
531
                        }
 
532
        }
 
533
        
 
534
        public string path {
 
535
                        get {
 
536
                                return path_;
 
537
                        }
 
538
                        set {
 
539
                                path_ = value;
 
540
                        }
 
541
        }
 
542
        
 
543
        public FilesCellRenderer () {
 
544
                GLib.Object ();
 
545
        }
 
546
        
 
547
        private Pango.Layout get_text_layout (Widget widget,
 
548
                                        Gdk.Rectangle? cell_area,
 
549
                                        CellRendererState flags,
 
550
                                        string text,
 
551
                                        bool bold,
 
552
                                        int size) {
 
553
                Pango.Layout layout;
 
554
                int xpad;
 
555
                var attr_list = new Pango.AttrList ();
 
556
 
 
557
                layout = widget.create_pango_layout (text);
 
558
 
 
559
                var attr = new Pango.AttrSize (size * Pango.SCALE);
 
560
                attr.absolute = 1;
 
561
                attr.start_index = 0;
 
562
                attr.end_index = attr.start_index + text.length;
 
563
                attr_list.insert ((owned) attr);
 
564
 
 
565
                if (bold) {
 
566
                        var desc = new Pango.FontDescription();
 
567
                        desc.set_weight (Pango.Weight.BOLD);
 
568
                        var attr_f = new Pango.AttrFontDesc (desc);
 
569
                        attr_list.insert ((owned) attr_f);
 
570
                }
 
571
                layout.set_attributes (attr_list);
 
572
 
 
573
                get_padding (out xpad, null);
 
574
 
 
575
                layout.set_ellipsize (Pango.EllipsizeMode.END);
 
576
 
 
577
                Pango.Rectangle rect;
 
578
                int width, text_width;
 
579
 
 
580
                layout.get_extents (null, out rect);
 
581
                text_width = rect.width;
 
582
 
 
583
                if (cell_area != null)
 
584
                        width = (cell_area.width - xpad) * Pango.SCALE;
 
585
                else
 
586
                        width = default_width * Pango.SCALE;
 
587
 
 
588
                width = int.min (width, text_width);
 
589
                layout.set_width (width);
 
590
 
 
591
                Pango.Alignment align;
 
592
                if (widget.get_direction () == TextDirection.RTL)
 
593
                        align = Pango.Alignment.RIGHT;
 
594
                else
 
595
                        align = Pango.Alignment.LEFT;
 
596
                layout.set_alignment (align);
 
597
 
 
598
                return layout;
 
599
        }
 
600
 
 
601
        public override void get_size (Widget        widget,
 
602
                                 Gdk.Rectangle? cell_area,
 
603
                                 out int       x_offset,
 
604
                                 out int       y_offset,
 
605
                                 out int       width,
 
606
                                 out int       height) {
 
607
                x_offset = y_offset = width = height = 0;
 
608
                // Not used
 
609
        }
 
610
 
 
611
        private void do_get_size (Widget       widget,
 
612
                                Gdk.Rectangle? cell_area,
 
613
                                Pango.Layout? layout,
 
614
                                out int       x_offset,
 
615
                                out int       y_offset) {
 
616
                Pango.Rectangle rect;
 
617
                int xpad, ypad;
 
618
 
 
619
                get_padding (out xpad, out ypad);
 
620
 
 
621
                layout.get_pixel_extents (null, out rect);
 
622
 
 
623
                if (cell_area != null) {
 
624
                        rect.width  = int.min (rect.width, cell_area.width - 2 * xpad + xspacing);
 
625
 
 
626
                if (widget.get_direction () == TextDirection.RTL)
 
627
                        x_offset = cell_area.width - (rect.width + xpad);
 
628
                else
 
629
                        x_offset = xpad;
 
630
 
 
631
                x_offset = int.max (x_offset, 0);
 
632
                } else {
 
633
                        x_offset = 0;
 
634
                }
 
635
 
 
636
                y_offset = ypad;
 
637
        }
 
638
 
 
639
 
 
640
        public override void render (Cairo.Context   cr,
 
641
                               Widget          widget,
 
642
                               Gdk.Rectangle   background_area,
 
643
                               Gdk.Rectangle   cell_area,
 
644
                               CellRendererState flags) {
 
645
                StyleContext context;
 
646
                Pango.Layout text_layout, path_layout;
 
647
                int text_x_offset = 0;
 
648
                int path_x_offset = 0;
 
649
                int text_y_offset = 0;
 
650
                int path_y_offset = 0;
 
651
                int xpad;
 
652
                Pango.Rectangle text_rect, path_rect;
 
653
 
 
654
                current_widget = widget;
 
655
 
 
656
                context = widget.get_style_context ();
 
657
                var font_size = context.get_font (StateFlags.NORMAL).get_size () / Pango.SCALE;
 
658
                get_padding (out xpad, null);
 
659
 
 
660
                text_layout = get_text_layout (widget, cell_area, flags, text, true, font_size);
 
661
                do_get_size (widget, cell_area, text_layout, out text_x_offset, out text_y_offset);
 
662
                text_layout.get_pixel_extents (null, out text_rect);
 
663
                text_x_offset = text_x_offset - text_rect.x;
 
664
 
 
665
                path_layout = get_text_layout (widget, cell_area, flags, path, false, font_size - 1);
 
666
                do_get_size (widget, cell_area, path_layout, out path_x_offset, out path_y_offset);
 
667
                path_layout.get_pixel_extents (null, out path_rect);
 
668
                path_x_offset = path_x_offset - path_rect.x;
 
669
 
 
670
                cr.save ();
 
671
 
 
672
                Gdk.cairo_rectangle (cr, cell_area);
 
673
                cr.clip ();
 
674
 
 
675
                Gdk.cairo_set_source_pixbuf (cr, this.pixbuf, cell_area.x, cell_area.y);
 
676
                cr.paint ();
 
677
 
 
678
                context.render_layout (cr,
 
679
                                cell_area.x + text_x_offset + this.pixbuf.width+ xspacing ,
 
680
                                cell_area.y + text_y_offset + 2,
 
681
                                text_layout);
 
682
                context.render_layout (cr,
 
683
                                cell_area.x + path_x_offset,
 
684
                                cell_area.y + path_y_offset + renderer_height - 11 - path_layout.get_baseline () / Pango.SCALE,
 
685
                                path_layout);
 
686
                cr.restore ();
 
687
        }
 
688
        
 
689
        public override void get_preferred_width (Widget       widget,
 
690
                                            out int      min_width,
 
691
                                            out int      nat_width) {
 
692
                int xpad;
 
693
 
 
694
                get_padding (out xpad, null);
 
695
 
 
696
                nat_width = min_width = xpad + default_width;
 
697
        }
 
698
 
 
699
        public override void get_preferred_height_for_width (Widget       widget,
 
700
                                                       int          width,
 
701
                                                       out int      minimum_height,
 
702
                                                       out int      natural_height) {
 
703
                int ypad;
 
704
 
 
705
                get_padding (null, out ypad);
 
706
                minimum_height = renderer_height + ypad;
 
707
                natural_height = renderer_height + ypad;
 
708
        }
 
709
 
 
710
        public override void get_preferred_height (Widget       widget,
 
711
                                             out int      minimum_size,
 
712
                                             out int      natural_size) {
 
713
                int min_width;
 
714
 
 
715
                get_preferred_width (widget, out min_width, null);
 
716
                get_preferred_height_for_width (widget, min_width,
 
717
                                        out minimum_size, out natural_size);
 
718
        }
 
719
}
 
720
 
 
721
}