~ubuntu-branches/debian/jessie/f-spot/jessie

« back to all changes in this revision

Viewing changes to src/Clients/MainApp/FSpot.Widgets/MetadataDisplay.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2010-08-11 22:17:42 UTC
  • mfrom: (2.4.9 experimental)
  • Revision ID: james.westby@ubuntu.com-20100811221742-2qv3a5uya7gfe1t1
* New upstream release 0.7.2 "Retooled"
  + Third release of the unstable 0.7 development series. Features a
    fully restructured source tree with full Monodevelop build
    support. Solves some of the regressions introduced in 0.7.1.
  + Reorganized source tree for clarity, builds with Monodevelop.
  + Switched from QueuedSqliteDatabase to HyenaSqliteConnection (Mike
    Gemünde)
  + Build tweaks (Christian Krause)
  + More GtkBuilder transition (Eric Faehnrich) 
  + Reliability improvements (lots of them) for metadata handling (Mike
    Gemünde, Ruben Vermeersch)
  + Prune empty directories when deleting photos, import usability
    enhancements (Mike Wallick)
  + Big race-condition fix in import (Paul Wellner Bou)
  + Loads of improvements to Taglib#, in terms of handling broken files,
    extra format support (Pentax, Panasonic, Leica), stability and
    correctness (Ruben Vermeersch)
    - Runs out of memory Importing photo with suspect EXIF data
      (LP: #272822)
    - Metadata parsing of broken file causes large memory allocation
      (LP: #597720)
    - Photo import: cancel & copy have same keyboard shortcut (LP: #244423)
    - Facebook export will not create new album (LP: #563495)
    - Allow export to iPod (LP: #518344)
  + Reporting of import errors.
  + Speedups to repeated imports of the same directory.
  + Piles of cleanups and general stability improvements.
  + Over 50 bugs closed (http://bit.ly/cqpC3y)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Widgets.MetadataDisplay.cs
 
3
 *
 
4
 * Author(s)
 
5
 *      Mike Gemuende <mike@gemuende.de>
 
6
 *      Ruben Vermeersch <ruben@savanne.be>
 
7
 *
 
8
 * This is free software. See COPYING for details.
 
9
 */
 
10
 
 
11
using System;
 
12
using System.IO;
 
13
using System.Text;
 
14
using System.Collections.Generic;
 
15
using Gtk;
 
16
 
 
17
using Mono.Unix;
 
18
 
 
19
using FSpot.Core;
 
20
using FSpot.Extensions;
 
21
using FSpot.Imaging;
 
22
 
 
23
namespace FSpot.Widgets {
 
24
        public class MetadataDisplayPage : SidebarPage {
 
25
                public MetadataDisplayPage() : base(new MetadataDisplayWidget(),
 
26
                                                                                        Catalog.GetString ("Metadata"),
 
27
                                                                                        "gtk-info") {
 
28
                        (SidebarWidget as MetadataDisplayWidget).Page = this;
 
29
                }
 
30
 
 
31
                protected override void AddedToSidebar ()
 
32
                {
 
33
                        MetadataDisplayWidget widget = SidebarWidget as MetadataDisplayWidget;
 
34
                        (Sidebar as Sidebar).SelectionChanged += widget.HandleSelectionChanged;
 
35
                        (Sidebar as Sidebar).SelectionItemsChanged += widget.HandleSelectionItemsChanged;
 
36
                }
 
37
        }
 
38
 
 
39
        public class MetadataDisplayWidget : ScrolledWindow {
 
40
                Delay update_delay;
 
41
 
 
42
                /*      This VBox only contains exif-data,
 
43
                        so it is seperated from other information */
 
44
                VBox metadata_vbox;
 
45
 
 
46
                VBox main_vbox;
 
47
                Label metadata_message;
 
48
                State display;
 
49
 
 
50
                private MetadataDisplayPage page;
 
51
                public MetadataDisplayPage Page {
 
52
                        set { page = value; }
 
53
                        get { return page; }
 
54
                }
 
55
 
 
56
                // stores list of the expanded expanders
 
57
                List<string> open_list;
 
58
 
 
59
                ListStore extended_metadata;
 
60
 
 
61
                bool up_to_date = false;
 
62
 
 
63
                enum State {
 
64
                        metadata,
 
65
                        message
 
66
                };
 
67
 
 
68
                public MetadataDisplayWidget ()
 
69
                {
 
70
                        main_vbox = new VBox ();
 
71
                        main_vbox.Spacing = 6;
 
72
 
 
73
                        metadata_message = new Label (String.Empty);
 
74
                        metadata_message.UseMarkup = true;
 
75
                        metadata_message.LineWrap = true;
 
76
                        metadata_vbox = new VBox ();
 
77
                        metadata_vbox.Spacing = 6;
 
78
 
 
79
                        main_vbox.PackStart (metadata_vbox, false, false, 0);
 
80
                        AddWithViewport (metadata_message);
 
81
                        ((Viewport) Child).ShadowType = ShadowType.None;
 
82
                        BorderWidth = 3;
 
83
 
 
84
                        display = State.message;
 
85
                        ExposeEvent += HandleExposeEvent;
 
86
 
 
87
                        open_list = new List<string> ();
 
88
 
 
89
                        // Create Expander and TreeView for
 
90
                        // extended metadata
 
91
                        TreeView tree_view = new TreeView ();
 
92
                        tree_view.HeadersVisible = false;
 
93
                        tree_view.RulesHint = true;
 
94
 
 
95
                        TreeViewColumn col = new TreeViewColumn ();
 
96
                        col.Sizing = TreeViewColumnSizing.Autosize;
 
97
                        CellRenderer colr = new CellRendererText ();
 
98
                        col.PackStart (colr, false);
 
99
 
 
100
                        col.AddAttribute (colr, "markup", 0);
 
101
 
 
102
                        tree_view.AppendColumn (col);
 
103
 
 
104
                        extended_metadata = new ListStore (typeof(string));
 
105
                        tree_view.Model = extended_metadata;
 
106
 
 
107
                        Expander expander = new Expander (String.Format("<span weight=\"bold\"><small>{0}</small></span>", Catalog.GetString ("Extended Metadata")));
 
108
                        expander.UseMarkup = true;
 
109
                        expander.Add (tree_view);
 
110
                        expander.Expanded = true;
 
111
 
 
112
                        main_vbox.PackStart (expander, false, false, 6);
 
113
                        expander.ShowAll ();
 
114
 
 
115
                        update_delay = new Delay (Update);
 
116
                        update_delay.Start ();
 
117
                }
 
118
 
 
119
                private IBrowsableItem photo;
 
120
                public IBrowsableItem Photo {
 
121
                        get { return photo; }
 
122
                        set {
 
123
                                photo = value;
 
124
 
 
125
                                if (!Visible) {
 
126
                                        up_to_date = false;
 
127
                                } else {
 
128
                                        update_delay.Start ();
 
129
                                }
 
130
                        }
 
131
                }
 
132
 
 
133
                private void HandleExposeEvent (object sender, ExposeEventArgs args)
 
134
                {
 
135
                        if (!up_to_date) {
 
136
                                update_delay.Start ();
 
137
                        }
 
138
                }
 
139
 
 
140
                internal void HandleSelectionChanged (IBrowsableCollection collection) {
 
141
            // Don't show metadata when multiple photos are selected.
 
142
                        Photo = (collection != null && collection.Count == 1) ? collection [0] : null;
 
143
                }
 
144
 
 
145
                internal void HandleSelectionItemsChanged (IBrowsableCollection collection, BrowsableEventArgs args) {
 
146
                        if (!args.Changes.MetadataChanged)
 
147
                                return;
 
148
 
 
149
                        if (!Visible) {
 
150
                                up_to_date = false;
 
151
            } else {
 
152
                                update_delay.Start ();
 
153
            }
 
154
                }
 
155
 
 
156
        private bool Visible {
 
157
            get {
 
158
                return (Page.Sidebar as Sidebar).IsActive (Page);
 
159
            }
 
160
        }
 
161
 
 
162
                private ListStore AddExpander (string name, int pos)
 
163
                {
 
164
                        TreeView tree_view = new TreeView ();
 
165
                        tree_view.HeadersVisible = false;
 
166
                        tree_view.RulesHint = true;
 
167
 
 
168
                        TreeViewColumn col = new TreeViewColumn ();
 
169
                        col.Sizing = TreeViewColumnSizing.Autosize;
 
170
                        CellRenderer colr = new CellRendererText ();
 
171
                        col.PackStart (colr, false);
 
172
 
 
173
                        col.AddAttribute (colr, "markup", 0);
 
174
 
 
175
                        tree_view.AppendColumn (col);
 
176
 
 
177
                        ListStore model = new ListStore (typeof(string));
 
178
                        tree_view.Model = model;
 
179
 
 
180
                        Expander expander = new Expander (String.Format ("<span weight=\"bold\"><small>{0}</small></span>", name));
 
181
                        expander.UseMarkup = true;
 
182
                        expander.Add (tree_view);
 
183
                        expander.Expanded = true;
 
184
 
 
185
                        metadata_vbox.PackStart (expander, false, false, 6);
 
186
                        metadata_vbox.ReorderChild (expander, pos);
 
187
 
 
188
                        if (open_list.Contains (name))
 
189
                                expander.Expanded = true;
 
190
 
 
191
                        expander.Activated += HandleExpanderActivated;
 
192
 
 
193
                        expander.ShowAll ();
 
194
 
 
195
                        return model;
 
196
                }
 
197
 
 
198
                public void HandleExpanderActivated (object sender, EventArgs e)
 
199
                {
 
200
                        Expander expander = (Expander) sender;
 
201
                        if (expander.Expanded)
 
202
                                open_list.Add (expander.Label);
 
203
                        else
 
204
                                open_list.Remove (expander.Label);
 
205
                }
 
206
 
 
207
                private bool Update ()
 
208
                {
 
209
                        bool empty = true;
 
210
                        int index_of_expander = 0;
 
211
                        bool missing = false;
 
212
                        System.Exception error = null;
 
213
 
 
214
                        /*
 
215
            // FIXME: The stuff below needs to be ported to Taglib#.
 
216
            TreeIter iter;
 
217
                        ListStore model;
 
218
                        string name;
 
219
 
 
220
                        up_to_date = true;
 
221
 
 
222
                        int i = 0;
 
223
 
 
224
                        // Write Exif-Data
 
225
                        if (exif_info != null) {
 
226
                                foreach (ExifContent content in exif_info.GetContents ()) {
 
227
                                        ExifEntry [] entries = content.GetEntries ();
 
228
 
 
229
                                        i++;
 
230
 
 
231
                                        if (entries.Length < 1)
 
232
                                                continue;
 
233
 
 
234
                                        empty = false;
 
235
 
 
236
                                        name = ExifUtil.GetIfdNameExtended ((Ifd)i - 1);
 
237
 
 
238
                                        if (index_of_expander >= metadata_vbox.Children.Length)
 
239
                                                model = AddExpander (name, index_of_expander);
 
240
                                        else {
 
241
                                                Expander expander = (Expander)metadata_vbox.Children[index_of_expander];
 
242
                                                if (expander.Label == name)
 
243
                                                        model = (ListStore)((TreeView)expander.Child).Model;
 
244
                                                else {
 
245
                                                        model = AddExpander (name, index_of_expander);
 
246
                                                }
 
247
                                        }
 
248
 
 
249
                                        model.GetIterFirst(out iter);
 
250
 
 
251
                                        foreach (ExifEntry entry in entries) {
 
252
                                                string s;
 
253
 
 
254
                                                if (entry.Title != null)
 
255
                                                        s = String.Format ("{0}\n\t<small>{1}</small>", entry.Title, entry.Value);
 
256
                                                else
 
257
                                                        s = String.Format ("Unknown Tag ID={0}\n\t<small>{1}</small>", entry.Tag.ToString (), entry.Value);
 
258
 
 
259
                                                if (model.IterIsValid(iter)) {
 
260
                                                        model.SetValue (iter, 0, s);
 
261
                                                        model.IterNext(ref iter);
 
262
                                                } else
 
263
                                                        model.AppendValues (s);
 
264
                                        }
 
265
 
 
266
                                        // remove rows, that are not used
 
267
                                        while (model.IterIsValid(iter)) {
 
268
                                                model.Remove (ref iter);
 
269
                                        }
 
270
 
 
271
                                        index_of_expander++;
 
272
                                }
 
273
                        }
 
274
 
 
275
 
 
276
                        // Write Extended Metadata
 
277
                        if (photo != null) {
 
278
                                MetadataStore store = new MetadataStore ();
 
279
                                try {
 
280
                                        using (var img = ImageFile.Create (photo.DefaultVersion.Uri)) {
 
281
                                                if (img is SemWeb.StatementSource) {
 
282
                                                        StatementSource source = (StatementSource)img;
 
283
                                                        source.Select (store);
 
284
                                                }
 
285
                                        }
 
286
                                } catch (System.IO.FileNotFoundException) {
 
287
                                        missing = true;
 
288
                                } catch (System.Exception e){
 
289
                                        // Sometimes we don't get the right exception, check for the file
 
290
                                        if (!System.IO.File.Exists (photo.DefaultVersion.Uri.LocalPath)) {
 
291
                                                missing = true;
 
292
                                        } else {
 
293
                                                // if the file is there but we still got an exception display it.
 
294
                                                error = e;
 
295
                                        }
 
296
                                }
 
297
 
 
298
                                model = extended_metadata;
 
299
                                model.GetIterFirst(out iter);
 
300
 
 
301
                                if (store.StatementCount > 0) {
 
302
                                        empty = false;
 
303
 
 
304
 
 
305
                                        foreach (Statement stmt in store) {
 
306
                                                // Skip anonymous subjects because they are
 
307
                                                // probably part of a collection
 
308
                                                if (stmt.Subject.Uri == null && store.SelectSubjects (null, stmt.Subject).Length > 0)
 
309
                                                        continue;
 
310
 
 
311
                                                string title;
 
312
                                                string value;
 
313
                                                string s;
 
314
 
 
315
                                                Description.GetDescription (store, stmt, out title, out value);
 
316
 
 
317
                                                if (value == null)
 
318
                                                {
 
319
                                                        MemoryStore substore = store.Select (new Statement ((Entity)stmt.Object, null, null, null)).Load();
 
320
                                                        StringBuilder collection = new StringBuilder ();
 
321
                                                        collection.Append (title);
 
322
                                                        WriteCollection (substore, collection);
 
323
                                                        if (model.IterIsValid(iter))
 
324
                                                        {
 
325
                                                                model.SetValue (iter, 0, collection.ToString ());
 
326
                                                                model.IterNext(ref iter);
 
327
                                                        } else
 
328
                                                                model.AppendValues (collection.ToString ());
 
329
                                                } else {
 
330
                                                        s = String.Format ("{0}\n\t<small>{1}</small>", title, value);
 
331
                                                        if (model.IterIsValid(iter))
 
332
                                                        {
 
333
                                                                model.SetValue (iter, 0, s);
 
334
                                                                model.IterNext(ref iter);
 
335
                                                        } else
 
336
                                                                model.AppendValues (s);
 
337
                                                }
 
338
                                        }
 
339
 
 
340
                                } else {
 
341
                                        // clear Extended Metadata
 
342
                                        String s = String.Format ("<small>{0}</small>", Catalog.GetString ("No Extended Metadata Available"));
 
343
                                        if (model.IterIsValid(iter))
 
344
                                        {
 
345
                                                model.SetValue (iter, 0, s);
 
346
                                                model.IterNext(ref iter);
 
347
                                        } else
 
348
                                                model.AppendValues (s);
 
349
                                }
 
350
 
 
351
                                // remove rows, that are not used
 
352
                                while (model.IterIsValid(iter)) {
 
353
                                        model.Remove (ref iter);
 
354
                                }
 
355
                        }*/
 
356
 
 
357
                        if (empty) {
 
358
                                string msg;
 
359
                                if (photo == null) {
 
360
                                     msg = Catalog.GetString ("No active photo");
 
361
                                } else if (missing) {
 
362
                                        msg = String.Format (Catalog.GetString ("The photo \"{0}\" does not exist"), photo.DefaultVersion.Uri);
 
363
                                } else {
 
364
                                     msg = Catalog.GetString ("No metadata available");
 
365
 
 
366
                                        if (error != null) {
 
367
                                                msg = String.Format ("<i>{0}</i>", error);
 
368
                                        }
 
369
                                }
 
370
 
 
371
                                metadata_message.Markup = "<span weight=\"bold\">" + msg + "</span>";
 
372
 
 
373
                                if (display == State.metadata) {
 
374
                                        // Child is a Viewport, (AddWithViewport in ctor)
 
375
                                        ((Viewport)Child).Remove (main_vbox);
 
376
                                        ((Viewport)Child).Add (metadata_message);
 
377
                                        display = State.message;
 
378
                                        metadata_message.Show ();
 
379
                                }
 
380
                        } else {
 
381
                                // remove Expanders, that are not used
 
382
                                while (index_of_expander < metadata_vbox.Children.Length)
 
383
                                        metadata_vbox.Remove (metadata_vbox.Children[index_of_expander]);
 
384
 
 
385
                                if (display == State.message) {
 
386
                                        // Child is a Viewport, (AddWithViewport in ctor)
 
387
                                        ((Viewport)Child).Remove (metadata_message);
 
388
                                        ((Viewport)Child).Add (main_vbox);
 
389
                                        display = State.metadata;
 
390
                                        main_vbox.ShowAll ();
 
391
                                }
 
392
                        }
 
393
 
 
394
                        return false;
 
395
                }
 
396
 
 
397
        /*
 
398
                private void WriteCollection (MemoryStore substore, StringBuilder collection)
 
399
                {
 
400
                        string type = null;
 
401
 
 
402
                        foreach (Statement stmt in substore) {
 
403
                                if (stmt.Predicate.Uri == MetadataStore.Namespaces.Resolve ("rdf:type")) {
 
404
                                        string prefix;
 
405
                                        MetadataStore.Namespaces.Normalize (stmt.Object.Uri, out prefix, out type);
 
406
                                }
 
407
                        }
 
408
 
 
409
                        foreach (Statement sub in substore) {
 
410
                                if (sub.Object is SemWeb.Literal) {
 
411
                                        string title;
 
412
                                        string value = ((SemWeb.Literal)sub.Object).Value;
 
413
 
 
414
                                        Description.GetDescription (substore, sub, out title, out value);
 
415
 
 
416
                                        if (type == null)
 
417
                                                collection.AppendFormat ("\n\t<small>{0}: {1}</small>", title, value);
 
418
                                        else
 
419
                                                collection.AppendFormat ("\n\t<small>{0}</small>", value);
 
420
 
 
421
                                } else {
 
422
                                        if (type == null) {
 
423
                                                MemoryStore substore2 = substore.Select (new Statement ((Entity)sub.Object, null, null, null)).Load();
 
424
                                                if (substore.StatementCount > 0)
 
425
                                                        WriteCollection (substore2, collection);
 
426
                                        }
 
427
                                }
 
428
                        }
 
429
                }*/
 
430
        }
 
431
}