xmpedit

GTK+ editor for XMP metadata embedded in images
git clone https://code.djc.id.au/git/xmpedit/

src/MainWindow.vala (5617B) - raw

      1 /*
      2  * xmpedit
      3  * Copyright 2010 Dan Callaghan <djc@djc.id.au>
      4  * Released under GPLv2
      5  */
      6 
      7 namespace Xmpedit {
      8 
      9 private const string STOCK_CLOSE_WITHOUT_SAVING = "xmpedit-close-without-saving";
     10 
     11 public class MainWindow : Gtk.Window {
     12 
     13     private File file;
     14     private ImageMetadata image_metadata;
     15     private Gtk.Table table;
     16     private Gtk.Image image_preview;
     17     private MetadataTreeView tree_view;
     18     private PropertyDetailView detail_view;
     19     
     20     static construct {
     21         add_stock();
     22     }
     23     
     24     public MainWindow(string path) throws GLib.Error {
     25         Object(type: Gtk.WindowType.TOPLEVEL);
     26         file = File.new_for_path(path);
     27         image_metadata = new ImageMetadata(path);
     28         image_metadata.load();
     29         table = new Gtk.Table(/* rows */ 2, /* cols */ 2, /* homogeneous */ false);
     30         
     31         title = file.get_basename();
     32         default_width = 640;
     33         default_height = 480;
     34         allow_shrink = true;
     35         
     36         image_preview = new Gtk.Image.from_pixbuf(new Gdk.Pixbuf.from_file_at_scale(path, 320, 320, /* preserve aspect */ true));
     37         ((Atk.Object) image_preview.get_accessible())
     38                 .set_name("Image preview");
     39         ((Atk.Object) image_preview.get_accessible())
     40                 .set_role(Atk.Role.IMAGE);
     41         ((Atk.Image) image_preview.get_accessible())
     42                 .set_image_description(@"Preview of $(file.get_basename())");
     43         table.attach(image_preview,
     44                 1, 2, 0, 1,
     45                 Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, 0,
     46                 10, 10);
     47         
     48         tree_view = new MetadataTreeView.connected_to(image_metadata);
     49         ((Atk.Object) tree_view.get_accessible())
     50                 .set_name("Image properties");
     51         var tree_view_scrolled = new Gtk.ScrolledWindow(null, null);
     52         tree_view_scrolled.add(tree_view);
     53         tree_view_scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
     54         var revert_button = new Gtk.Button.from_stock(Gtk.Stock.REVERT_TO_SAVED);
     55         revert_button.clicked.connect(() => {
     56             image_metadata.revert();
     57             tree_view.set_cursor(new Gtk.TreePath.first(), null, false);
     58         });
     59         var save_button = new Gtk.Button.from_stock(Gtk.Stock.SAVE);
     60         save_button.clicked.connect(() => {
     61             image_metadata.save();
     62         });
     63         revert_button.sensitive = false;
     64         save_button.sensitive = false;
     65         image_metadata.notify.connect((p) => {
     66             if (p.name == "dirty") {
     67                 revert_button.sensitive = image_metadata.dirty;
     68                 save_button.sensitive = image_metadata.dirty;
     69             }
     70         });
     71         var left_button_box = new Gtk.HButtonBox();
     72         left_button_box.spacing = 5;
     73         left_button_box.layout_style = Gtk.ButtonBoxStyle.END;
     74         left_button_box.add(revert_button);
     75         left_button_box.add(save_button);
     76         var left_vbox = new Gtk.VBox(/* homogeneous */ false, /* spacing */ 0);
     77         left_vbox.pack_start(tree_view_scrolled, /* expand */ true, /* fill */ true);
     78         left_vbox.pack_start(left_button_box, /* expand */ false, /* fill */ false,
     79                 /* padding */ 5);
     80         table.attach(left_vbox,
     81                 0, 1, 0, 2,
     82                 Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND,
     83                 0, 0);
     84         
     85         detail_view = new PropertyDetailView.connected_to(image_metadata, tree_view);
     86         table.attach(detail_view,
     87                 1, 2, 1, 2,
     88                 Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND,
     89                 Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND,
     90                 0, 0);
     91         
     92         add(table);
     93         show_all();
     94         
     95         delete_event.connect(() => {
     96             if (image_metadata.dirty) {
     97                 var dialog = new Gtk.MessageDialog.with_markup(
     98                         /* parent */ this, Gtk.DialogFlags.MODAL,
     99                         Gtk.MessageType.WARNING, Gtk.ButtonsType.NONE,
    100                         "<big><b>Your changes to image \"%s\" have not been saved.</b></big>\n\n" +
    101                         "Save changes before closing?",
    102                         file.get_basename());
    103                 dialog.add_button(STOCK_CLOSE_WITHOUT_SAVING, 1);
    104                 dialog.add_button(Gtk.Stock.CANCEL, 2);
    105                 dialog.add_button(Gtk.Stock.SAVE, 3);
    106                 dialog.set_default_response(3);
    107                 var response = dialog.run();
    108                 dialog.destroy();
    109                 switch (response) {
    110                     case 3: // save
    111                         image_metadata.save();
    112                         return false;
    113                     case 1: // close
    114                         return false;
    115                     case 2: // cancel
    116                     default:
    117                         return true;
    118                 }
    119             }
    120             return false;
    121         });
    122         
    123         add_stock();
    124     }
    125     
    126     private static Gtk.StockItem[] STOCK = {
    127         Gtk.StockItem() {
    128             stock_id = STOCK_CLOSE_WITHOUT_SAVING,
    129             label = "Close _without saving",
    130             modifier = 0,
    131             keyval = 0,
    132             translation_domain = null
    133         }
    134     };
    135     
    136     /** Create custom stock entries used in the application. */
    137     private static void add_stock() {
    138         Gtk.Stock.add_static(STOCK);
    139     
    140         var icon_factory = new Gtk.IconFactory();
    141         icon_factory.add(STOCK_CLOSE_WITHOUT_SAVING,
    142                 Gtk.IconFactory.lookup_default(Gtk.Stock.CLOSE));
    143         icon_factory.add_default();
    144     }
    145     
    146 }
    147 
    148 }