--- /dev/null
+/* Copyright 2009-2010 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+namespace DialogUtils {
+ public struct filter_description_struct {
+ public string name;
+ public string extension;
+ }
+
+ Gtk.FileFilter add_filter(Gtk.FileChooserDialog d, string name, string? extension) {
+ Gtk.FileFilter filter = new Gtk.FileFilter();
+ filter.set_name(name);
+ if (extension != null) {
+ filter.add_pattern("*." + extension);
+ } else {
+ filter.add_pattern("*");
+ }
+ d.add_filter(filter);
+ return filter;
+ }
+
+ void add_filters(filter_description_struct[] filter_descriptions, Gtk.FileChooserDialog d,
+ Gee.ArrayList<Gtk.FileFilter> filters, bool allow_all) {
+
+ int length = filter_descriptions.length;
+ for (int i=0;i<length;++i) {
+ Gtk.FileFilter filter = add_filter(d, filter_descriptions[i].name,
+ filter_descriptions[i].extension);
+ filters.add(filter);
+ }
+
+ if (allow_all) {
+ add_filter(d, "All files", null);
+ //don't add to filters. filters should have same number of items as filter_descriptions
+ }
+
+ assert(filter_descriptions.length == filters.size);
+
+ d.set_filter(filters[0]);
+ }
+
+ public bool open(Gtk.Window parent, filter_description_struct[] filter_descriptions,
+ bool allow_multiple, bool allow_all, out GLib.SList<string> filenames) {
+ bool return_value = false;
+ Hildon.FileChooserDialog file_chooser = new Hildon.FileChooserDialog(parent, Gtk.FileChooserAction.OPEN);
+ file_chooser.set_title("Open Files");
+ //file_chooser.set_parent(parent);
+ //file_chooser.set_current_folder(GLib.Environment.get_home_dir());
+ //file_chooser.set_safe_folder(GLib.Environment.get_home_dir());
+ file_chooser.set_show_upnp(true);
+ Gee.ArrayList<Gtk.FileFilter> filters = new Gee.ArrayList<Gtk.FileFilter>();
+ add_filters(filter_descriptions, (Gtk.FileChooserDialog)file_chooser, filters, allow_all);
+ file_chooser.set_select_multiple(allow_multiple);
+ if (file_chooser.run() == Gtk.ResponseType.OK) {
+ return_value = true;
+ filenames = file_chooser.get_filenames();
+ }
+ file_chooser.destroy();
+ return return_value;
+ }
+
+ public bool save(Gtk.Window parent, string title, bool create_directory,
+ filter_description_struct[] filter_descriptions, ref string filename) {
+ bool return_value = false;
+
+
+ Hildon.FileChooserDialog file_chooser = new Hildon.FileChooserDialog(parent, Gtk.FileChooserAction.SAVE);
+ file_chooser.set_title(title);
+ file_chooser.set_show_upnp(false);
+ if (filename != null) {
+ file_chooser.set_current_folder(Path.get_dirname(filename));
+ } else {
+ //file_chooser.set_current_folder(GLib.Environment.get_home_dir());
+ }
+ int length = filter_descriptions.length;
+ Gee.ArrayList<Gtk.FileFilter> filters = new Gee.ArrayList<Gtk.FileFilter>();
+
+ // add_filters(filter_descriptions, (Gtk.FileChooserDialog)file_chooser, filters, false);
+
+ //all this extra code is because the dialog doesn't append the extension for us
+ //in the filename, so we can't use d.set_do_overwrite_confirmation
+
+ while (file_chooser.run() == Gtk.ResponseType.OK) {
+ string local_filename = file_chooser.get_filename();
+ if (create_directory) {
+ if (GLib.DirUtils.create(local_filename, 0777) != 0) {
+ error("Could not create directory", GLib.strerror(GLib.errno));;
+ file_chooser.present();
+ continue;
+ }
+ local_filename = Path.build_filename(local_filename,
+ Path.get_basename(local_filename));
+ }
+
+ unowned Gtk.FileFilter selected_filter = file_chooser.get_filter();
+
+ int i = 0;
+ foreach (Gtk.FileFilter file_filter in filters) {
+ if (file_filter == selected_filter) {
+ break;
+ }
+ ++i;
+ }
+
+ assert(i < length);
+
+ local_filename = append_extension(local_filename, filter_descriptions[i].extension);
+ if (!FileUtils.test(local_filename, FileTest.EXISTS) ||
+ confirm_replace(parent, local_filename)) {
+ return_value = true;
+ filename = local_filename;
+ break;
+ }
+ else {
+ file_chooser.present();
+ }
+ }
+ file_chooser.destroy();
+ return return_value;
+ }
+
+ string bold_message(string message) {
+ return message; //"<span weight=\"bold\" size=\"larger\">" + message + "</span>";
+ }
+
+ public void warning(string major_message, string? minor_message) {
+ string message = bold_message(major_message);
+ if (minor_message != null) {
+ message = message + "\n\n" + minor_message;
+ }
+ Gtk.Widget banner = Hildon.Banner.show_information_with_markup(null, null, message);
+ ((Hildon.Banner)banner).set_timeout(1000 * 2);
+ }
+
+ public void error(string major_message, string? minor_message) {
+ string message = bold_message(major_message);
+ if (minor_message != null) {
+ message = message + "\n\n" + minor_message;
+ }
+ Gtk.Widget banner = Hildon.Banner.show_information_with_markup(null, null, message);
+ ((Hildon.Banner)banner).set_timeout(1000 * 2);
+ }
+
+ Gtk.ResponseType run_dialog(Gtk.Window? parent, Gtk.MessageType type,
+ string? title, string message, ButtonStruct[] buttons) {
+ //string the_message = bold_message(message);
+ if (null == title) title = "Message";
+ Hildon.Dialog dialog = new Hildon.Dialog();
+ dialog.set_parent(parent);
+ dialog.set_title(title);
+ Gtk.VBox content = (Gtk.VBox)dialog.get_content_area();
+ Gtk.Label label = new Gtk.Label(message);
+ //label.use_markup = true;
+ label.single_line_mode = false;
+ label.set_line_wrap(true);
+
+ content.add(label);
+
+ int length = buttons.length;
+ for (int i = 0; i < length; ++i) {
+ dialog.add_button(buttons[i].title, buttons[i].type);
+ }
+
+ dialog.show_all();
+ Gtk.ResponseType response = (Gtk.ResponseType) dialog.run();
+ dialog.destroy();
+
+ return response;
+ }
+
+ Gtk.ResponseType two_button_dialog(string message, string first_button, string second_button) {
+ Hildon.Dialog d = new Hildon.Dialog();
+
+ Gtk.VBox contents = (Gtk.VBox)d.get_content_area();
+ Gtk.VBox vbox = new Gtk.VBox(true, 4);
+ Gtk.Label label = new Gtk.Label(message);
+ label.use_markup = true;
+ label.single_line_mode = false;
+ label.set_line_wrap(true);
+ vbox.pack_start(label);
+ contents.add(vbox);
+ d.add_buttons(first_button, Gtk.ResponseType.NO,
+ second_button, Gtk.ResponseType.YES);
+
+ d.show_all();
+ Gtk.ResponseType r = (Gtk.ResponseType) d.run();
+ d.destroy();
+
+ return r;
+ }
+
+ public Gtk.ResponseType delete_keep(string message) {
+ return two_button_dialog(message, "Keep", Gtk.STOCK_DELETE);
+ }
+
+ public Gtk.ResponseType add_cancel(string message) {
+ return two_button_dialog(message, Gtk.STOCK_CANCEL, Gtk.STOCK_ADD);
+ }
+
+ public Gtk.ResponseType delete_cancel(string message) {
+ return two_button_dialog(message, Gtk.STOCK_CANCEL, Gtk.STOCK_DELETE);
+ }
+
+ public bool confirm_replace(Gtk.Window? parent, string filename) {
+ return Gtk.ResponseType.YES == two_button_dialog("<big><b>A file named \"%s\" already exists. Do you want to replace it?</b></big>", "Cancel", "Replace");
+ }
+
+ struct ButtonStruct {
+ public ButtonStruct(string title, Gtk.ResponseType type) {
+ this.title = title;
+ this.type = type;
+ }
+
+ public string title;
+ public Gtk.ResponseType type;
+ }
+
+ public Gtk.ResponseType save_close_cancel(Gtk.Window? parent, string? title, string message) {
+ ButtonStruct[] buttons = {
+ ButtonStruct(Gtk.STOCK_CLOSE, Gtk.ResponseType.NO),
+ ButtonStruct(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL),
+ ButtonStruct(Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)
+ };
+
+ return run_dialog(parent, Gtk.MessageType.WARNING, title, message, buttons);
+ }
+
+ Gtk.Alignment get_aligned_label(float x, float y, float exp_x, float exp_y, string text,
+ bool selectable) {
+ Gtk.Label l = new Gtk.Label(text);
+ l.set_line_wrap(true);
+ l.use_markup = true;
+ l.selectable = selectable;
+
+ Gtk.Alignment a = new Gtk.Alignment(x, y, exp_x, exp_y);
+ a.add(l);
+
+ return a;
+ }
+
+ void add_label_to_table(Gtk.Table t, string str, int x, int y, int xpad, int ypad,
+ bool selectable) {
+ Gtk.Alignment a = get_aligned_label(0.0f, 0.0f, 0.0f, 0.0f, str, selectable);
+ t.attach(a, x, x + 1, y, y + 1, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL, xpad, ypad);
+ }
+
+ public void show_clip_properties(Gtk.Window parent, ClipView? selected_clip,
+ Model.ClipFile ? clip_file, Fraction? frames_per_second) {
+ Hildon.Dialog d = new Hildon.Dialog.with_buttons("Clip Properties", parent,
+ Gtk.DialogFlags.MODAL, Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT);
+ if (selected_clip != null) {
+ clip_file = selected_clip.clip.clipfile;
+ }
+
+ d.set("has-separator", false);
+
+ Gtk.Table t = new Gtk.Table(10, 2, false);
+ int row = 0;
+ int tab_padding = 25;
+
+ for (int i = 0; i < 10; i++)
+ t.set_row_spacing(i, 10);
+
+ row = 1;
+ add_label_to_table(t, "<b>Clip</b>", 0, row++, 5, 0, false);
+
+ if (selected_clip != null) {
+ add_label_to_table(t, "<i>Name:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%s".printf(selected_clip.clip.name), 1, row++, 5, 0, true);
+ }
+
+ add_label_to_table(t, "<i>Location:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%s".printf(clip_file.filename), 1, row++, 5, 0, true);
+
+ if (selected_clip != null) {
+ add_label_to_table(t, "<i>Timeline length:</i>", 0, row, tab_padding, 0, false);
+
+ string length_string = "";
+ string actual_length = "";
+
+ if (frames_per_second != null && frames_per_second.numerator > 0) {
+ TimeCode time = frame_to_time (time_to_frame_with_rate(selected_clip.clip.duration,
+ frames_per_second), frames_per_second);
+ length_string = time.to_string();
+ time = frame_to_time(time_to_frame_with_rate(
+ selected_clip.clip.clipfile.length, frames_per_second), frames_per_second);
+ actual_length = time.to_string();
+ } else {
+ length_string = time_to_string(selected_clip.clip.duration);
+ actual_length = time_to_string(selected_clip.clip.clipfile.length);
+ }
+
+ add_label_to_table(t, "%s".printf(length_string), 1, row++, 5, 0, true);
+
+ if (selected_clip.clip.is_trimmed()) {
+ add_label_to_table(t, "<i>Actual length:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%s".printf(actual_length), 1, row++, 5, 0, true);
+ }
+ }
+
+ if (clip_file.has_caps_structure(Model.MediaType.VIDEO)) {
+ add_label_to_table(t, "<b>Video</b>", 0, row++, 5, 0, false);
+
+ int w, h;
+ if (clip_file.get_dimensions(out w, out h)) {
+ add_label_to_table(t, "<i>Dimensions:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%d x %d".printf(w, h), 1, row++, 5, 0, true);
+ }
+
+ Fraction r;
+ if (clip_file.get_frame_rate(out r)) {
+ add_label_to_table(t, "<i>Frame rate:</i>", 0, row, tab_padding, 0, false);
+
+ if (r.numerator % r.denominator != 0)
+ add_label_to_table(t,
+ "%.2f frames per second".printf(r.numerator / (float)r.denominator),
+ 1, row++, 5, 0, true);
+ else
+ add_label_to_table(t,
+ "%d frames per second".printf(r.numerator / r.denominator),
+ 1, row++, 5, 0, true);
+ }
+ }
+
+ if (clip_file.has_caps_structure(Model.MediaType.AUDIO)) {
+ add_label_to_table(t, "<b>Audio</b>", 0, row++, 5, 0, false);
+
+ int rate;
+ if (clip_file.get_sample_rate(out rate)) {
+ add_label_to_table(t, "<i>Sample rate:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%d Hz".printf(rate), 1, row++, 5, 0, true);
+ }
+
+ string s;
+ if (clip_file.get_num_channels_string(out s)) {
+ add_label_to_table(t, "<i>Number of channels:</i>", 0, row, tab_padding, 0, false);
+ add_label_to_table(t, "%s".printf(s), 1, row++, 5, 0, true);
+ }
+ }
+
+ d.vbox.pack_start(t, false, false, 0);
+
+ d.show_all();
+ d.run();
+ d.destroy();
+ }
+}