diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-04-03 13:15:00 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-04-03 13:15:00 +0200 | 
| commit | bc53b714952ceb0afd02b591403cb2bc0cb1aab9 (patch) | |
| tree | 8ff57ed1a1265b2c87f37e3c8fa19876faf80990 /src | |
| parent | d4c476947425c12b1984fedea16f8a8c42a07ba3 (diff) | |
| parent | c43dfb815a4951b8248f4f0e98babe4f80204f03 (diff) | |
Merge tag 'upstream/0.22.0'
Upstream version 0.22.0
Diffstat (limited to 'src')
175 files changed, 1235 insertions, 1147 deletions
| diff --git a/src/AppDirs.vala b/src/AppDirs.vala index 6bf6759..1421314 100644 --- a/src/AppDirs.vala +++ b/src/AppDirs.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/AppWindow.vala b/src/AppWindow.vala index 5a8e9c4..d294114 100644 --- a/src/AppWindow.vala +++ b/src/AppWindow.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -10,8 +10,8 @@ public class FullscreenWindow : PageWindow {      public const int TOOLBAR_CHECK_DISMISSAL_MSEC = 500;      private Gtk.Window toolbar_window = new Gtk.Window(Gtk.WindowType.POPUP); -    private Gtk.ToolButton close_button = new Gtk.ToolButton.from_stock(Gtk.Stock.LEAVE_FULLSCREEN); -    private Gtk.ToggleToolButton pin_button = new Gtk.ToggleToolButton.from_stock(Resources.PIN_TOOLBAR); +    private Gtk.ToolButton close_button = new Gtk.ToolButton(null, null); +    private Gtk.ToggleToolButton pin_button = new Gtk.ToggleToolButton();      private bool is_toolbar_shown = false;      private bool waiting_for_invoke = false;      private time_t left_toolbar_time = 0; @@ -49,11 +49,13 @@ public class FullscreenWindow : PageWindow {          // restore pin state          is_toolbar_dismissal_enabled = Config.Facade.get_instance().get_pin_toolbar_state(); +        pin_button.set_icon_name("pin-toolbar");          pin_button.set_label(_("Pin Toolbar"));          pin_button.set_tooltip_text(_("Pin the toolbar open"));          pin_button.set_active(!is_toolbar_dismissal_enabled);          pin_button.clicked.connect(update_toolbar_dismissal); +        close_button.set_icon_name("view-restore");          close_button.set_tooltip_text(_("Leave fullscreen"));          close_button.clicked.connect(on_close); @@ -129,10 +131,10 @@ public class FullscreenWindow : PageWindow {      private Gtk.ActionEntry[] create_actions() {          Gtk.ActionEntry[] actions = new Gtk.ActionEntry[0]; -        Gtk.ActionEntry leave_fullscreen = { "LeaveFullscreen", Gtk.Stock.LEAVE_FULLSCREEN, +        Gtk.ActionEntry leave_fullscreen = { "LeaveFullscreen", Resources.LEAVE_FULLSCREEN_LABEL,              TRANSLATABLE, "F11", TRANSLATABLE, on_close }; -        leave_fullscreen.label = _("Leave _Fullscreen"); -        leave_fullscreen.tooltip = _("Leave fullscreen"); +        leave_fullscreen.label = Resources.LEAVE_FULLSCREEN_LABEL; +        leave_fullscreen.tooltip = Resources.LEAVE_FULLSCREEN_LABEL;          actions += leave_fullscreen;          return actions; @@ -490,27 +492,35 @@ public abstract class AppWindow : PageWindow {          ui.ensure_update();          add_accel_group(ui.get_accel_group()); +         +        Gtk.CssProvider provider = new Gtk.CssProvider(); +        try { +            provider.load_from_data(Resources.CUSTOM_CSS, -1); +            Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); +        } catch (Error err) { +            debug("Unable to load custom CSS: %s", err.message); +        }      }      private Gtk.ActionEntry[] create_common_actions() {          Gtk.ActionEntry[] actions = new Gtk.ActionEntry[0]; -        Gtk.ActionEntry quit = { "CommonQuit", Gtk.Stock.QUIT, TRANSLATABLE, "<Ctrl>Q", +        Gtk.ActionEntry quit = { "CommonQuit", Resources.QUIT_LABEL, TRANSLATABLE, "<Ctrl>Q",              TRANSLATABLE, on_quit }; -        quit.label = _("_Quit"); +        quit.label = Resources.QUIT_LABEL;          actions += quit; -        Gtk.ActionEntry about = { "CommonAbout", Gtk.Stock.ABOUT, TRANSLATABLE, null, +        Gtk.ActionEntry about = { "CommonAbout", Resources.ABOUT_LABEL, TRANSLATABLE, null,              TRANSLATABLE, on_about }; -        about.label = _("_About"); +        about.label = Resources.ABOUT_LABEL;          actions += about; -        Gtk.ActionEntry fullscreen = { "CommonFullscreen", Gtk.Stock.FULLSCREEN, +        Gtk.ActionEntry fullscreen = { "CommonFullscreen", Resources.FULLSCREEN_LABEL,              TRANSLATABLE, "F11", TRANSLATABLE, on_fullscreen }; -        fullscreen.label = _("Fulls_creen"); +        fullscreen.label = Resources.FULLSCREEN_LABEL;          actions += fullscreen; -        Gtk.ActionEntry help_contents = { "CommonHelpContents", Gtk.Stock.HELP, +        Gtk.ActionEntry help_contents = { "CommonHelpContents", Resources.HELP_LABEL,              TRANSLATABLE, "F1", TRANSLATABLE, on_help_contents };          help_contents.label = _("_Contents");          actions += help_contents; @@ -525,22 +535,22 @@ public abstract class AppWindow : PageWindow {          help_report_problem.label = _("_Report a Problem...");          actions += help_report_problem; -        Gtk.ActionEntry undo = { "CommonUndo", Gtk.Stock.UNDO, TRANSLATABLE, "<Ctrl>Z", +        Gtk.ActionEntry undo = { "CommonUndo", Resources.UNDO_MENU, TRANSLATABLE, "<Ctrl>Z",              TRANSLATABLE, on_undo };          undo.label = Resources.UNDO_MENU;          actions += undo; -        Gtk.ActionEntry redo = { "CommonRedo", Gtk.Stock.REDO, TRANSLATABLE, "<Ctrl><Shift>Z", +        Gtk.ActionEntry redo = { "CommonRedo", Resources.REDO_MENU, TRANSLATABLE, "<Ctrl><Shift>Z",              TRANSLATABLE, on_redo };          redo.label = Resources.REDO_MENU;          actions += redo; -        Gtk.ActionEntry jump_to_file = { "CommonJumpToFile", Gtk.Stock.JUMP_TO, TRANSLATABLE,  +        Gtk.ActionEntry jump_to_file = { "CommonJumpToFile", Resources.JUMP_TO_FILE_MENU, TRANSLATABLE,               "<Ctrl><Shift>M", TRANSLATABLE, on_jump_to_file };          jump_to_file.label = Resources.JUMP_TO_FILE_MENU;          actions += jump_to_file; -        Gtk.ActionEntry select_all = { "CommonSelectAll", Gtk.Stock.SELECT_ALL, TRANSLATABLE, +        Gtk.ActionEntry select_all = { "CommonSelectAll", Resources.SELECT_ALL_MENU, TRANSLATABLE,              "<Ctrl>A", TRANSLATABLE, on_select_all };          select_all.label = Resources.SELECT_ALL_MENU;          actions += select_all; diff --git a/src/Application.vala b/src/Application.vala index 95163cf..fa81832 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/BatchImport.vala b/src/BatchImport.vala index d4298ed..13feabe 100644 --- a/src/BatchImport.vala +++ b/src/BatchImport.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Box.vala b/src/Box.vala index f48bcfb..253f0b6 100644 --- a/src/Box.vala +++ b/src/Box.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/CheckerboardLayout.vala b/src/CheckerboardLayout.vala index 6d0ce61..b71870c 100644 --- a/src/CheckerboardLayout.vala +++ b/src/CheckerboardLayout.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/CollectionPage.vala b/src/CollectionPage.vala index 22dcdee..95cbf01 100644 --- a/src/CollectionPage.vala +++ b/src/CollectionPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -142,7 +142,7 @@ public abstract class CollectionPage : MediaPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry print = { "Print", Gtk.Stock.PRINT, TRANSLATABLE, "<Ctrl>P", +        Gtk.ActionEntry print = { "Print", Resources.PRINT_LABEL, TRANSLATABLE, "<Ctrl>P",              TRANSLATABLE, on_print };          print.label = Resources.PRINT_MENU;          actions += print; @@ -193,7 +193,7 @@ public abstract class CollectionPage : MediaPage {          paste_adjustments.tooltip = Resources.PASTE_ADJUSTMENTS_TOOLTIP;          actions += paste_adjustments; -        Gtk.ActionEntry revert = { "Revert", Gtk.Stock.REVERT_TO_SAVED, TRANSLATABLE, null, +        Gtk.ActionEntry revert = { "Revert", null, TRANSLATABLE, null,              TRANSLATABLE, on_revert };          revert.label = Resources.REVERT_MENU;          actions += revert; @@ -215,7 +215,7 @@ public abstract class CollectionPage : MediaPage {          adjust_date_time.label = Resources.ADJUST_DATE_TIME_MENU;          actions += adjust_date_time; -        Gtk.ActionEntry external_edit = { "ExternalEdit", Gtk.Stock.EDIT, TRANSLATABLE, "<Ctrl>Return", +        Gtk.ActionEntry external_edit = { "ExternalEdit", Resources.EDIT_LABEL, TRANSLATABLE, "<Ctrl>Return",              TRANSLATABLE, on_external_edit };          external_edit.label = Resources.EXTERNAL_EDIT_MENU;          actions += external_edit; diff --git a/src/ColorTransformation.vala b/src/ColorTransformation.vala index 74e4cf2..1e3e4a8 100644 --- a/src/ColorTransformation.vala +++ b/src/ColorTransformation.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/CommandManager.vala b/src/CommandManager.vala index 070bc73..379b259 100644 --- a/src/CommandManager.vala +++ b/src/CommandManager.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Commands.vala b/src/Commands.vala index 04b771c..d1a0593 100644 --- a/src/Commands.vala +++ b/src/Commands.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/CustomComponents.vala b/src/CustomComponents.vala index 4ace52c..d9e4916 100644 --- a/src/CustomComponents.vala +++ b/src/CustomComponents.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Debug.vala b/src/Debug.vala index ad626f4..c8e8de5 100644 --- a/src/Debug.vala +++ b/src/Debug.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/DesktopIntegration.vala b/src/DesktopIntegration.vala index 9978803..1ee3c59 100644 --- a/src/DesktopIntegration.vala +++ b/src/DesktopIntegration.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. diff --git a/src/Dialogs.vala b/src/Dialogs.vala index 1f6a5ce..d760e73 100644 --- a/src/Dialogs.vala +++ b/src/Dialogs.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -35,7 +35,7 @@ public bool confirm_warn_developer_changed(int number) {          "<span weight=\"bold\" size=\"larger\">%s</span>".printf(ngettext("Switching developers will undo all changes you have made to this photo in Shotwell",          "Switching developers will undo all changes you have made to these photos in Shotwell", number))); -    dialog.add_buttons(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL); +    dialog.add_buttons(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL);      dialog.add_buttons(_("_Switch Developer"), Gtk.ResponseType.YES);      int response = dialog.run(); @@ -58,8 +58,8 @@ public File? choose_file(string current_file_basename) {          _("Export Video") : _("Export Photo");      Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog(file_chooser_title, -        AppWindow.get_instance(), Gtk.FileChooserAction.SAVE, Gtk.Stock.CANCEL,  -        Gtk.ResponseType.CANCEL, Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT, null); +        AppWindow.get_instance(), Gtk.FileChooserAction.SAVE, Resources.CANCEL_LABEL,  +        Gtk.ResponseType.CANCEL, Resources.SAVE_LABEL, Gtk.ResponseType.ACCEPT, null);      chooser.set_do_overwrite_confirmation(true);      chooser.set_current_folder(current_export_dir.get_path());      chooser.set_current_name(current_file_basename); @@ -87,8 +87,8 @@ public File? choose_dir(string? user_title = null) {          user_title = _("Export Photos");      Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog(user_title, -        AppWindow.get_instance(), Gtk.FileChooserAction.SELECT_FOLDER, Gtk.Stock.CANCEL,  -        Gtk.ResponseType.CANCEL, Gtk.Stock.OK, Gtk.ResponseType.ACCEPT, null); +        AppWindow.get_instance(), Gtk.FileChooserAction.SELECT_FOLDER, Resources.CANCEL_LABEL,  +        Gtk.ResponseType.CANCEL, Resources.OK_LABEL, Gtk.ResponseType.ACCEPT, null);      chooser.set_current_folder(current_export_dir.get_path());      chooser.set_local_only(false); @@ -168,6 +168,8 @@ public class ExportDialog : Gtk.Dialog {      private bool in_insert = false;      public ExportDialog(string title) { +        Object (use_header_bar: 1); +                  this.title = title;          resizable = false; @@ -198,7 +200,6 @@ public class ExportDialog : Gtk.Dialog {          pixels_entry = new Gtk.Entry();          pixels_entry.set_max_length(6); -        pixels_entry.set_size_request(60, -1);          pixels_entry.set_text("%d".printf(current_scale));          // register after preparation to avoid signals during init @@ -218,30 +219,23 @@ public class ExportDialog : Gtk.Dialog {          add_label(_("_Scaling constraint:"), 0, 2, constraint_combo);          add_control(constraint_combo, 1, 2); -        Gtk.Label pixels_label = new Gtk.Label.with_mnemonic(_(" _pixels")); -        pixels_label.set_mnemonic_widget(pixels_entry); -         -        Gtk.Box pixels_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0); -        pixels_box.pack_start(pixels_entry, false, false, 0); -        pixels_box.pack_end(pixels_label, false, false, 0); -        add_control(pixels_box, 1, 3); +        add_label(_("_Pixels:"), 0, 3, pixels_entry); +        add_control(pixels_entry, 1, 3);          export_metadata = new Gtk.CheckButton.with_label(_("Export metadata"));          add_control(export_metadata, 1, 4);          export_metadata.active = true; -        table.set_row_spacing(4); -        table.set_column_spacing(4); -        table.set_margin_top(4); -        table.set_margin_bottom(4); -        table.set_margin_left(4); -        table.set_margin_right(4); +        table.set_row_spacing(5); +        table.set_column_spacing(5); +        table.set_border_width(3);          ((Gtk.Box) get_content_area()).add(table);          // add buttons to action area -        add_button(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL); -        ok_button = add_button(Gtk.Stock.OK, Gtk.ResponseType.OK); +        add_button(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL); +        ok_button = add_button(Resources.OK_LABEL, Gtk.ResponseType.OK); +        set_default_response(Gtk.ResponseType.OK);          ok_button.set_can_default(true);          ok_button.has_default = true; @@ -357,7 +351,7 @@ public class ExportDialog : Gtk.Dialog {      }      private void add_label(string text, int x, int y, Gtk.Widget? widget = null) { -        Gtk.Alignment left_aligned = new Gtk.Alignment(0.0f, 0.5f, 0, 0); +        Gtk.Alignment left_aligned = new Gtk.Alignment(1, 0.5f, 0, 0);          Gtk.Label new_label = new Gtk.Label.with_mnemonic(text);          new_label.set_use_underline(true); @@ -371,7 +365,7 @@ public class ExportDialog : Gtk.Dialog {      }      private void add_control(Gtk.Widget widget, int x, int y) { -        Gtk.Alignment left_aligned = new Gtk.Alignment(0, 0.5f, 0, 0); +        Gtk.Alignment left_aligned = new Gtk.Alignment(0, 0.5f, 1, 0);          left_aligned.add(widget);          table.attach(left_aligned, x, y, 1, 1); @@ -857,7 +851,7 @@ public bool report_manifest(ImportManifest manifest, bool show_dest_id,          Gtk.Widget save_results_button = dialog.add_button(ImportUI.SAVE_RESULTS_BUTTON_NAME,              ImportUI.SAVE_RESULTS_RESPONSE_ID);          save_results_button.set_visible(manifest.success.size < manifest.all.size); -        Gtk.Widget ok_button = dialog.add_button(Gtk.Stock.OK, Gtk.ResponseType.OK); +        Gtk.Widget ok_button = dialog.add_button(Resources.OK_LABEL, Gtk.ResponseType.OK);          dialog.set_default(ok_button);          Gtk.Window dialog_parent = (Gtk.Window) dialog.get_parent(); @@ -896,7 +890,7 @@ public bool report_manifest(ImportManifest manifest, bool show_dest_id,  internal void save_import_results(Gtk.Window? chooser_dialog_parent, string results_log) {      Gtk.FileChooserDialog chooser_dialog = new Gtk.FileChooserDialog(          ImportUI.SAVE_RESULTS_FILE_CHOOSER_TITLE, chooser_dialog_parent, Gtk.FileChooserAction.SAVE, -        Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT, null); +        Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL, Resources.SAVE_AS_LABEL, Gtk.ResponseType.ACCEPT, null);      chooser_dialog.set_do_overwrite_confirmation(true);      chooser_dialog.set_current_folder(Environment.get_home_dir());      chooser_dialog.set_current_name("Shotwell Import Log.txt"); @@ -1196,6 +1190,10 @@ public class TextEntryDialog : Gtk.Dialog {      private Gtk.Button button2;      private Gtk.ButtonBox action_area_box; +    public TextEntryDialog() { +        Object (use_header_bar: 1); +    } +          public void set_builder(Gtk.Builder builder) {          this.builder = builder;      } @@ -1204,7 +1202,6 @@ public class TextEntryDialog : Gtk.Dialog {          string? initial_text, Gee.Collection<string>? completion_list, string? completion_delimiter) {          set_title(title);          set_resizable(true); -        set_default_size (350, 104);          set_parent_window(AppWindow.get_instance().get_parent_window());          set_transient_for(AppWindow.get_instance());          on_modify_validate = modify_validate; @@ -1220,8 +1217,8 @@ public class TextEntryDialog : Gtk.Dialog {          action_area_box = (Gtk.ButtonBox) get_action_area();          action_area_box.set_layout(Gtk.ButtonBoxStyle.END); -        button1 = (Gtk.Button) add_button(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL); -        button2 = (Gtk.Button) add_button(Gtk.Stock.SAVE, Gtk.ResponseType.OK); +        button1 = (Gtk.Button) add_button(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL); +        button2 = (Gtk.Button) add_button(Resources.SAVE_LABEL, Gtk.ResponseType.OK);          set_default_response(Gtk.ResponseType.OK);          if (completion_list != null) { // Textfield with autocompletion @@ -1266,6 +1263,10 @@ public class MultiTextEntryDialog : Gtk.Dialog {      private Gtk.Button button2;      private Gtk.ButtonBox action_area_box; +    public MultiTextEntryDialog() { +        Object (use_header_bar: 1); +    } +          public void set_builder(Gtk.Builder builder) {          this.builder = builder;      } @@ -1278,12 +1279,6 @@ public class MultiTextEntryDialog : Gtk.Dialog {          set_transient_for(AppWindow.get_instance());          on_modify_validate = modify_validate; -        Gtk.Label name_label = builder.get_object("label9") as Gtk.Label; -        name_label.set_text(label); -         -        Gtk.ScrolledWindow scrolled = builder.get_object("scrolledwindow1") as Gtk.ScrolledWindow; -        scrolled.set_shadow_type (Gtk.ShadowType.ETCHED_IN); -                  entry = builder.get_object("textview1") as Gtk.TextView;          entry.set_wrap_mode (Gtk.WrapMode.WORD);          entry.buffer = new Gtk.TextBuffer(null); @@ -1294,8 +1289,9 @@ public class MultiTextEntryDialog : Gtk.Dialog {          action_area_box = (Gtk.ButtonBox) get_action_area();          action_area_box.set_layout(Gtk.ButtonBoxStyle.END); -        button1 = (Gtk.Button) add_button(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL); -        button2 = (Gtk.Button) add_button(Gtk.Stock.SAVE, Gtk.ResponseType.OK); +        button1 = (Gtk.Button) add_button(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL); +        button2 = (Gtk.Button) add_button(Resources.SAVE_LABEL, Gtk.ResponseType.OK); +        set_default_response(Gtk.ResponseType.OK);          set_has_resize_grip(true);      } @@ -1326,7 +1322,9 @@ public class EventRenameDialog : TextEntryDialogMediator {  public class EditTitleDialog : TextEntryDialogMediator {      public EditTitleDialog(string? photo_title) { -        base (_("Edit Title"), _("Title:"), photo_title); +        // Dialog title +        base (_("Edit Title"), +            _("Title:"), photo_title);      }      public virtual string? execute() { @@ -1340,7 +1338,10 @@ public class EditTitleDialog : TextEntryDialogMediator {  public class EditCommentDialog : MultiTextEntryDialogMediator {      public EditCommentDialog(string? comment, bool is_event = false) { -        string title_tmp = (is_event) ? _("Edit Event Comment") : _("Edit Photo/Video Comment"); +        string title_tmp = (is_event) +            // Dialog title +            ? _("Edit Event Comment") +            : _("Edit Photo/Video Comment");          base(title_tmp, _("Comment:"), comment);      } @@ -1477,7 +1478,7 @@ public class ProgressDialog : Gtk.Window {          vbox_bar.pack_start(progress_bar, true, false, 0);          if (cancellable != null) { -            cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL); +            cancel_button = new Gtk.Button.with_mnemonic(Resources.CANCEL_LABEL);              cancel_button.clicked.connect(on_cancel);              delete_event.connect(on_window_closed);          } @@ -1648,12 +1649,14 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          bool contains_video = false, bool only_video = false) {          assert(source != null); +        Object(use_header_bar: 1); +                  set_modal(true);          set_resizable(false);          set_transient_for(AppWindow.get_instance()); -        add_buttons(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, -                    Gtk.Stock.OK, Gtk.ResponseType.OK); +        add_buttons(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL, +                    Resources.OK_LABEL, Gtk.ResponseType.OK);          set_title(Resources.ADJUST_DATE_TIME_LABEL);          calendar = new Gtk.Calendar(); @@ -1669,13 +1672,16 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          hour.output.connect(on_spin_button_output);          hour.set_width_chars(2);   +        hour.set_max_width_chars(2);          minute = new Gtk.SpinButton.with_range(0, 59, 1);          minute.set_width_chars(2); +        minute.set_max_width_chars(2);          minute.output.connect(on_spin_button_output);          second = new Gtk.SpinButton.with_range(0, 59, 1);          second.set_width_chars(2); +        second.set_max_width_chars(2);          second.output.connect(on_spin_button_output);          system = new Gtk.ComboBoxText(); @@ -1684,14 +1690,14 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          system.append_text(_("24 Hr"));          system.changed.connect(on_time_system_changed); -        Gtk.Box clock = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0); +        Gtk.Box clock = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3); -        clock.pack_start(hour, false, false, 3); -        clock.pack_start(new Gtk.Label(":"), false, false, 3); // internationalize? -        clock.pack_start(minute, false, false, 3); -        clock.pack_start(new Gtk.Label(":"), false, false, 3); -        clock.pack_start(second, false, false, 3); -        clock.pack_start(system, false, false, 3); +        clock.pack_start(hour, false, false, 0); +        clock.pack_start(new Gtk.Label(":"), false, false, 0); // internationalize? +        clock.pack_start(minute, false, false, 0); +        clock.pack_start(new Gtk.Label(":"), false, false, 0); +        clock.pack_start(second, false, false, 0); +        clock.pack_start(system, false, false, 0);          set_default_response(Gtk.ResponseType.OK); @@ -1719,15 +1725,15 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          modify_originals_check_button.sensitive = (!only_video) &&              (!Config.Facade.get_instance().get_commit_metadata_to_masters() && display_options); -        Gtk.Box time_content = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); +        Gtk.Box time_content = new Gtk.Box(Gtk.Orientation.VERTICAL, 5); -        time_content.pack_start(calendar, true, false, 3); -        time_content.pack_start(clock, true, false, 3); +        time_content.pack_start(calendar, true, false, 0); +        time_content.pack_start(clock, true, false, 0);          if (display_options) { -            time_content.pack_start(relativity_radio_button, true, false, 3); -            time_content.pack_start(batch_radio_button, true, false, 3); -            time_content.pack_start(modify_originals_check_button, true, false, 3); +            time_content.pack_start(relativity_radio_button, true, false, 0); +            time_content.pack_start(batch_radio_button, true, false, 0); +            time_content.pack_start(modify_originals_check_button, true, false, 0);          }          Gdk.Pixbuf preview = null; @@ -1740,26 +1746,26 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          }          Gtk.Box image_content = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); +        image_content.set_valign(Gtk.Align.START); +        image_content.set_homogeneous(true);          Gtk.Image image = (preview != null) ? new Gtk.Image.from_pixbuf(preview) : new Gtk.Image();          original_time_label = new Gtk.Label(null); -        image_content.pack_start(image, true, false, 3); -        image_content.pack_start(original_time_label, true, false, 3); +        image_content.pack_start(image, true, false, 0); +        image_content.pack_start(original_time_label, true, false, 0); -        Gtk.Box hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0); -        hbox.pack_start(image_content, true, false, 6); -        hbox.pack_start(time_content, true, false, 6); +        Gtk.Box hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 10); +        hbox.set_border_width(3); +        hbox.pack_start(image_content, true, false, 0); +        hbox.pack_start(time_content, true, false, 0);          Gtk.Alignment hbox_alignment = new Gtk.Alignment(0.5f, 0.5f, 0, 0); -        hbox_alignment.set_padding(6, 3, 6, 6);          hbox_alignment.add(hbox); -        ((Gtk.Box) get_content_area()).pack_start(hbox_alignment, true, false, 6); +        ((Gtk.Box) get_content_area()).pack_start(hbox_alignment, true, false, 0);          notification = new Gtk.Label("");          notification.set_line_wrap(true);          notification.set_justify(Gtk.Justification.CENTER); -        notification.set_size_request(-1, -1); -        notification.set_padding(12, 6);          ((Gtk.Box) get_content_area()).pack_start(notification, true, true, 0); @@ -1779,8 +1785,8 @@ public class AdjustDateTimeDialog : Gtk.Dialog {          calendar.select_day(time.day);          if (Config.Facade.get_instance().get_use_24_hour_time()) { -            hour.set_value(time.hour);              system.set_active(TimeSystem.24HR); +            hour.set_value(time.hour);          } else {              int AMPM_hour = time.hour % 12;              hour.set_value((AMPM_hour == 0) ? 12 : AMPM_hour); @@ -2066,7 +2072,7 @@ public class WelcomeDialog : Gtk.Dialog {      public WelcomeDialog(Gtk.Window owner) {          import_meta_host = new Spit.DataImports.WelcomeImportMetaHost(this);          bool show_system_pictures_import = is_system_pictures_import_possible(); -        Gtk.Widget ok_button = add_button(Gtk.Stock.OK, Gtk.ResponseType.OK); +        Gtk.Widget ok_button = add_button(Resources.OK_LABEL, Gtk.ResponseType.OK);          set_title(_("Welcome!"));          set_resizable(false);          set_type_hint(Gdk.WindowTypeHint.DIALOG); @@ -2265,7 +2271,6 @@ public class PreferencesDialog {      private Gee.ArrayList<PathFormat> path_formats = new Gee.ArrayList<PathFormat>();      private GLib.DateTime example_date = new GLib.DateTime.local(2009, 3, 10, 18, 16, 11);      private Gtk.CheckButton lowercase; -    private Gtk.Button close_button;      private Plugins.ManifestWidgetMediator plugins_mediator = new Plugins.ManifestWidgetMediator();      private Gtk.ComboBoxText default_raw_developer_combo; @@ -2289,8 +2294,6 @@ public class PreferencesDialog {          library_dir_button = builder.get_object("library_dir_button") as Gtk.FileChooserButton; -        close_button = builder.get_object("close_button") as Gtk.Button; -                  photo_editor_combo = builder.get_object("external_photo_editor_combo") as Gtk.ComboBox;          raw_editor_combo = builder.get_object("external_raw_editor_combo") as Gtk.ComboBox; @@ -2563,20 +2566,19 @@ public class PreferencesDialog {           if (is_string_empty(example) && !is_string_empty(dir_pattern_entry.text)) {              // Invalid pattern.              dir_pattern_example.set_text(_("Invalid pattern")); -            dir_pattern_entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, Gtk.Stock.DIALOG_ERROR); +            dir_pattern_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "dialog-error");              dir_pattern_entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, false);              set_allow_closing(false);           } else {              // Valid pattern.              dir_pattern_example.set_text(example); -            dir_pattern_entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, null); +            dir_pattern_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, null);              set_allow_closing(true);           }      }      private void set_allow_closing(bool allow) {          dialog.set_deletable(allow); -        close_button.set_sensitive(allow);          allow_closing = allow;      } diff --git a/src/Dimensions.vala b/src/Dimensions.vala index f689aca..42188d3 100644 --- a/src/Dimensions.vala +++ b/src/Dimensions.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/DirectoryMonitor.vala b/src/DirectoryMonitor.vala index 1778fe4..468425f 100644 --- a/src/DirectoryMonitor.vala +++ b/src/DirectoryMonitor.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Event.vala b/src/Event.vala index ed0af76..cbc3485 100644 --- a/src/Event.vala +++ b/src/Event.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Exporter.vala b/src/Exporter.vala index a930c4c..6a1b377 100644 --- a/src/Exporter.vala +++ b/src/Exporter.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/International.vala b/src/International.vala index 1bf242b..a51d0a2 100644 --- a/src/International.vala +++ b/src/International.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/LibraryFiles.vala b/src/LibraryFiles.vala index 4cffe94..918ed1e 100644 --- a/src/LibraryFiles.vala +++ b/src/LibraryFiles.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. diff --git a/src/LibraryMonitor.vala b/src/LibraryMonitor.vala index 363213b..4793f7d 100644 --- a/src/LibraryMonitor.vala +++ b/src/LibraryMonitor.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/MediaDataRepresentation.vala b/src/MediaDataRepresentation.vala index 6a54718..31b9cc8 100644 --- a/src/MediaDataRepresentation.vala +++ b/src/MediaDataRepresentation.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/MediaInterfaces.vala b/src/MediaInterfaces.vala index 96c5d49..e5f078c 100644 --- a/src/MediaInterfaces.vala +++ b/src/MediaInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/MediaMetadata.vala b/src/MediaMetadata.vala index ad0d719..22ee96b 100644 --- a/src/MediaMetadata.vala +++ b/src/MediaMetadata.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/MediaMonitor.vala b/src/MediaMonitor.vala index aeb2952..5d9c488 100644 --- a/src/MediaMonitor.vala +++ b/src/MediaMonitor.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/MediaPage.vala b/src/MediaPage.vala index 9f98466..6496503 100644 --- a/src/MediaPage.vala +++ b/src/MediaPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -9,6 +9,7 @@ public class MediaSourceItem : CheckerboardItem {      private static Gdk.Pixbuf current_sprocket_pixbuf = null;      private bool enable_sprockets = false; +    private string? natural_collation_key = null;      // preserve the same constructor arguments and semantics as CheckerboardItem so that we're      // a drop-in replacement @@ -93,6 +94,19 @@ public class MediaSourceItem : CheckerboardItem {      public void set_enable_sprockets(bool enable_sprockets) {          this.enable_sprockets = enable_sprockets;      } +     +    public new void set_title(string text, bool marked_up = false, +        Pango.Alignment alignment = Pango.Alignment.LEFT) { +        base.set_title(text, marked_up, alignment); +        this.natural_collation_key = null; +    } +     +    public string get_natural_collation_key() { +        if (this.natural_collation_key == null) { +            this.natural_collation_key = NaturalCollate.collate_key(this.get_title()); +        } +        return this.natural_collation_key; +    }  }  public abstract class MediaPage : CheckerboardPage { @@ -108,7 +122,8 @@ public abstract class MediaPage : CheckerboardPage {          TITLE = 1,          EXPOSURE_DATE = 2,          RATING = 3, -        MAX = 3 +        FILENAME = 4, +        MAX = 4      }      protected class ZoomSliderAssembly : Gtk.ToolItem { @@ -271,7 +286,7 @@ public abstract class MediaPage : CheckerboardPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry export = { "Export", Gtk.Stock.SAVE_AS, TRANSLATABLE, "<Ctrl><Shift>E", +        Gtk.ActionEntry export = { "Export", Resources.SAVE_AS_LABEL, TRANSLATABLE, "<Ctrl><Shift>E",              TRANSLATABLE, on_export };          export.label = Resources.EXPORT_MENU;          actions += export; @@ -288,7 +303,7 @@ public abstract class MediaPage : CheckerboardPage {          send_to_context_menu.label = Resources.SEND_TO_CONTEXT_MENU;          actions += send_to_context_menu; -        Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Gtk.Stock.REMOVE, TRANSLATABLE, +        Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Resources.REMOVE_LABEL, TRANSLATABLE,              "<Shift>Delete", TRANSLATABLE, on_remove_from_library };          remove_from_library.label = Resources.REMOVE_FROM_LIBRARY_MENU;          actions += remove_from_library; @@ -298,7 +313,7 @@ public abstract class MediaPage : CheckerboardPage {          move_to_trash.label = Resources.MOVE_TO_TRASH_MENU;          actions += move_to_trash; -        Gtk.ActionEntry new_event = { "NewEvent", Gtk.Stock.NEW, TRANSLATABLE, "<Ctrl>N", +        Gtk.ActionEntry new_event = { "NewEvent", Resources.NEW_LABEL, TRANSLATABLE, "<Ctrl>N",              TRANSLATABLE, on_new_event };          new_event.label = Resources.NEW_EVENT_MENU;          actions += new_event; @@ -320,13 +335,13 @@ public abstract class MediaPage : CheckerboardPage {          modify_tags.label = Resources.MODIFY_TAGS_MENU;          actions += modify_tags; -        Gtk.ActionEntry increase_size = { "IncreaseSize", Gtk.Stock.ZOOM_IN, TRANSLATABLE, +        Gtk.ActionEntry increase_size = { "IncreaseSize", Resources.ZOOM_IN_LABEL, TRANSLATABLE,              "<Ctrl>plus", TRANSLATABLE, on_increase_size };          increase_size.label = _("Zoom _In");          increase_size.tooltip = _("Increase the magnification of the thumbnails");          actions += increase_size; -        Gtk.ActionEntry decrease_size = { "DecreaseSize", Gtk.Stock.ZOOM_OUT, TRANSLATABLE, +        Gtk.ActionEntry decrease_size = { "DecreaseSize", Resources.ZOOM_OUT_LABEL, TRANSLATABLE,              "<Ctrl>minus", TRANSLATABLE, on_decrease_size };          decrease_size.label = _("Zoom _Out");          decrease_size.tooltip = _("Decrease the magnification of the thumbnails"); @@ -403,7 +418,7 @@ public abstract class MediaPage : CheckerboardPage {          filter_photos.label = Resources.FILTER_PHOTOS_MENU;          actions += filter_photos; -        Gtk.ActionEntry play = { "PlayVideo", Gtk.Stock.MEDIA_PLAY, TRANSLATABLE, "<Ctrl>Y", +        Gtk.ActionEntry play = { "PlayVideo", Resources.PLAY_LABEL, TRANSLATABLE, "<Ctrl>Y",              TRANSLATABLE, on_play_video };          play.label = _("_Play Video");          play.tooltip = _("Open the selected videos in the system video player"); @@ -484,18 +499,24 @@ public abstract class MediaPage : CheckerboardPage {          by_rating.tooltip = _("Sort photos by rating");          sort_crit_actions += by_rating; +        Gtk.RadioActionEntry by_filename = { "SortByFilename", null, TRANSLATABLE, null, +            TRANSLATABLE, SortBy.FILENAME }; +        by_filename.label = _("By _Filename"); +        by_filename.tooltip = _("Sort photos by filename"); +        sort_crit_actions += by_filename; +          action_group.add_radio_actions(sort_crit_actions, sort_by, on_sort_changed);          // Sort order.          Gtk.RadioActionEntry[] sort_order_actions = new Gtk.RadioActionEntry[0]; -        Gtk.RadioActionEntry ascending = { "SortAscending", Gtk.Stock.SORT_ASCENDING, +        Gtk.RadioActionEntry ascending = { "SortAscending", Resources.SORT_ASCENDING_LABEL,              TRANSLATABLE, null, TRANSLATABLE, SORT_ORDER_ASCENDING };          ascending.label = _("_Ascending");          ascending.tooltip = _("Sort photos in an ascending order");          sort_order_actions += ascending; -        Gtk.RadioActionEntry descending = { "SortDescending", Gtk.Stock.SORT_DESCENDING, +        Gtk.RadioActionEntry descending = { "SortDescending", Resources.SORT_DESCENDING_LABEL,              TRANSLATABLE, null, TRANSLATABLE, SORT_ORDER_DESCENDING };          descending.label = _("D_escending");          descending.tooltip = _("Sort photos in a descending order"); @@ -1206,6 +1227,13 @@ public abstract class MediaPage : CheckerboardPage {                  predicate = Thumbnail.rating_comparator_predicate;                  break; +            case SortBy.FILENAME: +                if (ascending) +                    comparator = Thumbnail.filename_ascending_comparator; +                else comparator = Thumbnail.filename_descending_comparator; +                predicate = Thumbnail.filename_comparator_predicate; +                break; +              default:                  debug("Unknown sort criteria: %s", get_menu_sort_by().to_string());                  comparator = Thumbnail.title_descending_comparator; @@ -1226,6 +1254,9 @@ public abstract class MediaPage : CheckerboardPage {              case SortBy.RATING:                  return "/MenuBar/ViewMenu/SortPhotos/SortByRating"; + +            case SortBy.FILENAME: +                return "/MenuBar/ViewMenu/SortPhotos/SortByFilename";              default:                  debug("Unknown sort criteria: %d", sort_by); diff --git a/src/MediaViewTracker.vala b/src/MediaViewTracker.vala index 879dc84..0c48f2d 100644 --- a/src/MediaViewTracker.vala +++ b/src/MediaViewTracker.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/MetadataWriter.vala b/src/MetadataWriter.vala index aee5855..969506e 100644 --- a/src/MetadataWriter.vala +++ b/src/MetadataWriter.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. @@ -23,6 +23,8 @@ public class MetadataWriter : Object {          public Photo.ReimportMasterState reimport_master_state = null;          public Photo.ReimportEditableState reimport_editable_state = null;          public Error? err = null; +        public bool wrote_master = false; +        public bool wrote_editable = false;          public CommitJob(MetadataWriter owner, LibraryPhoto photo, Gee.Set<string>? keywords) {              base (owner, owner.on_update_completed, new Cancellable(), owner.on_update_cancelled); @@ -58,6 +60,8 @@ public class MetadataWriter : Object {                      LibraryMonitor.unblacklist_file(photo.get_master_file());                  }              } +             +            wrote_master = true;          }          private void commit_editable() throws Error { @@ -75,6 +79,8 @@ public class MetadataWriter : Object {                      LibraryMonitor.unblacklist_file(photo.get_editable_file());                  }              } +             +            wrote_editable = true;          }          private bool update_metadata(PhotoMetadata metadata, bool skip_orientation = false) { @@ -617,10 +623,21 @@ public class MetadataWriter : Object {      private void on_update_completed(BackgroundJob j) {          CommitJob job = (CommitJob) j; -        if (job.err != null) -            warning("Unable to update metadata for %s: %s", job.photo.to_string(), job.err.message); -        else -            message("Completed writing metadata for %s", job.photo.to_string()); +        if (job.err != null) { +            warning("Unable to write metadata to %s: %s", job.photo.to_string(), job.err.message); +        } else { +            if (job.wrote_master) +                message("Completed writing metadata to %s", job.photo.get_master_file().get_path()); +            else +                message("Unable to write metadata to %s", job.photo.get_master_file().get_path()); +             +            if (job.photo.get_editable_file() != null) { +                if (job.wrote_editable) +                    message("Completed writing metadata to %s", job.photo.get_editable_file().get_path()); +                else +                    message("Unable to write metadata to %s", job.photo.get_editable_file().get_path()); +            } +        }          bool removed = pending.unset(job.photo);          assert(removed); diff --git a/src/NaturalCollate.vala b/src/NaturalCollate.vala new file mode 100644 index 0000000..4adb027 --- /dev/null +++ b/src/NaturalCollate.vala @@ -0,0 +1,98 @@ +/** + * NaturalCollate + * Simple helper class for natural sorting in Vala. + * + * (c) Tobia Tesan <tobia.tesan@gmail.com>, 2014 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; see the file COPYING.  If not, + * see <http://www.gnu.org/licenses/>. + */ + +namespace NaturalCollate { + +private const unichar SUPERDIGIT = ':'; +private const unichar NUM_SENTINEL = 0x2; // glib uses these, so do we +private const string  COLLATION_SENTINEL = "\x01\x01\x01"; + +private static int read_number(owned string s, ref int byte_index) { +    /* +     * Given a string in the form [numerals]*[everythingelse]* +     * returns the int value of the first block and increments index +     * by its length as a side effect. +     * Notice that "numerals" is not just 0-9 but everything else  +     * Unicode considers a numeral (see: string::isdigit()) +     */ +    int number = 0; + +    while (s.length != 0 && s.get_char(0).isdigit()) { +        number = number*10; +        number += s.get_char(0).digit_value(); +        int second_char = s.index_of_nth_char(1); +        s = s.substring(second_char); +        byte_index += second_char; +    } +    return number; +} + +public static int compare(string str1, string str2) { +    return strcmp(collate_key(str1), collate_key(str2)); +} + +public static string collate_key(owned string str) { +    /* +     * Computes a collate key. +     * Has roughly the same effect as g_utf8_collate_key_for_file, except that it doesn't +     * handle the dot as a special char. +     */ +    assert (str.validate()); +    string result = ""; +    bool eos = (str.length == 0); + +    while (!eos) { +        assert(str.validate()); +        int position = 0; +        while (!(str.get_char(position).to_string() in "0123456789")) { +            // We only care about plain old 0123456789, aping what g_utf8_collate_key_for_filename does +            position++; +        } + +        // (0... position( is a bunch of non-numerical chars, so we compute and append the collate key... +        result = result + (str.substring(0, position).collate_key()); + +        // ...then throw them away +        str = str.substring(position); + +        eos = (str.length == 0); +        position = 0; + +        if (!eos) { +            // We have some numbers to handle in front of us +            int number = read_number(str, ref position); +            str = str.substring(position); +            int number_of_superdigits = number.to_string().length; +            string to_append = ""; +            for (int i = 1; i < number_of_superdigits; i++) { +                // We append n - 1 superdigits where n is the number of digits +                to_append = to_append + SUPERDIGIT.to_string(); +            } +            to_append = to_append + (number.to_string()); // We append the actual number +            result = result + +                     COLLATION_SENTINEL + +                     NUM_SENTINEL.to_string() + +                     to_append; +        } +        eos = (str.length == 0); +    } + +    result = result + NUM_SENTINEL.to_string(); +    // No specific reason except that glib does it + +    return result; +} +} diff --git a/src/Orientation.vala b/src/Orientation.vala index b31c22d..e9f0cd0 100644 --- a/src/Orientation.vala +++ b/src/Orientation.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Page.vala b/src/Page.vala index 807a926..72613e0 100644 --- a/src/Page.vala +++ b/src/Page.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -95,8 +95,6 @@ public abstract class Page : Gtk.ScrolledWindow {          init_ui();          realize.connect(attach_view_signals); -         -        Resources.style_widget(this, Resources.SCROLL_FRAME_STYLESHEET);      }      ~Page() { @@ -218,6 +216,7 @@ public abstract class Page : Gtk.ScrolledWindow {              toolbar = toolbar_path == null ? new Gtk.Toolbar() :                                               ui.get_widget(toolbar_path) as Gtk.Toolbar;              toolbar.get_style_context().add_class("bottom-toolbar");  // for elementary theme +            toolbar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR);          }          return toolbar;      } @@ -1210,8 +1209,6 @@ public abstract class CheckerboardPage : Page {          viewport.set_border_width(0);          viewport.set_shadow_type(Gtk.ShadowType.NONE); -        Resources.style_widget(viewport, Resources.VIEWPORT_STYLESHEET); -                  viewport.add(layout);          // want to set_adjustments before adding to ScrolledWindow to let our signal handlers @@ -1228,8 +1225,6 @@ public abstract class CheckerboardPage : Page {          // scrollbar policy          set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); -         -        Resources.style_widget(this, Resources.PAGE_STYLESHEET);      }      public void init_item_context_menu(string path) { @@ -1952,9 +1947,6 @@ public abstract class SinglePhotoPage : Page {          canvas.draw.connect(on_canvas_exposed);          set_event_source(canvas); -         -        // style the viewport -        Resources.style_widget(viewport, Resources.VIEWPORT_STYLESHEET);      }      public bool is_transition_in_progress() { diff --git a/src/Photo.vala b/src/Photo.vala index 98a3175..2f2b7a5 100644 --- a/src/Photo.vala +++ b/src/Photo.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/PhotoMonitor.vala b/src/PhotoMonitor.vala index d7f2929..58725a4 100644 --- a/src/PhotoMonitor.vala +++ b/src/PhotoMonitor.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/PhotoPage.vala b/src/PhotoPage.vala index 8db84a1..c4175a3 100644 --- a/src/PhotoPage.vala +++ b/src/PhotoPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -398,8 +398,8 @@ public abstract class EditingHostPage : SinglePhotoPage {      private Gtk.ToggleToolButton straighten_button = null;      private Gtk.ToolButton enhance_button = null;      private Gtk.Scale zoom_slider = null; -    private Gtk.ToolButton prev_button = new Gtk.ToolButton.from_stock(Gtk.Stock.GO_BACK); -    private Gtk.ToolButton next_button = new Gtk.ToolButton.from_stock(Gtk.Stock.GO_FORWARD); +    private Gtk.ToolButton prev_button = new Gtk.ToolButton(null, Resources.PREVIOUS_LABEL); +    private Gtk.ToolButton next_button = new Gtk.ToolButton(null, Resources.NEXT_LABEL);      private EditingTools.EditingTool current_tool = null;      private Gtk.ToggleToolButton current_editing_toggle = null;      private Gdk.Pixbuf cancel_editing_pixbuf = null; @@ -467,7 +467,8 @@ public abstract class EditingHostPage : SinglePhotoPage {          toolbar.insert(redeye_button, -1);          // adjust tool -        adjust_button = new Gtk.ToggleToolButton.from_stock(Resources.ADJUST); +        adjust_button = new Gtk.ToggleToolButton(); +        adjust_button.set_icon_name(Resources.ADJUST);          adjust_button.set_label(Resources.ADJUST_LABEL);          adjust_button.set_tooltip_text(Resources.ADJUST_TOOLTIP);          adjust_button.toggled.connect(on_adjust_toggled); @@ -475,8 +476,8 @@ public abstract class EditingHostPage : SinglePhotoPage {          toolbar.insert(adjust_button, -1);          // enhance tool -        enhance_button = new Gtk.ToolButton.from_stock(Resources.ENHANCE); -        enhance_button.set_label(Resources.ENHANCE_LABEL); +        enhance_button = new Gtk.ToolButton(null, Resources.ENHANCE_LABEL); +        enhance_button.set_icon_name(Resources.ENHANCE);          enhance_button.set_tooltip_text(Resources.ENHANCE_TOOLTIP);          enhance_button.clicked.connect(on_enhance);          enhance_button.is_important = true; @@ -530,11 +531,13 @@ public abstract class EditingHostPage : SinglePhotoPage {          // previous button          prev_button.set_tooltip_text(_("Previous photo")); +        prev_button.set_icon_name("go-previous");          prev_button.clicked.connect(on_previous_photo);          toolbar.insert(prev_button, -1);          // next button          next_button.set_tooltip_text(_("Next photo")); +        next_button.set_icon_name("go-next");          next_button.clicked.connect(on_next_photo);          toolbar.insert(next_button, -1);      } @@ -1157,7 +1160,7 @@ public abstract class EditingHostPage : SinglePhotoPage {          }          if (pixbuf == null) {              // Create empty pixbuf. -            pixbuf = AppWindow.get_instance().render_icon(Gtk.Stock.MISSING_IMAGE,  +            pixbuf = AppWindow.get_instance().render_icon("image-missing",                   Gtk.IconSize.DIALOG, null);              get_canvas_scaling().perform_on_pixbuf(pixbuf, Gdk.InterpType.NEAREST, true); @@ -2381,12 +2384,12 @@ public class LibraryPhotoPage : EditingHostPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry export = { "Export", Gtk.Stock.SAVE_AS, TRANSLATABLE, "<Ctrl><Shift>E", +        Gtk.ActionEntry export = { "Export", Resources.SAVE_AS_LABEL, TRANSLATABLE, "<Ctrl><Shift>E",              TRANSLATABLE, on_export };          export.label = Resources.EXPORT_MENU;          actions += export; -        Gtk.ActionEntry print = { "Print", Gtk.Stock.PRINT, TRANSLATABLE, "<Ctrl>P", +        Gtk.ActionEntry print = { "Print", Resources.PRINT_LABEL, TRANSLATABLE, "<Ctrl>P",              TRANSLATABLE, on_print };          print.label = Resources.PRINT_MENU;          actions += print; @@ -2397,7 +2400,7 @@ public class LibraryPhotoPage : EditingHostPage {          publish.tooltip = Resources.PUBLISH_TOOLTIP;          actions += publish; -        Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Gtk.Stock.REMOVE, TRANSLATABLE, +        Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Resources.REMOVE_LABEL, TRANSLATABLE,              "<Shift>Delete", TRANSLATABLE, on_remove_from_library };          remove_from_library.label = Resources.REMOVE_FROM_LIBRARY_MENU;          actions += remove_from_library; @@ -2415,13 +2418,13 @@ public class LibraryPhotoPage : EditingHostPage {          tools.label = _("T_ools");          actions += tools; -        Gtk.ActionEntry prev = { "PrevPhoto", Gtk.Stock.GO_BACK, TRANSLATABLE, null, +        Gtk.ActionEntry prev = { "PrevPhoto", Resources.PREVIOUS_LABEL, TRANSLATABLE, null,              TRANSLATABLE, on_previous_photo };          prev.label = _("_Previous Photo");          prev.tooltip = _("Previous Photo");          actions += prev; -        Gtk.ActionEntry next = { "NextPhoto", Gtk.Stock.GO_FORWARD, TRANSLATABLE, null, +        Gtk.ActionEntry next = { "NextPhoto", Resources.NEXT_LABEL, TRANSLATABLE, null,              TRANSLATABLE, on_next_photo };          next.label = _("_Next Photo");          next.tooltip = _("Next Photo"); @@ -2473,7 +2476,7 @@ public class LibraryPhotoPage : EditingHostPage {          crop.tooltip = Resources.CROP_TOOLTIP;          actions += crop; -        Gtk.ActionEntry straighten = { "Straighten", Gtk.Stock.REFRESH, TRANSLATABLE, "<Ctrl>A", +        Gtk.ActionEntry straighten = { "Straighten", Resources.REFRESH_LABEL, TRANSLATABLE, "<Ctrl>A",              TRANSLATABLE, toggle_straighten };          straighten.label = Resources.STRAIGHTEN_MENU;          straighten.tooltip = Resources.STRAIGHTEN_TOOLTIP; @@ -2491,7 +2494,7 @@ public class LibraryPhotoPage : EditingHostPage {          adjust.tooltip = Resources.ADJUST_TOOLTIP;          actions += adjust; -        Gtk.ActionEntry revert = { "Revert", Gtk.Stock.REVERT_TO_SAVED, TRANSLATABLE, +        Gtk.ActionEntry revert = { "Revert", Resources.REVERT_TO_SAVED_LABEL, TRANSLATABLE,              null, TRANSLATABLE, on_revert };          revert.label = Resources.REVERT_MENU;          actions += revert; @@ -2511,7 +2514,7 @@ public class LibraryPhotoPage : EditingHostPage {          adjust_date_time.label = Resources.ADJUST_DATE_TIME_MENU;          actions += adjust_date_time; -        Gtk.ActionEntry external_edit = { "ExternalEdit", Gtk.Stock.EDIT, TRANSLATABLE, +        Gtk.ActionEntry external_edit = { "ExternalEdit", Resources.EDIT_LABEL, TRANSLATABLE,              "<Ctrl>Return", TRANSLATABLE, on_external_edit };          external_edit.label = Resources.EXTERNAL_EDIT_MENU;          actions += external_edit; @@ -2585,25 +2588,25 @@ public class LibraryPhotoPage : EditingHostPage {          rate_five.label = Resources.rating_menu(Rating.FIVE);          actions += rate_five; -        Gtk.ActionEntry increase_size = { "IncreaseSize", Gtk.Stock.ZOOM_IN, TRANSLATABLE, +        Gtk.ActionEntry increase_size = { "IncreaseSize", Resources.ZOOM_IN_LABEL, TRANSLATABLE,              "<Ctrl>plus", TRANSLATABLE, on_increase_size };          increase_size.label = _("Zoom _In");          increase_size.tooltip = _("Increase the magnification of the photo");          actions += increase_size; -        Gtk.ActionEntry decrease_size = { "DecreaseSize", Gtk.Stock.ZOOM_OUT, TRANSLATABLE, +        Gtk.ActionEntry decrease_size = { "DecreaseSize", Resources.ZOOM_OUT_LABEL, TRANSLATABLE,              "<Ctrl>minus", TRANSLATABLE, on_decrease_size };          decrease_size.label = _("Zoom _Out");          decrease_size.tooltip = _("Decrease the magnification of the photo");          actions += decrease_size; -        Gtk.ActionEntry best_fit = { "ZoomFit", Gtk.Stock.ZOOM_FIT, TRANSLATABLE, +        Gtk.ActionEntry best_fit = { "ZoomFit", Resources.ZOOM_FIT_LABEL, TRANSLATABLE,              "<Ctrl>0", TRANSLATABLE, snap_zoom_to_min };          best_fit.label = _("Fit to _Page");          best_fit.tooltip = _("Zoom the photo to fit on the screen");          actions += best_fit; -        Gtk.ActionEntry actual_size = { "Zoom100", Gtk.Stock.ZOOM_100, TRANSLATABLE, +        Gtk.ActionEntry actual_size = { "Zoom100", Resources.ZOOM_100_LABEL, TRANSLATABLE,              "<Ctrl>1", TRANSLATABLE, snap_zoom_to_isomorphic };          /// xgettext:no-c-format          actual_size.label = _("Zoom _100%"); @@ -3029,15 +3032,13 @@ public class LibraryPhotoPage : EditingHostPage {      }      protected override bool on_double_click(Gdk.EventButton event) { -        if (!(get_container() is FullscreenWindow)) { +        FullscreenWindow? fs = get_container() as FullscreenWindow; +        if (fs == null)              return_to_collection_on_release = true; -             -            return true; -        } -         -        AppWindow.get_instance().end_fullscreen(); +        else +            fs.close(); -        return base.on_double_click(event); +        return true;      }      protected override bool on_left_released(Gdk.EventButton event) { diff --git a/src/PixbufCache.vala b/src/PixbufCache.vala index 0708f5e..e3723ae 100644 --- a/src/PixbufCache.vala +++ b/src/PixbufCache.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Printing.vala b/src/Printing.vala index 8e37997..b0a2cf0 100644 --- a/src/Printing.vala +++ b/src/Printing.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Properties.vala b/src/Properties.vala index 9edb4fb..88e0e1d 100644 --- a/src/Properties.vala +++ b/src/Properties.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -453,8 +453,6 @@ private class BasicProperties : Properties {  private class ExtendedPropertiesWindow : Gtk.Dialog {      private ExtendedProperties properties = null; -    private const int FRAME_BORDER = 6; -    private Gtk.Button close_button;      private class ExtendedProperties : Properties {          private const string NO_VALUE = ""; @@ -632,13 +630,13 @@ private class ExtendedPropertiesWindow : Gtk.Dialog {      }      public ExtendedPropertiesWindow(Gtk.Window owner) { +        Object(use_header_bar: 1); +                  add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.KEY_PRESS_MASK);          focus_on_map = true;          set_accept_focus(true);          set_can_focus(true);          set_title(_("Extended Information")); -        set_size_request(300,-1); -        set_default_size(520, -1);          set_position(Gtk.WindowPosition.CENTER);          set_transient_for(owner);          set_type_hint(Gdk.WindowTypeHint.DIALOG); @@ -648,20 +646,8 @@ private class ExtendedPropertiesWindow : Gtk.Dialog {          properties = new ExtendedProperties();          Gtk.Alignment alignment = new Gtk.Alignment(0.5f,0.5f,1,1);          alignment.add(properties); -        alignment.set_padding(4, 4, 4, 4); +        alignment.set_border_width(3);          ((Gtk.Box) get_content_area()).add(alignment); -        close_button = new Gtk.Button.from_stock(Gtk.Stock.CLOSE); -        close_button.clicked.connect(on_close_clicked); -     -        Gtk.Alignment action_alignment = new Gtk.Alignment(1, 0.5f, 1, 1); -        action_alignment.add(close_button); -        ((Gtk.Container) get_action_area()).add(action_alignment); -         -        set_has_resize_grip(false); -    } - -    ~ExtendedPropertiesWindow() { -        close_button.clicked.disconnect(on_close_clicked);      }      public override bool button_press_event(Gdk.EventButton event) { @@ -674,10 +660,6 @@ private class ExtendedPropertiesWindow : Gtk.Dialog {          return true;      } -    private void on_close_clicked() { -        hide(); -    } -      public override bool key_press_event(Gdk.EventKey event) {          // hide properties          if (Gdk.keyval_name(event.keyval) == "Escape") { diff --git a/src/Resources.vala b/src/Resources.vala index c8f02c4..54118f8 100644 --- a/src/Resources.vala +++ b/src/Resources.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -24,7 +24,7 @@ namespace Resources {      public const string? GIT_VERSION = null;  #endif -    public const string COPYRIGHT = _("Copyright 2009-2014 Yorba Foundation"); +    public const string COPYRIGHT = _("Copyright 2009-2015 Yorba Foundation");      public const string APP_GETTEXT_PACKAGE = GETTEXT_PACKAGE;      public const string HOME_URL = "https://wiki.gnome.org/Apps/Shotwell"; @@ -73,7 +73,7 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string CROP = "shotwell-crop";      public const string STRAIGHTEN = "shotwell-straighten";      public const string REDEYE = "shotwell-redeye"; -    public const string ADJUST = "shotwell-adjust"; +    public const string ADJUST = "image-adjust";      public const string PIN_TOOLBAR = "shotwell-pin-toolbar";      public const string MAKE_PRIMARY = "shotwell-make-primary";      public const string IMPORT = "shotwell-import"; @@ -82,6 +82,9 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string CROP_PIVOT_RETICLE = "shotwell-crop-pivot-reticle";      public const string PUBLISH = "applications-internet";      public const string MERGE = "shotwell-merge-events"; +     +    public const string GO_NEXT = "go-next"; +    public const string GO_PREVIOUS = "go-previous";      public const string ICON_APP = "shotwell.svg";      public const string ICON_APP16 = "shotwell-16.svg"; @@ -117,8 +120,7 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string ICON_NO_EVENT = "no-event";      public const string ICON_ONE_TAG = "one-tag";      public const string ICON_TAGS = "multiple-tags"; -    public const string ICON_FOLDER_CLOSED = "folder"; -    public const string ICON_FOLDER_OPEN = "folder-open"; +    public const string ICON_FOLDER = "folder";      public const string ICON_FOLDER_DOCUMENTS = "folder-documents";      public const string ICON_IMPORTING = "go-down";      public const string ICON_LAST_IMPORT = "document-open-recent"; @@ -155,6 +157,37 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string VFLIP_MENU = _("Flip Verti_cally");      public const string VFLIP_LABEL = _("Flip Vertically"); +    public const string ABOUT_LABEL = _("_About"); +    public const string APPLY_LABEL = _("_Apply"); +    public const string CANCEL_LABEL = _("_Cancel"); +    public const string DELETE_LABEL = _("_Delete"); +    public const string EDIT_LABEL = _("_Edit"); +    public const string FORWARD_LABEL = _("_Forward"); +    public const string FULLSCREEN_LABEL = _("Fulls_creen"); +    public const string HELP_LABEL = _("_Help"); +    public const string LEAVE_FULLSCREEN_LABEL = _("Leave _Fullscreen"); +    public const string NEW_LABEL = _("_New"); +    public const string NEXT_LABEL = _("_Next"); +    public const string OK_LABEL = _("_OK"); +    public const string PLAY_LABEL = _("_Play"); +    public const string PREFERENCES_LABEL = _("_Preferences"); +    public const string PREVIOUS_LABEL = _("_Previous"); +    public const string PRINT_LABEL = _("_Print"); +    public const string QUIT_LABEL = _("_Quit"); +    public const string REFRESH_LABEL = _("_Refresh"); +    public const string REMOVE_LABEL = _("_Remove"); +    public const string REVERT_TO_SAVED_LABEL = _("_Revert"); +    public const string SAVE_LABEL = _("_Save"); +    public const string SAVE_AS_LABEL = _("Save _As"); +    public const string SORT_ASCENDING_LABEL = _("Sort _Ascending"); +    public const string SORT_DESCENDING_LABEL = _("Sort _Descending"); +    public const string STOP_LABEL = _("_Stop"); +    public const string UNDELETE_LABEL = _("_Undelete"); +    public const string ZOOM_100_LABEL = _("_Normal Size"); +    public const string ZOOM_FIT_LABEL = _("Best _Fit"); +    public const string ZOOM_IN_LABEL = _("Zoom _In"); +    public const string ZOOM_OUT_LABEL = _("Zoom _Out"); +          public const string ENHANCE_MENU = _("_Enhance");      public const string ENHANCE_LABEL = _("Enhance");      public const string ENHANCE_TOOLTIP = _("Automatically improve the photo's appearance"); @@ -246,7 +279,9 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string DISPLAY_REJECTED_OR_HIGHER_TOOLTIP = _("Show all photos, including rejected");      public const string DISPLAY_UNRATED_OR_HIGHER_MENU = _("_All Photos"); +    // Button label      public const string DISPLAY_UNRATED_OR_HIGHER_LABEL = _("Show all photos"); +    // Button tooltip      public const string DISPLAY_UNRATED_OR_HIGHER_TOOLTIP = _("Show all photos");      public const string VIEW_RATINGS_MENU = _("_Ratings"); @@ -269,9 +304,11 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string PUBLISH_TOOLTIP = _("Publish to various websites");      public const string EDIT_TITLE_MENU = _("Edit _Title..."); +    // Button label      public const string EDIT_TITLE_LABEL = _("Edit Title");      public const string EDIT_COMMENT_MENU = _("Edit _Comment..."); +    // Button label      public const string EDIT_COMMENT_LABEL = _("Edit Comment");      public const string EDIT_EVENT_COMMENT_MENU = _("Edit Event _Comment..."); @@ -282,6 +319,7 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      public const string ADD_TAGS_MENU = _("Add _Tags...");      public const string ADD_TAGS_CONTEXT_MENU = _("_Add Tags..."); +    // Dialog title      public const string ADD_TAGS_TITLE = _("Add Tags");      public const string PREFERENCES_MENU = _("_Preferences"); @@ -306,14 +344,17 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,      }      public string add_tags_label(string[] names) { -        if (names.length == 1) +        if (names.length == 1) {              return _("Add Tag \"%s\"").printf(HierarchicalTagUtilities.get_basename(names[0])); -        else if (names.length == 2) +        } else if (names.length == 2) { +            // Used when adding two tags to photo(s)              return _("Add Tags \"%s\" and \"%s\"").printf( -            HierarchicalTagUtilities.get_basename(names[0]), -            HierarchicalTagUtilities.get_basename(names[1])); -        else +                HierarchicalTagUtilities.get_basename(names[0]), +                HierarchicalTagUtilities.get_basename(names[1])); +        } else { +            // Undo/Redo command name (in Edit menu)              return _("Add Tags"); +        }      }      public string delete_tag_menu(string name) { @@ -677,13 +718,11 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,          File icons_dir = AppDirs.get_resources_dir().get_child("icons");          add_stock_icon(icons_dir.get_child("crop.svg"), CROP);          add_stock_icon(icons_dir.get_child("redeye.png"), REDEYE); -        add_stock_icon(icons_dir.get_child("image-adjust.svg"), ADJUST); -        add_stock_icon(icons_dir.get_child("pin-toolbar.svg"), PIN_TOOLBAR);          add_stock_icon(icons_dir.get_child("make-primary.svg"), MAKE_PRIMARY);          add_stock_icon(icons_dir.get_child("import.svg"), IMPORT);          add_stock_icon(icons_dir.get_child("straighten.svg"), STRAIGHTEN);          add_stock_icon(icons_dir.get_child("import-all.png"), IMPORT_ALL); -        add_stock_icon(icons_dir.get_child("enhance.png"), ENHANCE); +        add_stock_icon(icons_dir.get_child("shotwell-auto-enhance.png"), ENHANCE);          add_stock_icon(icons_dir.get_child("crop-pivot-reticle.png"), CROP_PIVOT_RETICLE);          add_stock_icon(icons_dir.get_child("merge.svg"), MERGE);          add_stock_icon_from_themed_icon(new GLib.ThemedIcon(ICON_FLAGGED_PAGE), ICON_FLAGGED_PAGE); @@ -1046,97 +1085,20 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,          providers.set(widget, styler);      } -     -    public const string INSET_FRAME_STYLESHEET = -        """ .frame { -               border-style: inset; -               border-width: 1px; -           }"""; -            -    public const string SCROLL_FRAME_STYLESHEET = -        """ GtkScrolledWindow { -               border-width: 0; -               border-style: none; -               border-radius: 0; -               padding: 0; -           } -            -            .frame { -                border-width: 1px; -                border-style: inset; -            }"""; -    public const string PAGE_STYLESHEET = -        """ .frame { -               border-width: 1px; -               border-style: inset; -               border-radius: 0; -                -               padding: 0; -           }"""; -     -    public const string VIEWPORT_STYLESHEET = -        """ GtkViewport { -               border-width: 1px; -               border-style: inset; -               border-radius: 0; -               padding: 0; -           }"""; - -    public const string TOOLBAR_STYLESHEET_TEMPLATE = -        """ -             @define-color primary-bg %s; -              -            .toolbar { -                background-color: @primary-bg; -                border-width: 1px; -                border-color: shade (@primary-bg, 0.75); -                border-style: solid; -            }"""; - -    public const string SEARCH_BUTTON_STYLESHEET_TEMPLATE = -        """  -             @define-color primary-bg %s; -              -            .button { -                background-image: none; -                background-color: @primary-bg; -                border-image: none; -                border-color: shade (@primary-bg, 0.75) @primary-bg shade (@primary-bg, 0.75) @primary-bg; -                border-style: solid; -                margin: 5px; -                 -                -unico-border-gradient: none; -                -unico-outer-stroke-width: 0; -                -unico-outer-stroke-gradient: none; -                -unico-glow-radius: 0; -                -unico-inner-stroke-width: 0; -                -unico-inner-stroke-color: shade (@primary-bg, 1.1); +    public const string CUSTOM_CSS = +        """LibraryWindow { +               -GtkPaned-handle-size: 1;              } -             -            .button:prelight { -                border-style: solid; -                border-width: 1px; -                border-color: shade (@primary-bg, 1.1); -                 -                -unico-inner-stroke-color: shade (@primary-bg, 1.1); -                -unico-inner-stroke-width: 0; - -                -unico-outer-stroke-width: 1px; -                -unico-outer-stroke-color: shade (@primary-bg, 0.8); +            LibraryWindow .pane-separator { +               background-color: @borders;              } -             -            .button:active { -                background-image: none; -                background-color: shade (@primary-bg, 0.75); -                border-style: solid; -                border-width: 1px; -                border-color: shade (@primary-bg, 0.6); -                 -                -unico-outer-stroke-width: 1px; -                -unico-outer-stroke-color: shade (@primary-bg, 1.1); +            SearchFilterToolbar { +               border-width: 0 0 1px 0; +               border-style: solid; +               border-color: @borders;              }"""; -     +      public const string ONIMAGE_FONT_COLOR = "#000000";      public const string ONIMAGE_FONT_BACKGROUND = "rgba(255,255,255,0.5)";  } diff --git a/src/Screensaver.vala b/src/Screensaver.vala index d00af21..836df5b 100644 --- a/src/Screensaver.vala +++ b/src/Screensaver.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/SearchFilter.vala b/src/SearchFilter.vala index e8f0986..3fc5d8b 100644 --- a/src/SearchFilter.vala +++ b/src/SearchFilter.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -646,7 +646,8 @@ public class SearchFilterActions {      }  } -public class SearchFilterToolbar : Gtk.Toolbar { +public class SearchFilterToolbar : Gtk.Revealer { +    private Gtk.Toolbar toolbar;      private const int FILTER_BUTTON_MARGIN = 12; // the distance between icon and edge of button      private const float FILTER_ICON_STAR_SCALE = 0.65f; // changes the size of the filter icon      private const float FILTER_ICON_SCALE = 0.75f; // changes the size of the all photos icon @@ -671,10 +672,6 @@ public class SearchFilterToolbar : Gtk.Toolbar {                  add(label);              }          } -         -        public void set_color(Gdk.RGBA color) { -            label.override_color(Gtk.StateFlags.NORMAL, color); -        }      }      private class ToggleActionToolButton : Gtk.ToolItem { @@ -688,8 +685,8 @@ public class SearchFilterToolbar : Gtk.Toolbar {              button.set_active(action.active);              button.clicked.connect(on_button_activate);              button.set_has_tooltip(true); - -            restyle(); +            button.set_relief(Gtk.ReliefStyle.NONE); +            button.set_margin_start(2);              this.add(button);          } @@ -711,21 +708,13 @@ public class SearchFilterToolbar : Gtk.Toolbar {              button.set_image(image);          } -         -        public void restyle() { -            string bgcolorname = -                Resources.to_css_color(Config.Facade.get_instance().get_bg_color()); -            string stylesheet = Resources.SEARCH_BUTTON_STYLESHEET_TEMPLATE.printf(bgcolorname); -             -            Resources.style_widget(button, stylesheet); -        }      }      // Ticket #3260 - Add a 'close' context menu to      // the searchbar.      // The close menu. Populated below in the constructor.      private Gtk.Menu close_menu = new Gtk.Menu(); -    private Gtk.ImageMenuItem close_item = new Gtk.ImageMenuItem.from_stock(Gtk.Stock.CLOSE, null); +    private Gtk.MenuItem close_item = new Gtk.MenuItem();      // Text search box.      protected class SearchBox : Gtk.ToolItem { @@ -812,10 +801,10 @@ public class SearchFilterToolbar : Gtk.Toolbar {              button = new Gtk.Button();              button.set_image(get_filter_icon(RatingFilter.UNRATED_OR_HIGHER));              button.set_can_focus(false); +            button.set_relief(Gtk.ReliefStyle.NONE); +            button.set_margin_start(2);              button.clicked.connect(on_clicked); - -            restyle();              set_homogeneous(false); @@ -911,14 +900,6 @@ public class SearchFilterToolbar : Gtk.Toolbar {          private int get_filter_button_size(RatingFilter filter) {              return get_filter_icon_size(filter) + 2 * FILTER_BUTTON_MARGIN;          } - -        public void restyle() { -            string bgcolorname = -                Resources.to_css_color(Config.Facade.get_instance().get_bg_color()); -            string stylesheet = Resources.SEARCH_BUTTON_STYLESHEET_TEMPLATE.printf(bgcolorname); -             -            Resources.style_widget(button, stylesheet); -        }      }      public Gtk.UIManager ui = new Gtk.UIManager(); @@ -939,11 +920,12 @@ public class SearchFilterToolbar : Gtk.Toolbar {      public SearchFilterToolbar(SearchFilterActions actions) {          this.actions = actions; +        toolbar = new Gtk.Toolbar();          actions.media_context_changed.connect(on_media_context_changed);          search_box = new SearchBox(actions.text); -        set_name("search-filter-toolbar"); -        set_icon_size(Gtk.IconSize.SMALL_TOOLBAR); +        toolbar.set_name("search-filter-toolbar"); +        toolbar.set_icon_size(Gtk.IconSize.SMALL_TOOLBAR);          File ui_file = Resources.get_ui("search_bar.ui");          try { @@ -960,14 +942,14 @@ public class SearchFilterToolbar : Gtk.Toolbar {          // Prepare the close menu for use, but don't          // display it yet; we'll connect it to secondary          // click later on. -        ((Gtk.MenuItem) close_item).show(); -        close_item.always_show_image = true; +        close_item.set_label(_("Close")); +        close_item.show();          close_item.activate.connect(on_context_menu_close_chosen);          close_menu.append(close_item);          // Type label and toggles          label_type = new LabelToolItem(_("Type"), 10, 5); -        insert(label_type, -1); +        toolbar.insert(label_type, -1);          toolbtn_photos = new ToggleActionToolButton(actions.photos);          toolbtn_photos.set_tooltip_text(actions.get_action_group().get_action("CommonDisplayPhotos").tooltip); @@ -978,47 +960,45 @@ public class SearchFilterToolbar : Gtk.Toolbar {          toolbtn_raw = new ToggleActionToolButton(actions.raw);          toolbtn_raw.set_tooltip_text(actions.get_action_group().get_action("CommonDisplayRaw").tooltip); -        insert(toolbtn_photos, -1); -        insert(toolbtn_videos, -1); -        insert(toolbtn_raw, -1); +        toolbar.insert(toolbtn_photos, -1); +        toolbar.insert(toolbtn_videos, -1); +        toolbar.insert(toolbtn_raw, -1);          // separator          sepr_mediatype_flagged = new Gtk.SeparatorToolItem(); -        insert(sepr_mediatype_flagged, -1); +        toolbar.insert(sepr_mediatype_flagged, -1);          // Flagged label and toggle          label_flagged = new LabelToolItem(_("Flagged")); -        insert(label_flagged, -1); +        toolbar.insert(label_flagged, -1);          toolbtn_flag = new ToggleActionToolButton(actions.flagged);          toolbtn_flag.set_tooltip_text(actions.get_action_group().get_action("CommonDisplayFlagged").tooltip); -        insert(toolbtn_flag, -1); +        toolbar.insert(toolbtn_flag, -1);          // separator          sepr_flagged_rating = new Gtk.SeparatorToolItem(); -        insert(sepr_flagged_rating, -1); +        toolbar.insert(sepr_flagged_rating, -1);          // Rating label and button          label_rating = new LabelToolItem(_("Rating")); -        insert(label_rating, -1); +        toolbar.insert(label_rating, -1);          rating_button.filter_popup = (Gtk.Menu) ui.get_widget("/FilterPopupMenu");          rating_button.set_expand(false);          rating_button.clicked.connect(on_filter_button_clicked); -        insert(rating_button, -1); +        toolbar.insert(rating_button, -1);          // Separator to right-align the text box          Gtk.SeparatorToolItem separator_align = new Gtk.SeparatorToolItem();          separator_align.set_expand(true);          separator_align.set_draw(false); -        insert(separator_align, -1); +        toolbar.insert(separator_align, -1);          // Search box. -        insert(search_box, -1); -         -        // Set background color of toolbar and update them when the configuration is updated -        Config.Facade.get_instance().bg_color_name_changed.connect(on_bg_color_name_changed); -        on_bg_color_name_changed(); +        toolbar.insert(search_box, -1); + +        add(toolbar);          // hook up signals to actions to be notified when they change          actions.flagged_toggled.connect(on_flagged_toggled); @@ -1030,14 +1010,13 @@ public class SearchFilterToolbar : Gtk.Toolbar {          actions.criteria_changed.connect(on_criteria_changed);          // #3260 part II Hook up close menu. -        popup_context_menu.connect(on_context_menu_requested); +        toolbar.popup_context_menu.connect(on_context_menu_requested);          on_media_context_changed(actions.get_has_photos(), actions.get_has_videos(),              actions.get_has_raw(), actions.get_has_flagged());      }      ~SearchFilterToolbar() { -        Config.Facade.get_instance().bg_color_name_changed.disconnect(on_bg_color_name_changed);          actions.media_context_changed.disconnect(on_media_context_changed); @@ -1049,7 +1028,7 @@ public class SearchFilterToolbar : Gtk.Toolbar {          actions.text_changed.disconnect(on_search_text_changed);          actions.criteria_changed.disconnect(on_criteria_changed); -        popup_context_menu.disconnect(on_context_menu_requested);  +        toolbar.popup_context_menu.disconnect(on_context_menu_requested);       }      private void on_media_context_changed(bool has_photos, bool has_videos, bool has_raw, @@ -1075,24 +1054,6 @@ public class SearchFilterToolbar : Gtk.Toolbar {              toolbtn_flag.set_icon_name(Resources.ICON_FILTER_FLAGGED_DISABLED);      } -    private void on_bg_color_name_changed() { -        string bgcolorname = -            Resources.to_css_color(Config.Facade.get_instance().get_bg_color()); -        string toolbar_stylesheet = Resources.TOOLBAR_STYLESHEET_TEMPLATE.printf(bgcolorname); -        Resources.style_widget(this, toolbar_stylesheet); -         -        label_type.set_color(Config.Facade.get_instance().get_unselected_color()); -        label_flagged.set_color(Config.Facade.get_instance().get_unselected_color()); -        label_rating.set_color(Config.Facade.get_instance().get_unselected_color()); -         -        toolbtn_photos.restyle(); -        toolbtn_videos.restyle(); -        toolbtn_raw.restyle(); -        toolbtn_flag.restyle(); -        rating_button.restyle(); -         -    } -          // Ticket #3260 part IV - display the context menu on secondary click      private bool on_context_menu_requested(int x, int y, int button) {           close_menu.popup(null, null, null, button, Gtk.get_current_event_time());  diff --git a/src/SlideshowPage.vala b/src/SlideshowPage.vala index f22fd53..654576d 100644 --- a/src/SlideshowPage.vala +++ b/src/SlideshowPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -44,8 +44,8 @@ class SlideshowPage : SinglePhotoPage {              set_modal(true);              set_transient_for(AppWindow.get_fullscreen()); -            add_buttons(Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,  -                Gtk.Stock.OK, Gtk.ResponseType.OK); +            add_buttons(Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL,  +                Resources.OK_LABEL, Gtk.ResponseType.OK);              set_title(_("Settings"));              Gtk.Adjustment adjustment = new Gtk.Adjustment(delay, Config.Facade.SLIDESHOW_DELAY_MIN, Config.Facade.SLIDESHOW_DELAY_MAX, 0.1, 1, 0); @@ -157,28 +157,29 @@ class SlideshowPage : SinglePhotoPage {          Gtk.Toolbar toolbar = get_toolbar();          // add toolbar buttons -        Gtk.ToolButton previous_button = new Gtk.ToolButton.from_stock(Gtk.Stock.GO_BACK); -        previous_button.set_label(_("Back")); +        Gtk.ToolButton previous_button = new Gtk.ToolButton(null, _("Back")); +        previous_button.set_icon_name("go-previous");          previous_button.set_tooltip_text(_("Go to the previous photo"));          previous_button.clicked.connect(on_previous_photo);          toolbar.insert(previous_button, -1); -        play_pause_button = new Gtk.ToolButton.from_stock(Gtk.Stock.MEDIA_PAUSE); -        play_pause_button.set_label(_("Pause")); +        play_pause_button = new Gtk.ToolButton(null, _("Pause")); +        play_pause_button.set_icon_name("media-playback-pause");          play_pause_button.set_tooltip_text(_("Pause the slideshow"));          play_pause_button.clicked.connect(on_play_pause);          toolbar.insert(play_pause_button, -1); -        Gtk.ToolButton next_button = new Gtk.ToolButton.from_stock(Gtk.Stock.GO_FORWARD); -        next_button.set_label(_("Next")); +        Gtk.ToolButton next_button = new Gtk.ToolButton(null, _("Next")); +        next_button.set_icon_name("go-next");          next_button.set_tooltip_text(_("Go to the next photo"));          next_button.clicked.connect(on_next_photo);          toolbar.insert(next_button, -1); -        settings_button = new Gtk.ToolButton.from_stock(Gtk.Stock.PREFERENCES); +        settings_button = new Gtk.ToolButton(null, null); +        settings_button.set_icon_name("preferences-system");          settings_button.set_label(_("Settings"));          settings_button.set_tooltip_text(_("Change slideshow settings"));          settings_button.clicked.connect(on_change_settings); @@ -265,11 +266,11 @@ class SlideshowPage : SinglePhotoPage {      private void on_play_pause() {          if (playing) { -            play_pause_button.set_stock_id(Gtk.Stock.MEDIA_PLAY); +            play_pause_button.set_icon_name("media-playback-start");              play_pause_button.set_label(_("Play"));              play_pause_button.set_tooltip_text(_("Continue the slideshow"));          } else { -            play_pause_button.set_stock_id(Gtk.Stock.MEDIA_PAUSE); +            play_pause_button.set_icon_name("media-playback-pause");              play_pause_button.set_label(_("Pause"));              play_pause_button.set_tooltip_text(_("Pause the slideshow"));          } diff --git a/src/SortedList.vala b/src/SortedList.vala index 791f9e0..ed8313f 100644 --- a/src/SortedList.vala +++ b/src/SortedList.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/Tag.vala b/src/Tag.vala index 450af20..8218a88 100644 --- a/src/Tag.vala +++ b/src/Tag.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/Thumbnail.vala b/src/Thumbnail.vala index c33d43b..4ce9e81 100644 --- a/src/Thumbnail.vala +++ b/src/Thumbnail.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -161,8 +161,7 @@ public class Thumbnail : MediaSourceItem {      }      public static int64 title_ascending_comparator(void *a, void *b) { -        int64 result = strcmp(((Thumbnail *) a)->media.get_name(), ((Thumbnail *) b)->media.get_name()); -         +        int64 result = strcmp(((Thumbnail *) a)->get_natural_collation_key(), ((Thumbnail *) b)->get_natural_collation_key());          return (result != 0) ? result : photo_id_ascending_comparator(a, b);      } @@ -194,6 +193,10 @@ public class Thumbnail : MediaSourceItem {          return alteration.has_detail("metadata", "exposure-time");      } +    public static bool filename_comparator_predicate(DataObject object, Alteration alteration) { +        return alteration.has_detail("metadata", "filename"); +    } +      public static int64 filename_ascending_comparator(void *a, void *b) {          string path_a = ((Thumbnail *) a)->media.get_file().get_basename().down();          string path_b = ((Thumbnail *) b)->media.get_file().get_basename().down(); diff --git a/src/ThumbnailCache.vala b/src/ThumbnailCache.vala index c24087c..6408a1a 100644 --- a/src/ThumbnailCache.vala +++ b/src/ThumbnailCache.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -86,6 +86,7 @@ public class ThumbnailCache : Object {          public Gdk.Pixbuf scaled = null;          public Error err = null;          public bool fetched = false; +        public bool replace = false;          public AsyncFetchJob(ThumbnailCache cache, string thumbnail_name,              ThumbnailSource source, Gdk.Pixbuf? prefetched, Dimensions dim, @@ -131,38 +132,33 @@ public class ThumbnailCache : Object {                  // scale if specified                  scaled = dim.has_area() ? resize_pixbuf(unscaled, dim, interp) : unscaled;              } catch (Error err) { -                // Is the problem that the thumbnail couldn't be read? If so, it's recoverable; -                // we'll just create it and leave this.err as null if creation works.                  if (err is FileError) {                      try { -                        Photo photo = source as Photo; -                        Video video = source as Video; - -                        if (photo != null) { -                            unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true)); -                            photo.notify_altered(new Alteration("image","thumbnail")); -                            return; -                        } - -                        if (video != null) { -                            unscaled = video.create_thumbnail(dim.width); -                            scaled = resize_pixbuf(unscaled, dim, interp); -                            cache.save_thumbnail(cache.get_source_cached_file(source), -                                unscaled, source); -                            replace(source, cache.size, unscaled); -                            return; -                        } - -                    } catch (Error e) { -                        // Creating the thumbnail failed; tell the rest of the app. -                        this.err = e; -                        return; +                        generate_thumbnail(); +                    } catch (Error generr) { +                        // save thumbnail generation error, not original, for processing in callback +                        err = generr;                      } +                } else { +                    // save error for processing in callback +                    this.err = err;                  } - -                // ...the original error wasn't from reading the file, but something else; -                // tell the rest of the app. -                this.err = err; +            } +        } +         +        private void generate_thumbnail() throws Error { +            Photo? photo = source as Photo; +            if (photo != null) { +                unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true)); +            } else { +                Video? video = source as Video; +                if (video != null) +                    unscaled = video.create_thumbnail(dim.width); +            } +             +            if (unscaled != null) { +                scaled = resize_pixbuf(unscaled, dim, interp); +                replace = true;              }          }      } @@ -420,6 +416,16 @@ public class ThumbnailCache : Object {      private static void async_fetch_completion_callback(BackgroundJob background_job) {          AsyncFetchJob job = (AsyncFetchJob) background_job; +        // Is the problem that the thumbnail couldn't be read? If so, it's recoverable; +        // we'll just create it and leave this.err as null if creation works. +        if (job.replace && job.unscaled != null) { +            try { +                replace(job.source, job.cache.size, job.unscaled); +            } catch (Error err) { +                job.err = err; +            } +        } +                  if (job.unscaled != null) {              if (job.fetched) {                  // only store in cache if fetched, not pre-fetched diff --git a/src/TimedQueue.vala b/src/TimedQueue.vala index 7001421..d175c8d 100644 --- a/src/TimedQueue.vala +++ b/src/TimedQueue.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/Tombstone.vala b/src/Tombstone.vala index d25b979..6a95881 100644 --- a/src/Tombstone.vala +++ b/src/Tombstone.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/UnityProgressBar.vala b/src/UnityProgressBar.vala index fcf36bc..d28428e 100644 --- a/src/UnityProgressBar.vala +++ b/src/UnityProgressBar.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/Upgrades.vala b/src/Upgrades.vala index 7fef59a..d7ccf6f 100644 --- a/src/Upgrades.vala +++ b/src/Upgrades.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/VideoMetadata.vala b/src/VideoMetadata.vala index 100a040..5dfa812 100644 --- a/src/VideoMetadata.vala +++ b/src/VideoMetadata.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/VideoMonitor.vala b/src/VideoMonitor.vala index f062999..7f2fd3b 100644 --- a/src/VideoMonitor.vala +++ b/src/VideoMonitor.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/VideoSupport.vala b/src/VideoSupport.vala index e23ba37..4e6f3ed 100644 --- a/src/VideoSupport.vala +++ b/src/VideoSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -197,8 +197,11 @@ public class VideoReader {              // (and the corresponding output struct) in order to implement #2836.              Date? video_date = null;              if (info.get_tags() != null && info.get_tags().get_date(Gst.Tags.DATE, out video_date)) { -                timestamp = new DateTime.local(video_date.get_year(), video_date.get_month(),  -                    video_date.get_day(), 0, 0, 0); +                // possible for get_date() to return true and a null Date +                if (video_date != null) { +                    timestamp = new DateTime.local(video_date.get_year(), video_date.get_month(), +                        video_date.get_day(), 0, 0, 0); +                }              }          } catch (Error e) {              debug("Video read error: %s", e.message); diff --git a/src/camera/Branch.vala b/src/camera/Branch.vala index 63a5443..83f3f56 100644 --- a/src/camera/Branch.vala +++ b/src/camera/Branch.vala @@ -1,17 +1,17 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */  public class Camera.Branch : Sidebar.Branch { -    internal static Icon? cameras_icon = null; +    internal static string? cameras_icon = Resources.ICON_CAMERAS;      private Gee.HashMap<DiscoveredCamera, Camera.SidebarEntry> camera_map = new Gee.HashMap<          DiscoveredCamera, Camera.SidebarEntry>();      public Branch() { -        base (new Camera.Grouping(), +        base (new Camera.Header(),              Sidebar.Branch.Options.HIDE_IF_EMPTY | Sidebar.Branch.Options.AUTO_OPEN_ON_NEW_CHILD,              camera_comparator); @@ -23,11 +23,9 @@ public class Camera.Branch : Sidebar.Branch {      }      internal static void init() { -        cameras_icon = new GLib.ThemedIcon(Resources.ICON_CAMERAS);      }      internal static void terminate() { -        cameras_icon = null;      }      private static int camera_comparator(Sidebar.Entry a, Sidebar.Entry b) { @@ -82,9 +80,9 @@ public class Camera.Branch : Sidebar.Branch {      }  } -public class Camera.Grouping : Sidebar.Grouping { -    public Grouping() { -        base (_("Cameras"), Camera.Branch.cameras_icon); +public class Camera.Header : Sidebar.Header { +    public Header() { +        base (_("Cameras"));      }  } @@ -101,7 +99,7 @@ public class Camera.SidebarEntry : Sidebar.SimplePageEntry {          return camera.display_name ?? _("Camera");      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return camera.icon ?? Camera.Branch.cameras_icon;      } diff --git a/src/camera/Camera.vala b/src/camera/Camera.vala index f6d1f4b..84fff8e 100644 --- a/src/camera/Camera.vala +++ b/src/camera/Camera.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/camera/CameraTable.vala b/src/camera/CameraTable.vala index 8466388..bdeac54 100644 --- a/src/camera/CameraTable.vala +++ b/src/camera/CameraTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. @@ -8,9 +8,9 @@ public class DiscoveredCamera {      public GPhoto.Camera gcamera;      public string uri;      public string display_name; -    public GLib.Icon? icon; +    public string? icon; -    public DiscoveredCamera(GPhoto.Camera gcamera, string uri, string display_name, GLib.Icon? icon) { +    public DiscoveredCamera(GPhoto.Camera gcamera, string uri, string display_name, string? icon) {          this.gcamera = gcamera;          this.uri = uri;          this.display_name = display_name; @@ -221,10 +221,10 @@ public class CameraTable {          return null;      } -    private GLib.Icon? get_icon_for_uuid(string uuid) { +    private string? get_icon_for_uuid(string uuid) {          foreach (Volume volume in volume_monitor.get_volumes()) {              if (volume.get_identifier(VolumeIdentifier.UUID) == uuid) { -                return volume.get_icon(); +                return volume.get_icon().to_string();              }          }          return null; @@ -323,7 +323,7 @@ public class CameraTable {          foreach (string port in detected_map.keys) {              string name = detected_map.get(port);              string display_name = null; -            GLib.Icon? icon = null; +            string? icon = null;              string uri = get_port_uri(port);              if (camera_map.has_key(uri)) { diff --git a/src/camera/GPhoto.vala b/src/camera/GPhoto.vala index a1a46cb..41af0b2 100644 --- a/src/camera/GPhoto.vala +++ b/src/camera/GPhoto.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/camera/ImportPage.vala b/src/camera/ImportPage.vala index 823a458..ba66990 100644 --- a/src/camera/ImportPage.vala +++ b/src/camera/ImportPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -289,7 +289,7 @@ class ImportPreview : MediaSourceItem {          bool using_placeholder = (pixbuf == null);          if (pixbuf == null) {              if (placeholder_preview == null) { -                placeholder_preview = AppWindow.get_instance().render_icon(Gtk.Stock.MISSING_IMAGE,  +                placeholder_preview = AppWindow.get_instance().render_icon("image-missing",                       Gtk.IconSize.DIALOG, null);                  placeholder_preview = scale_pixbuf(placeholder_preview, MAX_SCALE,                      Gdk.InterpType.BILINEAR, true); @@ -691,7 +691,7 @@ public class ImportPage : CheckerboardPage {      private string camera_name;      private VolumeMonitor volume_monitor = null;      private ImportPage? local_ref = null; -    private GLib.Icon? icon; +    private string? icon;      private ImportPageSearchViewFilter search_filter = new ImportPageSearchViewFilter();      private HideImportedViewFilter hide_imported_filter = new HideImportedViewFilter();      private CameraViewTracker tracker; @@ -707,7 +707,7 @@ public class ImportPage : CheckerboardPage {          LIBRARY_ERROR      } -    public ImportPage(GPhoto.Camera camera, string uri, string? display_name = null, GLib.Icon? icon = null) { +    public ImportPage(GPhoto.Camera camera, string uri, string? display_name = null, string? icon = null) {          base(_("Camera"));          this.camera = camera;          this.uri = uri; @@ -810,13 +810,15 @@ public class ImportPage : CheckerboardPage {              toolbar.insert(new Gtk.SeparatorToolItem(), -1);              // Import selected -            Gtk.ToolButton import_selected_button = new Gtk.ToolButton.from_stock(Resources.IMPORT); +            Gtk.ToolButton import_selected_button = new Gtk.ToolButton(null, null); +            import_selected_button.set_icon_name(Resources.IMPORT);              import_selected_button.set_related_action(get_action("ImportSelected"));              toolbar.insert(import_selected_button, -1);              // Import all -            Gtk.ToolButton import_all_button = new Gtk.ToolButton.from_stock(Resources.IMPORT_ALL); +            Gtk.ToolButton import_all_button = new Gtk.ToolButton(null, null); +            import_all_button.set_icon_name(Resources.IMPORT_ALL);              import_all_button.set_related_action(get_action("ImportAll"));              toolbar.insert(import_all_button, -1); @@ -1736,7 +1738,7 @@ public class ImportPage : CheckerboardPage {                  photos_string, videos_string, both_string, neither_string);              ImportUI.QuestionParams question = new ImportUI.QuestionParams( -                question_string, Gtk.Stock.DELETE, _("_Keep")); +                question_string, Resources.DELETE_LABEL, _("_Keep"));              if (!ImportUI.report_manifest(manifest, false, question))                  return; diff --git a/src/config/Config.vala b/src/config/Config.vala index 2095107..588c466 100644 --- a/src/config/Config.vala +++ b/src/config/Config.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/config/ConfigurationInterfaces.vala b/src/config/ConfigurationInterfaces.vala index 42a591a..41ae188 100644 --- a/src/config/ConfigurationInterfaces.vala +++ b/src/config/ConfigurationInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/config/GSettingsEngine.vala b/src/config/GSettingsEngine.vala index 0b2e691..1586684 100644 --- a/src/config/GSettingsEngine.vala +++ b/src/config/GSettingsEngine.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/core/Alteration.vala b/src/core/Alteration.vala index 865be84..ecb8142 100644 --- a/src/core/Alteration.vala +++ b/src/core/Alteration.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/ContainerSourceCollection.vala b/src/core/ContainerSourceCollection.vala index 655cfa0..24e2d89 100644 --- a/src/core/ContainerSourceCollection.vala +++ b/src/core/ContainerSourceCollection.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/Core.vala b/src/core/Core.vala index 1b9958e..b646f02 100644 --- a/src/core/Core.vala +++ b/src/core/Core.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DataCollection.vala b/src/core/DataCollection.vala index 615c6ac..0e8041d 100644 --- a/src/core/DataCollection.vala +++ b/src/core/DataCollection.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/core/DataObject.vala b/src/core/DataObject.vala index 1fe133d..85ec63f 100644 --- a/src/core/DataObject.vala +++ b/src/core/DataObject.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/core/DataSet.vala b/src/core/DataSet.vala index ebb5500..dc11422 100644 --- a/src/core/DataSet.vala +++ b/src/core/DataSet.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DataSource.vala b/src/core/DataSource.vala index e4d2d34..514ef9b 100644 --- a/src/core/DataSource.vala +++ b/src/core/DataSource.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DataSourceTypes.vala b/src/core/DataSourceTypes.vala index 9f23ac6..f7ebec1 100644 --- a/src/core/DataSourceTypes.vala +++ b/src/core/DataSourceTypes.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DataView.vala b/src/core/DataView.vala index 07cd4fc..c70b9b4 100644 --- a/src/core/DataView.vala +++ b/src/core/DataView.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DataViewTypes.vala b/src/core/DataViewTypes.vala index fac7602..fe7bffd 100644 --- a/src/core/DataViewTypes.vala +++ b/src/core/DataViewTypes.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/DatabaseSourceCollection.vala b/src/core/DatabaseSourceCollection.vala index 0c704bb..917c50d 100644 --- a/src/core/DatabaseSourceCollection.vala +++ b/src/core/DatabaseSourceCollection.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/SourceCollection.vala b/src/core/SourceCollection.vala index 020df0e..9e2af57 100644 --- a/src/core/SourceCollection.vala +++ b/src/core/SourceCollection.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/SourceHoldingTank.vala b/src/core/SourceHoldingTank.vala index adfec8b..a3fb1c6 100644 --- a/src/core/SourceHoldingTank.vala +++ b/src/core/SourceHoldingTank.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/SourceInterfaces.vala b/src/core/SourceInterfaces.vala index 59956d3..958e4b3 100644 --- a/src/core/SourceInterfaces.vala +++ b/src/core/SourceInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/Tracker.vala b/src/core/Tracker.vala index e72992b..3f5d39a 100644 --- a/src/core/Tracker.vala +++ b/src/core/Tracker.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/ViewCollection.vala b/src/core/ViewCollection.vala index a34e23e..5577681 100644 --- a/src/core/ViewCollection.vala +++ b/src/core/ViewCollection.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/core/util.vala b/src/core/util.vala index 1846380..0460454 100644 --- a/src/core/util.vala +++ b/src/core/util.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/data_imports/DataImportJob.vala b/src/data_imports/DataImportJob.vala index b27997c..df5aebe 100644 --- a/src/data_imports/DataImportJob.vala +++ b/src/data_imports/DataImportJob.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -157,6 +157,10 @@ public class DataImportJob : BatchImportJob {          string? title = src_photo.get_title();          if (title != null)              photo.set_title(title); +        // exposure time +        time_t? date_time = src_photo.get_exposure_time(); +        if (date_time != null) +            photo.set_exposure_time(date_time);          // import ID          photo.set_import_id(import_roll.import_id); diff --git a/src/data_imports/DataImportSource.vala b/src/data_imports/DataImportSource.vala index d7e8ec8..f60c06d 100644 --- a/src/data_imports/DataImportSource.vala +++ b/src/data_imports/DataImportSource.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -48,9 +48,16 @@ public class DataImportSource {                  warning("Could not get file metadata for %s: %s", get_filename(), e.message);                  metadata = null;              } -             -            title = (metadata != null) ? metadata.get_title() : null; -            exposure_time = (metadata != null) ? metadata.get_exposure_date_time() : null; +            title = db_photo.get_title(); +            if (title == null) { +                title = (metadata != null) ? metadata.get_title() : null; +            } +            time_t? date_time = db_photo.get_exposure_time(); +            if (date_time != null) { +                exposure_time = new MetadataDateTime(date_time); +            } else { +                exposure_time = (metadata != null) ? metadata.get_exposure_date_time() : null; +            }              PhotoPreview? preview = metadata != null ? metadata.get_preview(0) : null;              if (preview != null) {                  try { diff --git a/src/data_imports/DataImports.vala b/src/data_imports/DataImports.vala index 72c8b4d..1406d71 100644 --- a/src/data_imports/DataImports.vala +++ b/src/data_imports/DataImports.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/data_imports/DataImportsPluginHost.vala b/src/data_imports/DataImportsPluginHost.vala index f92bc53..f783e1f 100644 --- a/src/data_imports/DataImportsPluginHost.vala +++ b/src/data_imports/DataImportsPluginHost.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/data_imports/DataImportsUI.vala b/src/data_imports/DataImportsUI.vala index 9b171b1..7b975a7 100644 --- a/src/data_imports/DataImportsUI.vala +++ b/src/data_imports/DataImportsUI.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -202,19 +202,19 @@ public class DataImportsDialog : Gtk.Dialog {      public const int STANDARD_ACTION_BUTTON_WIDTH = 128;      private Gtk.ComboBoxText service_selector_box; -    private Gtk.Label service_selector_box_label;      private Gtk.Box central_area_layouter;      private Gtk.Button close_cancel_button;      private Spit.DataImports.DialogPane active_pane;      private Spit.DataImports.ConcreteDataImportsHost host;      protected DataImportsDialog() { +        Object(use_header_bar: 1); +        ((Gtk.HeaderBar) get_header_bar()).set_show_close_button(false);          resizable = false;          delete_event.connect(on_window_close);          string title = _("Import From Application"); -        string label = _("Import media _from:");          set_title(title); @@ -225,9 +225,6 @@ public class DataImportsDialog : Gtk.Dialog {              // service to select from              service_selector_box = new Gtk.ComboBoxText();              service_selector_box.set_active(0); -            service_selector_box_label = new Gtk.Label.with_mnemonic(label); -            service_selector_box_label.set_mnemonic_widget(service_selector_box); -            service_selector_box_label.set_alignment(0.0f, 0.5f);              // get the name of the service the user last used              string? last_used_service = Config.Facade.get_instance().get_last_used_dataimports_service(); @@ -248,30 +245,6 @@ public class DataImportsDialog : Gtk.Dialog {                  service_selector_box.set_active(0);              service_selector_box.changed.connect(on_service_changed); - -            /* the wrapper is not an extraneous widget -- it's necessary to prevent the service -               selection box from growing and shrinking whenever its parent's size changes. -               When wrapped inside a Gtk.Alignment, the Alignment grows and shrinks instead of -               the service selection box. */ -            Gtk.Alignment service_selector_box_wrapper = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f); -            service_selector_box_wrapper.add(service_selector_box); - -            Gtk.Box service_selector_layouter = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); -            service_selector_layouter.set_border_width(12); -            service_selector_layouter.add(service_selector_box_label); -            service_selector_layouter.pack_start(service_selector_box_wrapper, true, true, 0); -             -            /* 'service area' is the selector assembly plus the horizontal rule dividing it from the -               rest of the dialog */ -            Gtk.Box service_area_layouter = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); -            service_area_layouter.pack_start(service_selector_layouter, true, true, 0); -            Gtk.Separator service_central_separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL); -            service_area_layouter.add(service_central_separator); -             -            Gtk.Alignment service_area_wrapper = new Gtk.Alignment(0.0f, 0.0f, 1.0f, 0.0f); -            service_area_wrapper.add(service_area_layouter); - -            ((Gtk.Box) get_content_area()).pack_start(service_area_wrapper, false, false, 0);          }          // Intall the central area in all cases @@ -281,7 +254,9 @@ public class DataImportsDialog : Gtk.Dialog {          close_cancel_button = new Gtk.Button.with_mnemonic("_Cancel");          close_cancel_button.set_can_default(true);          close_cancel_button.clicked.connect(on_close_cancel_clicked); -        ((Gtk.Box) get_action_area()).add(close_cancel_button); + +        ((Gtk.HeaderBar) get_header_bar()).pack_start(close_cancel_button); +        ((Gtk.HeaderBar) get_header_bar()).pack_end(service_selector_box);          set_standard_window_mode(); diff --git a/src/db/DatabaseTable.vala b/src/db/DatabaseTable.vala index 55d440d..235ac06 100644 --- a/src/db/DatabaseTable.vala +++ b/src/db/DatabaseTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/db/Db.vala b/src/db/Db.vala index ced530a..c6b69d9 100644 --- a/src/db/Db.vala +++ b/src/db/Db.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/EventTable.vala b/src/db/EventTable.vala index 016fa00..04310b8 100644 --- a/src/db/EventTable.vala +++ b/src/db/EventTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/PhotoTable.vala b/src/db/PhotoTable.vala index 9891fe6..21a8d5e 100644 --- a/src/db/PhotoTable.vala +++ b/src/db/PhotoTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/SavedSearchDBTable.vala b/src/db/SavedSearchDBTable.vala index d986038..9baab4e 100644 --- a/src/db/SavedSearchDBTable.vala +++ b/src/db/SavedSearchDBTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/TagTable.vala b/src/db/TagTable.vala index a0fade8..05b2daa 100644 --- a/src/db/TagTable.vala +++ b/src/db/TagTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/TombstoneTable.vala b/src/db/TombstoneTable.vala index 9e108bd..861cba4 100644 --- a/src/db/TombstoneTable.vala +++ b/src/db/TombstoneTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/VersionTable.vala b/src/db/VersionTable.vala index 9003b1b..3711b83 100644 --- a/src/db/VersionTable.vala +++ b/src/db/VersionTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/db/VideoTable.vala b/src/db/VideoTable.vala index c681dc2..bd45750 100644 --- a/src/db/VideoTable.vala +++ b/src/db/VideoTable.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/direct/Direct.vala b/src/direct/Direct.vala index dd2a847..59680b1 100644 --- a/src/direct/Direct.vala +++ b/src/direct/Direct.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/direct/DirectPhoto.vala b/src/direct/DirectPhoto.vala index f7271ba..9cd86f9 100644 --- a/src/direct/DirectPhoto.vala +++ b/src/direct/DirectPhoto.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. diff --git a/src/direct/DirectPhotoPage.vala b/src/direct/DirectPhotoPage.vala index 4dfd520..58d82fc 100644 --- a/src/direct/DirectPhotoPage.vala +++ b/src/direct/DirectPhotoPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. @@ -46,13 +46,13 @@ public class DirectPhotoPage : EditingHostPage {          file.label = _("_File");          actions += file; -        Gtk.ActionEntry save = { "Save", Gtk.Stock.SAVE, TRANSLATABLE, "<Ctrl>S", TRANSLATABLE, +        Gtk.ActionEntry save = { "Save", Resources.SAVE_LABEL, TRANSLATABLE, "<Ctrl>S", TRANSLATABLE,              on_save };          save.label = _("_Save");          save.tooltip = _("Save photo");          actions += save; -        Gtk.ActionEntry save_as = { "SaveAs", Gtk.Stock.SAVE_AS, TRANSLATABLE, +        Gtk.ActionEntry save_as = { "SaveAs", Resources.SAVE_AS_LABEL, TRANSLATABLE,              "<Ctrl><Shift>S", TRANSLATABLE, on_save_as };          save_as.label = _("Save _As...");          save_as.tooltip = _("Save photo with a different name"); @@ -63,7 +63,7 @@ public class DirectPhotoPage : EditingHostPage {          send_to.label = Resources.SEND_TO_MENU;          actions += send_to; -        Gtk.ActionEntry print = { "Print", Gtk.Stock.PRINT, TRANSLATABLE, "<Ctrl>P", +        Gtk.ActionEntry print = { "Print", Resources.PRINT_LABEL, TRANSLATABLE, "<Ctrl>P",              TRANSLATABLE, on_print };          print.label = Resources.PRINT_MENU;          print.tooltip = _("Print the photo to a printer connected to your computer"); @@ -81,13 +81,13 @@ public class DirectPhotoPage : EditingHostPage {          tools.label = _("T_ools");          actions += tools; -        Gtk.ActionEntry prev = { "PrevPhoto", Gtk.Stock.GO_BACK, TRANSLATABLE, null, +        Gtk.ActionEntry prev = { "PrevPhoto", Resources.PREVIOUS_LABEL, TRANSLATABLE, null,              TRANSLATABLE, on_previous_photo };          prev.label = _("_Previous Photo");          prev.tooltip = _("Previous Photo");          actions += prev; -        Gtk.ActionEntry next = { "NextPhoto", Gtk.Stock.GO_FORWARD, TRANSLATABLE, null, +        Gtk.ActionEntry next = { "NextPhoto", Resources.NEXT_LABEL, TRANSLATABLE, null,              TRANSLATABLE, on_next_photo };          next.label = _("_Next Photo");          next.tooltip = _("Next Photo"); @@ -127,7 +127,7 @@ public class DirectPhotoPage : EditingHostPage {          crop.tooltip = Resources.CROP_TOOLTIP;          actions += crop; -        Gtk.ActionEntry straighten = { "Straighten", Gtk.Stock.REFRESH, TRANSLATABLE, "<Ctrl>A", +        Gtk.ActionEntry straighten = { "Straighten", Resources.REFRESH_LABEL, TRANSLATABLE, "<Ctrl>A",              TRANSLATABLE, toggle_straighten };          straighten.label = Resources.STRAIGHTEN_MENU;          straighten.tooltip = Resources.STRAIGHTEN_TOOLTIP; @@ -145,7 +145,7 @@ public class DirectPhotoPage : EditingHostPage {          adjust.tooltip = Resources.ADJUST_TOOLTIP;          actions += adjust; -        Gtk.ActionEntry revert = { "Revert", Gtk.Stock.REVERT_TO_SAVED, TRANSLATABLE, +        Gtk.ActionEntry revert = { "Revert", Resources.REVERT_LABEL, TRANSLATABLE,              null, TRANSLATABLE, on_revert };          revert.label = Resources.REVERT_MENU;          actions += revert; @@ -169,25 +169,25 @@ public class DirectPhotoPage : EditingHostPage {          help.label = _("_Help");          actions += help; -        Gtk.ActionEntry increase_size = { "IncreaseSize", Gtk.Stock.ZOOM_IN, TRANSLATABLE, +        Gtk.ActionEntry increase_size = { "IncreaseSize", Resources.ZOOM_IN_LABEL, TRANSLATABLE,              "<Ctrl>plus", TRANSLATABLE, on_increase_size };          increase_size.label = _("Zoom _In");          increase_size.tooltip = _("Increase the magnification of the photo");          actions += increase_size; -        Gtk.ActionEntry decrease_size = { "DecreaseSize", Gtk.Stock.ZOOM_OUT, TRANSLATABLE, +        Gtk.ActionEntry decrease_size = { "DecreaseSize", Resources.ZOOM_OUT_LABEL, TRANSLATABLE,              "<Ctrl>minus", TRANSLATABLE, on_decrease_size };          decrease_size.label = _("Zoom _Out");          decrease_size.tooltip = _("Decrease the magnification of the photo");          actions += decrease_size; -        Gtk.ActionEntry best_fit = { "ZoomFit", Gtk.Stock.ZOOM_FIT, TRANSLATABLE, +        Gtk.ActionEntry best_fit = { "ZoomFit", Resources.ZOOM_FIT_LABEL, TRANSLATABLE,              "<Ctrl>0", TRANSLATABLE, snap_zoom_to_min };          best_fit.label = _("Fit to _Page");          best_fit.tooltip = _("Zoom the photo to fit on the screen");          actions += best_fit; -        Gtk.ActionEntry actual_size = { "Zoom100", Gtk.Stock.ZOOM_100, TRANSLATABLE, +        Gtk.ActionEntry actual_size = { "Zoom100", Resources.ZOOM_100_LABEL, TRANSLATABLE,              "<Ctrl>1", TRANSLATABLE, snap_zoom_to_isomorphic };          /// xgettext:no-c-format          actual_size.label = _("Zoom _100%"); @@ -324,10 +324,15 @@ public class DirectPhotoPage : EditingHostPage {      }      protected override bool on_double_click(Gdk.EventButton event) { -        AppWindow.get_instance().end_fullscreen(); +        FullscreenWindow? fs = get_container() as FullscreenWindow; +        if (fs != null) { +            fs.close(); +             +            return true; +        }          return base.on_double_click(event); -    }     +    }      protected override void update_ui(bool missing) {          bool sensitivity = !missing; @@ -501,8 +506,8 @@ public class DirectPhotoPage : EditingHostPage {          }          Gtk.FileChooserDialog save_as_dialog = new Gtk.FileChooserDialog(_("Save As"),  -            AppWindow.get_instance(), Gtk.FileChooserAction.SAVE, Gtk.Stock.CANCEL,  -            Gtk.ResponseType.CANCEL, Gtk.Stock.OK, Gtk.ResponseType.OK); +            AppWindow.get_instance(), Gtk.FileChooserAction.SAVE, Resources.CANCEL_LABEL,  +            Gtk.ResponseType.CANCEL, Resources.OK_LABEL, Gtk.ResponseType.OK);          save_as_dialog.set_select_multiple(false);          save_as_dialog.set_current_name(filename);          save_as_dialog.set_current_folder(current_save_dir.get_path()); diff --git a/src/direct/DirectView.vala b/src/direct/DirectView.vala index a36ec68..6f37850 100644 --- a/src/direct/DirectView.vala +++ b/src/direct/DirectView.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/direct/DirectWindow.vala b/src/direct/DirectWindow.vala index b339ac4..35729b7 100644 --- a/src/direct/DirectWindow.vala +++ b/src/direct/DirectWindow.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/editing_tools/EditingTools.vala b/src/editing_tools/EditingTools.vala index f5fb144..6c91011 100644 --- a/src/editing_tools/EditingTools.vala +++ b/src/editing_tools/EditingTools.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -647,7 +647,7 @@ public class CropTool : EditingTool {          private const int CONTROL_SPACING = 8;          public Gtk.Button ok_button = new Gtk.Button.with_label(Resources.CROP_LABEL); -        public Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL); +        public Gtk.Button cancel_button = new Gtk.Button.with_mnemonic(Resources.CANCEL_LABEL);          public Gtk.ComboBox constraint_combo;          public Gtk.Button pivot_reticle_button = new Gtk.Button();          public Gtk.Entry custom_width_entry = new Gtk.Entry(); @@ -1890,9 +1890,9 @@ public class RedeyeTool : EditingTool {          private Gtk.Label slider_label = new Gtk.Label.with_mnemonic(_("Size:"));          public Gtk.Button apply_button = -            new Gtk.Button.from_stock(Gtk.Stock.APPLY); +            new Gtk.Button.with_mnemonic(Resources.APPLY_LABEL);          public Gtk.Button close_button = -            new Gtk.Button.from_stock(Gtk.Stock.CLOSE); +            new Gtk.Button.with_mnemonic(Resources.CANCEL_LABEL);          public Gtk.Scale slider = new Gtk.Scale.with_range(Gtk.Orientation.HORIZONTAL,              RedeyeInstance.MIN_RADIUS, RedeyeInstance.MAX_RADIUS, 1.0); @@ -2240,9 +2240,9 @@ public class AdjustTool : EditingTool {              HighlightDetailTransformation.MIN_PARAMETER, HighlightDetailTransformation.MAX_PARAMETER,              1.0); -        public Gtk.Button ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK); +        public Gtk.Button ok_button = new Gtk.Button.with_mnemonic(Resources.OK_LABEL);          public Gtk.Button reset_button = new Gtk.Button.with_mnemonic(_("_Reset")); -        public Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL); +        public Gtk.Button cancel_button = new Gtk.Button.with_mnemonic(Resources.CANCEL_LABEL);          public RGBHistogramManipulator histogram_manipulator = new RGBHistogramManipulator();          public AdjustToolWindow(Gtk.Window container) { diff --git a/src/editing_tools/StraightenTool.vala b/src/editing_tools/StraightenTool.vala index 8a778ec..e2b117e 100644 --- a/src/editing_tools/StraightenTool.vala +++ b/src/editing_tools/StraightenTool.vala @@ -1,5 +1,5 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. @@ -98,7 +98,7 @@ public class StraightenTool : EditingTool {          public Gtk.Label angle_label = new Gtk.Label("");          public Gtk.Label description_label = new Gtk.Label(_("Angle:"));          public Gtk.Button ok_button = new Gtk.Button.with_mnemonic(_("_Straighten")); -        public Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL); +        public Gtk.Button cancel_button = new Gtk.Button.with_mnemonic(Resources.CANCEL_LABEL);          public Gtk.Button reset_button = new Gtk.Button.with_mnemonic(_("_Reset"));          /** diff --git a/src/events/Branch.vala b/src/events/Branch.vala index e1b5221..1093411 100644 --- a/src/events/Branch.vala +++ b/src/events/Branch.vala @@ -1,15 +1,14 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */  public class Events.Branch : Sidebar.Branch { -    internal static Icon open_icon; -    internal static Icon closed_icon; -    internal static Icon events_icon; -    internal static Icon single_event_icon; -    internal static Icon no_event_icon; +    internal static string icon = Resources.ICON_FOLDER; +    internal static string events_icon = Resources.ICON_EVENTS; +    internal static string single_event_icon = Resources.ICON_ONE_EVENT; +    internal static string no_event_icon = Resources.ICON_NO_EVENT;      // NOTE: Because the comparators must be static methods (due to CompareFunc's stupid impl.)      // and there's an assumption that only one Events.Branch is ever created, this is a static @@ -20,11 +19,14 @@ public class Events.Branch : Sidebar.Branch {          Event, Events.EventEntry>();      private Events.UndatedDirectoryEntry undated_entry = new Events.UndatedDirectoryEntry();      private Events.NoEventEntry no_event_entry = new Events.NoEventEntry(); +    private Events.MasterDirectoryEntry all_events_entry = new Events.MasterDirectoryEntry();      public Branch() { -        base (new Events.MasterDirectoryEntry(), Sidebar.Branch.Options.STARTUP_EXPAND_TO_FIRST_CHILD, +        base (new Sidebar.Header(_("Events")), Sidebar.Branch.Options.STARTUP_EXPAND_TO_FIRST_CHILD,              event_year_comparator); +        graft(get_root(), all_events_entry); +                  // seed the branch          foreach (DataObject object in Event.global.get_all())              add_event((Event) object); @@ -49,25 +51,18 @@ public class Events.Branch : Sidebar.Branch {      }      internal static void init() { -        open_icon = new ThemedIcon(Resources.ICON_FOLDER_OPEN); -        closed_icon = new ThemedIcon(Resources.ICON_FOLDER_CLOSED); -        events_icon = new ThemedIcon(Resources.ICON_EVENTS); -        single_event_icon = new ThemedIcon(Resources.ICON_ONE_EVENT); -        no_event_icon = new ThemedIcon(Resources.ICON_NO_EVENT); -                  sort_ascending = Config.Facade.get_instance().get_events_sort_ascending();      }      internal static void terminate() { -        open_icon = null; -        closed_icon = null; -        events_icon = null; -        single_event_icon = null; -        no_event_icon = null; +    } +     +    public bool is_user_renameable() { +        return true;      }      public Events.MasterDirectoryEntry get_master_entry() { -        return (Events.MasterDirectoryEntry) get_root(); +        return all_events_entry;      }      private static int event_year_comparator(Sidebar.Entry a, Sidebar.Entry b) { @@ -91,6 +86,12 @@ public class Events.Branch : Sidebar.Branch {          else if (b is Events.NoEventEntry)              return -1; +        // The All events entry should always appear on top +        if (a is Events.MasterDirectoryEntry) +            return -1; +        else if (b is Events.MasterDirectoryEntry) +            return 1; +                  if (!sort_ascending) {              Sidebar.Entry swap = a;              a = b; @@ -312,7 +313,8 @@ public class Events.Branch : Sidebar.Branch {          int event_year = event_tm.year + 1900;          return find_first_child(get_root(), (entry) => { -            if ((entry is Events.UndatedDirectoryEntry) || (entry is Events.NoEventEntry)) +            if ((entry is Events.UndatedDirectoryEntry) || (entry is Events.NoEventEntry) ||  +                 entry is Events.MasterDirectoryEntry)                  return false;              else                  return ((Events.YearDirectoryEntry) entry).get_year() == event_year; @@ -334,11 +336,11 @@ public class Events.Branch : Sidebar.Branch {      }      private void graft_event(Sidebar.Entry parent, Event event, -        owned CompareDataFunc<Sidebar.Entry>? comparator = null) { +        owned CompareFunc<Sidebar.Entry>? comparator = null) {          Events.EventEntry entry = new Events.EventEntry(event);          entry_map.set(event, entry); -        graft(parent, entry, (owned) comparator); +        graft(parent, entry, comparator);      }      private void reparent_event(Event event, Sidebar.Entry new_parent) { @@ -372,16 +374,8 @@ public abstract class Events.DirectoryEntry : Sidebar.SimplePageEntry, Sidebar.E      public DirectoryEntry() {      } -    public override Icon? get_sidebar_icon() { -        return null; -    } -     -    public virtual Icon? get_sidebar_open_icon() { -        return Events.Branch.open_icon; -    } -     -    public virtual Icon? get_sidebar_closed_icon() { -        return Events.Branch.closed_icon; +    public override string? get_sidebar_icon() { +        return Events.Branch.icon;      }      public bool expand_on_select() { @@ -397,15 +391,7 @@ public class Events.MasterDirectoryEntry : Events.DirectoryEntry {          return MasterEventsDirectoryPage.NAME;      } -    public override Icon? get_sidebar_icon() { -        return Events.Branch.events_icon; -    } -     -    public override Icon? get_sidebar_open_icon() { -        return Events.Branch.events_icon; -    } -     -    public override Icon? get_sidebar_closed_icon() { +    public override string? get_sidebar_icon() {          return Events.Branch.events_icon;      } @@ -492,7 +478,7 @@ public class Events.EventEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr          return event.get_name();      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return Events.Branch.single_event_icon;      } @@ -500,6 +486,10 @@ public class Events.EventEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr          return new EventPage(event);      } +    public bool is_user_renameable() { +        return true; +    } +          public void rename(string new_name) {          string? prepped = Event.prep_event_name(new_name);          if (prepped != null) @@ -523,6 +513,7 @@ public class Events.EventEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr      }  } +  public class Events.NoEventEntry : Sidebar.SimplePageEntry {      public NoEventEntry() {      } @@ -531,7 +522,7 @@ public class Events.NoEventEntry : Sidebar.SimplePageEntry {          return NoEventPage.NAME;      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return Events.Branch.no_event_icon;      } diff --git a/src/events/EventDirectoryItem.vala b/src/events/EventDirectoryItem.vala index 5b2026b..d3434c2 100644 --- a/src/events/EventDirectoryItem.vala +++ b/src/events/EventDirectoryItem.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/events/EventPage.vala b/src/events/EventPage.vala index 3d23f25..ed103a8 100644 --- a/src/events/EventPage.vala +++ b/src/events/EventPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. diff --git a/src/events/Events.vala b/src/events/Events.vala index dc2b662..f93e33c 100644 --- a/src/events/Events.vala +++ b/src/events/Events.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/events/EventsDirectoryPage.vala b/src/events/EventsDirectoryPage.vala index 41a1ac6..99601a0 100644 --- a/src/events/EventsDirectoryPage.vala +++ b/src/events/EventsDirectoryPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -227,7 +227,7 @@ public abstract class EventsDirectoryPage : CheckerboardPage {  }  public class MasterEventsDirectoryPage : EventsDirectoryPage { -    public const string NAME = _("Events"); +    public const string NAME = _("All Events");      public MasterEventsDirectoryPage() {          base (NAME, new EventDirectoryManager(), (Gee.Collection<Event>) Event.global.get_all()); diff --git a/src/folders/Branch.vala b/src/folders/Branch.vala index bc5b578..0904e5c 100644 --- a/src/folders/Branch.vala +++ b/src/folders/Branch.vala @@ -1,4 +1,4 @@ -/* Copyright 2012-2014 Yorba Foundation +/* Copyright 2012-2015 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. @@ -136,9 +136,9 @@ public class Folders.Branch : Sidebar.Branch {      }  } -private class Folders.Root : Sidebar.Grouping { +private class Folders.Root : Sidebar.Header {      public Root() { -        base (_("Folders"), Folders.opened_icon, Folders.closed_icon); +        base (_("Folders"));      }  } @@ -172,22 +172,14 @@ public class Folders.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.ExpandableE          return dir.get_basename();      } -    public override Icon? get_sidebar_icon() { -        return count == 0 ? closed_icon : have_photos_icon; +    public override string? get_sidebar_icon() { +        return count == 0 ? icon : have_photos_icon;      }      public override string to_string() {          return dir.get_path();      } -    public Icon? get_sidebar_open_icon() { -        return count == 0 ? opened_icon : have_photos_icon; -    } -     -    public Icon? get_sidebar_closed_icon() { -        return count == 0 ? closed_icon : have_photos_icon; -    } -          public bool expand_on_select() {          return true;      } diff --git a/src/folders/Folders.vala b/src/folders/Folders.vala index 1cc14b1..da6f817 100644 --- a/src/folders/Folders.vala +++ b/src/folders/Folders.vala @@ -1,4 +1,4 @@ -/* Copyright 2012-2014 Yorba Foundation +/* Copyright 2012-2015 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. @@ -15,19 +15,16 @@  namespace Folders { -static Icon? opened_icon = null; -static Icon? closed_icon = null; -static Icon? have_photos_icon = null; +static string? icon = null; +static string? have_photos_icon = null;  public void init() throws Error { -    opened_icon = new ThemedIcon(Resources.ICON_FOLDER_OPEN); -    closed_icon = new ThemedIcon(Resources.ICON_FOLDER_CLOSED); -    have_photos_icon = new ThemedIcon(Resources.ICON_FOLDER_DOCUMENTS); +    icon = Resources.ICON_FOLDER; +    have_photos_icon = Resources.ICON_FOLDER_DOCUMENTS;  }  public void terminate() { -    opened_icon = null; -    closed_icon = null; +    icon = null;      have_photos_icon = null;  } diff --git a/src/folders/Page.vala b/src/folders/Page.vala index d101e88..eb3a84f 100644 --- a/src/folders/Page.vala +++ b/src/folders/Page.vala @@ -1,4 +1,4 @@ -/* Copyright 2012-2014 Yorba Foundation +/* Copyright 2012-2015 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. diff --git a/src/library/Branch.vala b/src/library/Branch.vala index dc05d60..0e875d2 100644 --- a/src/library/Branch.vala +++ b/src/library/Branch.vala @@ -1,31 +1,104 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.Branch : Sidebar.RootOnlyBranch { +public class Library.Branch : Sidebar.Branch { +    private const string POSITION_DATA = "x-photos-entry-position"; + +    public Library.PhotosEntry photos_entry { get; private set; } +    public Library.FlaggedSidebarEntry flagged_entry { get; private set; } +    public Library.LastImportSidebarEntry last_imported_entry { get; private set; } +    public Library.ImportQueueSidebarEntry import_queue_entry { get; private set; } +    public Library.OfflineSidebarEntry offline_entry { get; private set; } +    public Library.TrashSidebarEntry trash_entry { get; private set; } +     +    // This lists the order of the library items in the sidebar. To re-order, simply move +    // the item in this list to a new position. These numbers should *not* persist anywhere +    // outside the app. +    private enum EntryPosition { +        PHOTOS, +        FLAGGED, +        LAST_IMPORTED, +        IMPORT_QUEUE, +        OFFLINE, +        TRASH +    } +          public Branch() { -        base (new Library.SidebarEntry()); +        base(new Sidebar.Header(_("Library")), +            Sidebar.Branch.Options.STARTUP_OPEN_GROUPING, comparator); + +        photos_entry = new Library.PhotosEntry(); +        trash_entry = new Library.TrashSidebarEntry(); +        last_imported_entry = new Library.LastImportSidebarEntry(); +        flagged_entry = new Library.FlaggedSidebarEntry(); +        offline_entry = new Library.OfflineSidebarEntry(); +        import_queue_entry = new Library.ImportQueueSidebarEntry(); + +        insert(photos_entry, EntryPosition.PHOTOS); +        insert(trash_entry, EntryPosition.TRASH); + +        flagged_entry.visibility_changed.connect(on_flagged_visibility_changed); +        on_flagged_visibility_changed(); + +        last_imported_entry.visibility_changed.connect(on_last_imported_visibility_changed); +        on_last_imported_visibility_changed(); + +        import_queue_entry.visibility_changed.connect(on_import_queue_visibility_changed); +        on_import_queue_visibility_changed(); + +        offline_entry.visibility_changed.connect(on_offline_visibility_changed); +        on_offline_visibility_changed();      } -    public Library.MainPage get_main_page() { -        return (Library.MainPage) ((Library.SidebarEntry) get_root()).get_page(); +    private void insert(Sidebar.Entry entry, int position) { +        entry.set_data<int>(POSITION_DATA, position); +        graft(get_root(), entry); +    } + +    private void on_flagged_visibility_changed() { +        update_entry_visibility(flagged_entry, EntryPosition.FLAGGED); +    } + +    private void on_last_imported_visibility_changed() { +        update_entry_visibility(last_imported_entry, EntryPosition.LAST_IMPORTED); +    } + +    private void on_import_queue_visibility_changed() { +        update_entry_visibility(import_queue_entry, EntryPosition.IMPORT_QUEUE); +    } + +    private void on_offline_visibility_changed() { +        update_entry_visibility(offline_entry, EntryPosition.OFFLINE); +    } + +    private void update_entry_visibility(Library.HideablePageEntry entry, int position) { +        if (entry.visible) { +            if (!has_entry(entry)) +                insert(entry, position); +        } else if (has_entry(entry)) { +            prune(entry); +        } +    } + +    private static int comparator(Sidebar.Entry a, Sidebar.Entry b) { +        return a.get_data<int>(POSITION_DATA) - b.get_data<int>(POSITION_DATA);      }  } -public class Library.SidebarEntry : Sidebar.SimplePageEntry { -    private Icon icon = new ThemedIcon(Resources.ICON_PHOTOS); +public class Library.PhotosEntry : Sidebar.SimplePageEntry { -    public SidebarEntry() { +    public PhotosEntry() {      }      public override string get_sidebar_name() { -        return Library.MainPage.NAME; +        return _("Photos");      } -    public override Icon? get_sidebar_icon() { -        return icon; +    public override string? get_sidebar_icon() { +        return Resources.ICON_PHOTOS;      }      protected override Page create_page() { @@ -33,6 +106,26 @@ public class Library.SidebarEntry : Sidebar.SimplePageEntry {      }  } +public abstract class Library.HideablePageEntry : Sidebar.SimplePageEntry { +    // container branch should listen to this signal +    public signal void visibility_changed(bool visible); + +    private bool show_entry = false; +    public bool visible { +        get { return show_entry; } +        set { +            if (value == show_entry) +                return; + +            show_entry = value; +            visibility_changed(value); +        } +    } + +    public HideablePageEntry() { +    } +} +  public class Library.MainPage : CollectionPage {      public const string NAME = _("Library"); diff --git a/src/library/FlaggedPage.vala b/src/library/FlaggedPage.vala index 28bc57b..b45cc54 100644 --- a/src/library/FlaggedPage.vala +++ b/src/library/FlaggedPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/library/FlaggedBranch.vala b/src/library/FlaggedSidebarEntry.vala index 472d999..240aaf3 100644 --- a/src/library/FlaggedBranch.vala +++ b/src/library/FlaggedSidebarEntry.vala @@ -1,47 +1,28 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.FlaggedBranch : Sidebar.RootOnlyBranch { -    public FlaggedBranch() { -        base (new Library.FlaggedSidebarEntry()); -         +public class Library.FlaggedSidebarEntry : Library.HideablePageEntry, Sidebar.InternalDropTargetEntry { +    public FlaggedSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.flagged_contents_altered.connect(on_flagged_contents_altered); -        set_show_branch(get_total_flagged() != 0); +        visible = (get_total_flagged() != 0);      } -    ~FlaggedBranch() { +    ~FlaggedSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.flagged_contents_altered.disconnect(on_flagged_contents_altered); -    } -     -    private void on_flagged_contents_altered() { -        set_show_branch(get_total_flagged() != 0); -    } -     -    private int get_total_flagged() { -        int total = 0; -        foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all()) -            total += media_sources.get_flagged().size; -         -        return total; -    } -} - -public class Library.FlaggedSidebarEntry : Sidebar.SimplePageEntry, Sidebar.InternalDropTargetEntry { -    public FlaggedSidebarEntry() { -    } -     +    }  +             public override string get_sidebar_name() {          return FlaggedPage.NAME;      } -    public override Icon? get_sidebar_icon() { -        return new ThemedIcon(Resources.ICON_FLAGGED_PAGE); +    public override string? get_sidebar_icon() { +        return Resources.ICON_FLAGGED_PAGE;      }      protected override Page create_page() { @@ -57,5 +38,17 @@ public class Library.FlaggedSidebarEntry : Sidebar.SimplePageEntry, Sidebar.Inte      public bool internal_drop_received_arbitrary(Gtk.SelectionData data) {          return false;      } + +    private void on_flagged_contents_altered() { +        visible = (get_total_flagged() != 0); +    } +     +    private int get_total_flagged() { +        int total = 0; +        foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all()) +            total += media_sources.get_flagged().size; +         +        return total; +    }  } diff --git a/src/library/ImportQueuePage.vala b/src/library/ImportQueuePage.vala index 5ace1d8..9886f5a 100644 --- a/src/library/ImportQueuePage.vala +++ b/src/library/ImportQueuePage.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. @@ -28,7 +28,8 @@ public class ImportQueuePage : SinglePhotoPage {          Gtk.Toolbar toolbar = get_toolbar();          // Stop button -        Gtk.ToolButton stop_button = new Gtk.ToolButton.from_stock(Gtk.Stock.STOP); +        Gtk.ToolButton stop_button = new Gtk.ToolButton(null, null); +        stop_button.set_icon_name("stop");          stop_button.set_related_action(get_action("Stop"));          toolbar.insert(stop_button, -1); @@ -61,7 +62,7 @@ public class ImportQueuePage : SinglePhotoPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry stop = { "Stop", Gtk.Stock.STOP, TRANSLATABLE, null, TRANSLATABLE, +        Gtk.ActionEntry stop = { "Stop", Resources.STOP_LABEL, TRANSLATABLE, null, TRANSLATABLE,              on_stop };          stop.label = _("_Stop Import");          stop.tooltip = _("Stop importing photos"); diff --git a/src/library/ImportQueueBranch.vala b/src/library/ImportQueueSidebarEntry.vala index 32a3e0d..5d34ce2 100644 --- a/src/library/ImportQueueBranch.vala +++ b/src/library/ImportQueueSidebarEntry.vala @@ -1,38 +1,37 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.ImportQueueBranch : Sidebar.RootOnlyBranch { -    private Library.ImportQueueSidebarEntry entry; -     -    public ImportQueueBranch() { -        // can't pass to base() an object that was allocated in declaration; see -        // https://bugzilla.gnome.org/show_bug.cgi?id=646286 -        base (new Library.ImportQueueSidebarEntry()); -         -        entry = (Library.ImportQueueSidebarEntry) get_root(); -         +public class Library.ImportQueueSidebarEntry : Library.HideablePageEntry { +    public ImportQueueSidebarEntry() {          // only attach signals to the page when it's created -        entry.page_created.connect(on_page_created); -        entry.destroying_page.connect(on_destroying_page); +        page_created.connect(on_page_created); +        destroying_page.connect(on_destroying_page);          // don't use entry.get_page() or get_queue_page() because (a) we don't want to          // create the page during initialization, and (b) we know there's no import activity          // at this moment -        set_show_branch(false); +        visible = false;      } -    ~ImportQueueBranch() { -        entry.page_created.disconnect(on_page_created); -        entry.destroying_page.disconnect(on_destroying_page); +    public override string get_sidebar_name() { +        return ImportQueuePage.NAME;      } -    public ImportQueuePage get_queue_page() { -        return (ImportQueuePage) entry.get_page(); +    public override string? get_sidebar_icon() { +        return Resources.ICON_IMPORTING;      } +    protected override Page create_page() { +        return new ImportQueuePage(); +    } + +    private ImportQueuePage get_queue_page() { +        return get_page() as ImportQueuePage; +    } +      private void on_page_created() {          get_queue_page().batch_added.connect(on_batch_added_or_removed);          get_queue_page().batch_removed.connect(on_batch_added_or_removed); @@ -44,31 +43,14 @@ public class Library.ImportQueueBranch : Sidebar.RootOnlyBranch {      }      private void on_batch_added_or_removed() { -        set_show_branch(get_queue_page().get_batch_count() > 0); +        visible = (get_queue_page().get_batch_count() > 0);      }      public void enqueue_and_schedule(BatchImport batch_import, bool allow_user_cancel) {          // want to display the branch before passing to the page because this might result in the          // page being created, and want it all hooked up in the tree prior to creating the page -        set_show_branch(true); +        visible = true;          get_queue_page().enqueue_and_schedule(batch_import, allow_user_cancel);      }  } -public class Library.ImportQueueSidebarEntry : Sidebar.SimplePageEntry { -    public ImportQueueSidebarEntry() { -    } -     -    public override string get_sidebar_name() { -        return ImportQueuePage.NAME; -    } -     -    public override Icon? get_sidebar_icon() { -        return new ThemedIcon(Resources.ICON_IMPORTING); -    } -     -    protected override Page create_page() { -        return new ImportQueuePage(); -    } -} - diff --git a/src/library/LastImportPage.vala b/src/library/LastImportPage.vala index 877faa5..ea9045c 100644 --- a/src/library/LastImportPage.vala +++ b/src/library/LastImportPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/library/LastImportBranch.vala b/src/library/LastImportSidebarEntry.vala index bc03ee5..3414130 100644 --- a/src/library/LastImportBranch.vala +++ b/src/library/LastImportSidebarEntry.vala @@ -1,47 +1,36 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.LastImportBranch : Sidebar.RootOnlyBranch { -    public LastImportBranch() { -        base (new Library.LastImportSidebarEntry()); -         +public class Library.LastImportSidebarEntry : Library.HideablePageEntry { +    public LastImportSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.import_roll_altered.connect(on_import_rolls_altered); -        set_show_branch(MediaCollectionRegistry.get_instance().get_last_import_id() != null); +        visible = (MediaCollectionRegistry.get_instance().get_last_import_id() != null);      } -    ~LastImportBranch() { +    ~LastImportSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.import_roll_altered.disconnect(on_import_rolls_altered);      } -    public Library.LastImportSidebarEntry get_main_entry() { -        return (Library.LastImportSidebarEntry) get_root(); -    } -     -    private void on_import_rolls_altered() { -        set_show_branch(MediaCollectionRegistry.get_instance().get_last_import_id() != null); -    } -} - -public class Library.LastImportSidebarEntry : Sidebar.SimplePageEntry { -    public LastImportSidebarEntry() { -    } -          public override string get_sidebar_name() {          return LastImportPage.NAME;      } -    public override Icon? get_sidebar_icon() { -        return new ThemedIcon(Resources.ICON_LAST_IMPORT); +    public override string? get_sidebar_icon() { +        return Resources.ICON_LAST_IMPORT;      }      protected override Page create_page() {          return new LastImportPage();      } + +    private void on_import_rolls_altered() { +        visible = (MediaCollectionRegistry.get_instance().get_last_import_id() != null); +    }  } diff --git a/src/library/Library.vala b/src/library/Library.vala index 79a4880..272f3d2 100644 --- a/src/library/Library.vala +++ b/src/library/Library.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/library/LibraryWindow.vala b/src/library/LibraryWindow.vala index dab1f6f..a756436 100644 --- a/src/library/LibraryWindow.vala +++ b/src/library/LibraryWindow.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. @@ -42,16 +42,11 @@ public class LibraryWindow : AppWindow {      // outside the app.      private enum SidebarRootPosition {          LIBRARY, -        FLAGGED, -        LAST_IMPORTED,          CAMERAS, -        IMPORT_QUEUE,          SAVED_SEARCH,          EVENTS,          FOLDERS, -        TAGS, -        TRASH, -        OFFLINE +        TAGS      }      public enum TargetType { @@ -114,12 +109,7 @@ public class LibraryWindow : AppWindow {      private Library.Branch library_branch = new Library.Branch();      private Tags.Branch tags_branch = new Tags.Branch();      private Folders.Branch folders_branch = new Folders.Branch(); -    private Library.TrashBranch trash_branch = new Library.TrashBranch();      private Events.Branch events_branch = new Events.Branch(); -    private Library.OfflineBranch offline_branch = new Library.OfflineBranch(); -    private Library.FlaggedBranch flagged_branch = new Library.FlaggedBranch(); -    private Library.LastImportBranch last_import_branch = new Library.LastImportBranch(); -    private Library.ImportQueueBranch import_queue_branch = new Library.ImportQueueBranch();      private Camera.Branch camera_branch = new Camera.Branch();      private Searches.Branch saved_search_branch = new Searches.Branch();      private bool page_switching_enabled = true; @@ -172,12 +162,7 @@ public class LibraryWindow : AppWindow {          sidebar_tree.graft(library_branch, SidebarRootPosition.LIBRARY);          sidebar_tree.graft(tags_branch, SidebarRootPosition.TAGS);          sidebar_tree.graft(folders_branch, SidebarRootPosition.FOLDERS); -        sidebar_tree.graft(trash_branch, SidebarRootPosition.TRASH);          sidebar_tree.graft(events_branch, SidebarRootPosition.EVENTS); -        sidebar_tree.graft(offline_branch, SidebarRootPosition.OFFLINE); -        sidebar_tree.graft(flagged_branch, SidebarRootPosition.FLAGGED); -        sidebar_tree.graft(last_import_branch, SidebarRootPosition.LAST_IMPORTED); -        sidebar_tree.graft(import_queue_branch, SidebarRootPosition.IMPORT_QUEUE);          sidebar_tree.graft(camera_branch, SidebarRootPosition.CAMERAS);          sidebar_tree.graft(saved_search_branch, SidebarRootPosition.SAVED_SEARCH); @@ -207,7 +192,7 @@ public class LibraryWindow : AppWindow {          menubar.no_show_all = true;          // create the main layout & start at the Library page -        create_layout(library_branch.get_main_page()); +        create_layout(library_branch.photos_entry.get_page());          // settings that should persist between sessions          load_configuration(); @@ -313,12 +298,12 @@ public class LibraryWindow : AppWindow {          sort.label = _("Sort _Events");          actions += sort; -        Gtk.ActionEntry preferences = { "CommonPreferences", Gtk.Stock.PREFERENCES, TRANSLATABLE, +        Gtk.ActionEntry preferences = { "CommonPreferences", Resources.PREFERENCES_LABEL, TRANSLATABLE,              null, TRANSLATABLE, on_preferences };          preferences.label = Resources.PREFERENCES_MENU;          actions += preferences; -        Gtk.ActionEntry empty = { "CommonEmptyTrash", Gtk.Stock.CLEAR, TRANSLATABLE, null, null, +        Gtk.ActionEntry empty = { "CommonEmptyTrash", null, TRANSLATABLE, null, null,              on_empty_trash };          empty.label = _("Empty T_rash");          empty.tooltip = _("Delete all photos in the trash"); @@ -329,8 +314,7 @@ public class LibraryWindow : AppWindow {          jump_to_event.label = _("View Eve_nt for Photo");          actions += jump_to_event; -        Gtk.ActionEntry find = { "CommonFind", Gtk.Stock.FIND, TRANSLATABLE, null, null, -            on_find }; +        Gtk.ActionEntry find = { "CommonFind", null, TRANSLATABLE, null, null, on_find };          find.label = _("_Find");          find.tooltip = _("Find photos and videos by search criteria");          actions += find; @@ -398,7 +382,7 @@ public class LibraryWindow : AppWindow {          extended_props.tooltip = _("Display extended information for the selection");          actions += extended_props; -        Gtk.ToggleActionEntry searchbar = { "CommonDisplaySearchbar", Gtk.Stock.FIND, TRANSLATABLE, +        Gtk.ToggleActionEntry searchbar = { "CommonDisplaySearchbar", "edit-find", TRANSLATABLE,              "F8", TRANSLATABLE, on_display_searchbar, is_search_toolbar_visible };          searchbar.label = _("_Search Bar");          searchbar.tooltip = _("Display the search bar"); @@ -417,14 +401,14 @@ public class LibraryWindow : AppWindow {          Gtk.RadioActionEntry[] actions = new Gtk.RadioActionEntry[0];          Gtk.RadioActionEntry ascending = { "CommonSortEventsAscending", -            Gtk.Stock.SORT_ASCENDING, TRANSLATABLE, null, TRANSLATABLE, +            Resources.SORT_ASCENDING_LABEL, TRANSLATABLE, null, TRANSLATABLE,              SORT_EVENTS_ORDER_ASCENDING };          ascending.label = _("_Ascending");          ascending.tooltip = _("Sort photos in an ascending order");          actions += ascending;          Gtk.RadioActionEntry descending = { "CommonSortEventsDescending", -            Gtk.Stock.SORT_DESCENDING, TRANSLATABLE, null, TRANSLATABLE, +            Resources.SORT_DESCENDING_LABEL, TRANSLATABLE, null, TRANSLATABLE,              SORT_EVENTS_ORDER_DESCENDING };          descending.label = _("D_escending");          descending.tooltip = _("Sort photos in a descending order"); @@ -666,8 +650,8 @@ public class LibraryWindow : AppWindow {      private void on_file_import() {          Gtk.FileChooserDialog import_dialog = new Gtk.FileChooserDialog(_("Import From Folder"), null, -            Gtk.FileChooserAction.SELECT_FOLDER, Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,  -            Gtk.Stock.OK, Gtk.ResponseType.OK); +            Gtk.FileChooserAction.SELECT_FOLDER, Resources.CANCEL_LABEL, Gtk.ResponseType.CANCEL,  +            Resources.OK_LABEL, Gtk.ResponseType.OK);          import_dialog.set_local_only(false);          import_dialog.set_select_multiple(true);          import_dialog.set_current_folder(import_dir); @@ -883,7 +867,7 @@ public class LibraryWindow : AppWindow {      }      public void enqueue_batch_import(BatchImport batch_import, bool allow_user_cancel) { -        import_queue_branch.enqueue_and_schedule(batch_import, allow_user_cancel); +        library_branch.import_queue_entry.enqueue_and_schedule(batch_import, allow_user_cancel);      }      private void import_reporter(ImportManifest manifest) { @@ -1029,7 +1013,7 @@ public class LibraryWindow : AppWindow {      }      public void switch_to_library_page() { -        switch_to_page(library_branch.get_main_page()); +        switch_to_page(library_branch.photos_entry.get_page());      }      public void switch_to_event(Event event) { @@ -1066,7 +1050,7 @@ public class LibraryWindow : AppWindow {      }      public void switch_to_import_queue_page() { -        switch_to_page(import_queue_branch.get_queue_page()); +        switch_to_page(library_branch.import_queue_entry.get_page());      }      private void on_camera_added(DiscoveredCamera camera) { @@ -1285,52 +1269,36 @@ public class LibraryWindow : AppWindow {          Gtk.ScrolledWindow scrolled_sidebar = new Gtk.ScrolledWindow(null, null);          scrolled_sidebar.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);          scrolled_sidebar.add(sidebar_tree); -        scrolled_sidebar.get_style_context().add_class(Gtk.STYLE_CLASS_SIDEBAR); -        scrolled_sidebar.set_shadow_type(Gtk.ShadowType.IN); -        get_style_context().add_class("sidebar-pane-separator"); -         -        // divy the sidebar up into selection tree list, background progress bar, and properties -        Gtk.Frame top_frame = new Gtk.Frame(null); -        top_frame.add(scrolled_sidebar); -        top_frame.set_shadow_type(Gtk.ShadowType.IN); +        background_progress_frame.set_border_width(2);          background_progress_frame.add(background_progress_bar); -        background_progress_frame.set_shadow_type(Gtk.ShadowType.IN); +        background_progress_frame.get_style_context().remove_class("frame");          // pad the bottom frame (properties)          Gtk.Alignment bottom_alignment = new Gtk.Alignment(0, 0.5f, 1, 0); - -        Resources.style_widget(scrolled_sidebar, Resources.SCROLL_FRAME_STYLESHEET); -        Resources.style_widget(bottom_frame, Resources.INSET_FRAME_STYLESHEET);          bottom_alignment.set_padding(10, 10, 6, 0);          bottom_alignment.add(basic_properties);          bottom_frame.add(bottom_alignment); -        bottom_frame.set_shadow_type(Gtk.ShadowType.IN); +        bottom_frame.get_style_context().remove_class("frame");          // "attach" the progress bar to the sidebar tree, so the movable ridge is to resize the          // top two and the basic information pane -        top_section.pack_start(top_frame, true, true, 0); +        top_section.pack_start(scrolled_sidebar, true, true, 0);          sidebar_paned.pack1(top_section, true, false);          sidebar_paned.pack2(bottom_frame, false, false);          sidebar_paned.set_position(1000); - -        // layout the selection tree to the left of the collection/toolbar box with an adjustable -        // gutter between them, framed for presentation -        Gtk.Frame right_frame = new Gtk.Frame(null); -        right_frame.set_shadow_type(Gtk.ShadowType.IN);          right_vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); -        right_frame.add(right_vbox);          right_vbox.pack_start(search_toolbar, false, false, 0);          right_vbox.pack_start(notebook, true, true, 0);          client_paned = new Gtk.Paned(Gtk.Orientation.HORIZONTAL);          client_paned.pack1(sidebar_paned, false, false);          sidebar_tree.set_size_request(SIDEBAR_MIN_WIDTH, -1); -        client_paned.pack2(right_frame, true, false); +        client_paned.pack2(right_vbox, true, false);          client_paned.set_position(Config.Facade.get_instance().get_sidebar_position());          // TODO: Calc according to layout's size, to give sidebar a maximum width          notebook.set_size_request(PAGE_MIN_WIDTH, -1); @@ -1436,7 +1404,7 @@ public class LibraryWindow : AppWindow {      // Turns the search bar on or off.  Note that if show is true, page must not be null.      private void toggle_search_bar(bool show, CheckerboardPage? page = null) { -        search_toolbar.visible = show; +        search_toolbar.set_reveal_child(show);          if (show) {              assert(null != page);              search_toolbar.set_view_filter(page.get_search_view_filter()); @@ -1457,7 +1425,7 @@ public class LibraryWindow : AppWindow {      private void on_destroying_page(Sidebar.PageRepresentative entry, Page page) {          // if page is the current page, switch to fallback before destroying          if (page == get_current_page()) -            switch_to_page(library_branch.get_main_page()); +            switch_to_page(library_branch.photos_entry.get_page());          remove_from_notebook(page); @@ -1475,9 +1443,11 @@ public class LibraryWindow : AppWindow {          // if the currently selected item is removed, want to jump to fallback page (which          // depends on the item that was selected) +        Library.LastImportSidebarEntry last_import_entry = library_branch.last_imported_entry; +                  // Importing... -> Last Import (if available) -        if (selectable is Library.ImportQueueSidebarEntry && last_import_branch.get_show_branch()) { -            switch_to_page(last_import_branch.get_main_entry().get_page()); +        if (selectable is Library.ImportQueueSidebarEntry && last_import_entry.visible) { +            switch_to_page(last_import_entry.get_page());              return;          } @@ -1497,7 +1467,7 @@ public class LibraryWindow : AppWindow {          }          // basic all-around default: jump to the Library page -        switch_to_page(library_branch.get_main_page()); +        switch_to_page(library_branch.photos_entry.get_page());      }      private void subscribe_for_basic_information(Page page) { diff --git a/src/library/OfflinePage.vala b/src/library/OfflinePage.vala index cb6af2d..eecd71b 100644 --- a/src/library/OfflinePage.vala +++ b/src/library/OfflinePage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. @@ -55,7 +55,7 @@ public class OfflinePage : CheckerboardPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry remove = { "RemoveFromLibrary", Gtk.Stock.REMOVE, TRANSLATABLE, "Delete", +        Gtk.ActionEntry remove = { "RemoveFromLibrary", Resources.REMOVE_LABEL, TRANSLATABLE, "Delete",              TRANSLATABLE, on_remove_from_library };          remove.label = Resources.REMOVE_FROM_LIBRARY_MENU;          remove.tooltip = Resources.DELETE_FROM_LIBRARY_TOOLTIP; diff --git a/src/library/OfflineBranch.vala b/src/library/OfflineSidebarEntry.vala index 4ed2e49..34c09a0 100644 --- a/src/library/OfflineBranch.vala +++ b/src/library/OfflineSidebarEntry.vala @@ -1,26 +1,25 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.OfflineBranch : Sidebar.RootOnlyBranch { -    public OfflineBranch() { -        base (new Library.OfflineSidebarEntry()); +public class Library.OfflineSidebarEntry : Library.HideablePageEntry { +    public OfflineSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.offline_contents_altered.connect(on_offline_contents_altered); -        set_show_branch(get_total_offline() != 0); +        visible = (get_total_offline() != 0);      } -     -    ~OfflineBranch() { + +    ~OfflineSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all())              media_sources.trashcan_contents_altered.disconnect(on_offline_contents_altered);      }      private void on_offline_contents_altered() { -        set_show_branch(get_total_offline() != 0); +        visible = (get_total_offline() != 0);      }      private int get_total_offline() { @@ -30,18 +29,13 @@ public class Library.OfflineBranch : Sidebar.RootOnlyBranch {          return total;      } -} - -public class Library.OfflineSidebarEntry : Sidebar.SimplePageEntry { -    public OfflineSidebarEntry() { -    }      public override string get_sidebar_name() {          return OfflinePage.NAME;      } -    public override Icon? get_sidebar_icon() { -        return new ThemedIcon(Resources.ICON_MISSING_FILES); +    public override string? get_sidebar_icon() { +        return Resources.ICON_MISSING_FILES;      }      protected override Page create_page() { diff --git a/src/library/TrashPage.vala b/src/library/TrashPage.vala index 2991727..ae80a7b 100644 --- a/src/library/TrashPage.vala +++ b/src/library/TrashPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. @@ -50,13 +50,13 @@ public class TrashPage : CheckerboardPage {      protected override Gtk.ActionEntry[] init_collect_action_entries() {          Gtk.ActionEntry[] actions = base.init_collect_action_entries(); -        Gtk.ActionEntry delete_action = { "Delete", Gtk.Stock.DELETE, TRANSLATABLE, "Delete", +        Gtk.ActionEntry delete_action = { "Delete", Resources.DELETE_LABEL, TRANSLATABLE, "Delete",              TRANSLATABLE, on_delete };          delete_action.label = Resources.DELETE_PHOTOS_MENU;          delete_action.tooltip = Resources.DELETE_FROM_TRASH_TOOLTIP;          actions += delete_action; -        Gtk.ActionEntry restore = { "Restore", Gtk.Stock.UNDELETE, TRANSLATABLE, null, TRANSLATABLE, +        Gtk.ActionEntry restore = { "Restore", Resources.UNDELETE_LABEL, TRANSLATABLE, null, TRANSLATABLE,              on_restore };          restore.label = Resources.RESTORE_PHOTOS_MENU;          restore.tooltip = Resources.RESTORE_PHOTOS_TOOLTIP; diff --git a/src/library/TrashBranch.vala b/src/library/TrashSidebarEntry.vala index 5ef8b3c..69412b7 100644 --- a/src/library/TrashBranch.vala +++ b/src/library/TrashSidebarEntry.vala @@ -1,18 +1,10 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */ -public class Library.TrashBranch : Sidebar.RootOnlyBranch { -    public TrashBranch() { -        base (new Library.TrashSidebarEntry()); -    } -} -  public class Library.TrashSidebarEntry : Sidebar.SimplePageEntry, Sidebar.InternalDropTargetEntry { -    private static Icon? full_icon = null; -    private static Icon? empty_icon = null;      public TrashSidebarEntry() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all()) @@ -25,30 +17,26 @@ public class Library.TrashSidebarEntry : Sidebar.SimplePageEntry, Sidebar.Intern      }      internal static void init() { -        full_icon = new ThemedIcon(Resources.ICON_TRASH_FULL); -        empty_icon = new ThemedIcon(Resources.ICON_TRASH_EMPTY);      }      internal static void terminate() { -        full_icon = null; -        empty_icon = null;      }      public override string get_sidebar_name() {          return TrashPage.NAME;      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return get_current_icon();      } -    private static Icon get_current_icon() { +    private static string get_current_icon() {          foreach (MediaSourceCollection media_sources in MediaCollectionRegistry.get_instance().get_all()) {              if (media_sources.get_trashcan_count() > 0) -                return full_icon; +                return Resources.ICON_TRASH_FULL;          } -        return empty_icon; +        return Resources.ICON_TRASH_EMPTY;      }      public bool internal_drop_received(Gee.List<MediaSource> media) { diff --git a/src/library/mk/library.mk b/src/library/mk/library.mk index b4ab790..dc6201f 100644 --- a/src/library/mk/library.mk +++ b/src/library/mk/library.mk @@ -13,11 +13,11 @@ UNIT_DIR := library  UNIT_FILES := \  	LibraryWindow.vala \  	Branch.vala \ -	TrashBranch.vala \ -	OfflineBranch.vala \ -	FlaggedBranch.vala \ -	LastImportBranch.vala \ -	ImportQueueBranch.vala \ +        TrashSidebarEntry.vala \ +        OfflineSidebarEntry.vala \ +        FlaggedSidebarEntry.vala \ +        LastImportSidebarEntry.vala \ +        ImportQueueSidebarEntry.vala \  	FlaggedPage.vala \  	ImportQueuePage.vala \  	LastImportPage.vala \ diff --git a/src/main.vala b/src/main.vala index 8c045fd..6a705a7 100644 --- a/src/main.vala +++ b/src/main.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/BmpSupport.vala b/src/photos/BmpSupport.vala index dbeb64c..677eac3 100644 --- a/src/photos/BmpSupport.vala +++ b/src/photos/BmpSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/GRaw.vala b/src/photos/GRaw.vala index 915a861..1aa7ca5 100644 --- a/src/photos/GRaw.vala +++ b/src/photos/GRaw.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/GdkSupport.vala b/src/photos/GdkSupport.vala index ed2ff63..05e6854 100644 --- a/src/photos/GdkSupport.vala +++ b/src/photos/GdkSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/JfifSupport.vala b/src/photos/JfifSupport.vala index d721441..6ac5e4b 100644 --- a/src/photos/JfifSupport.vala +++ b/src/photos/JfifSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/PhotoFileAdapter.vala b/src/photos/PhotoFileAdapter.vala index 38b00ea..735e153 100644 --- a/src/photos/PhotoFileAdapter.vala +++ b/src/photos/PhotoFileAdapter.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/PhotoFileFormat.vala b/src/photos/PhotoFileFormat.vala index 2ab2f00..b9d3f63 100644 --- a/src/photos/PhotoFileFormat.vala +++ b/src/photos/PhotoFileFormat.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/PhotoFileSniffer.vala b/src/photos/PhotoFileSniffer.vala index 3f65ac2..cdbdad2 100644 --- a/src/photos/PhotoFileSniffer.vala +++ b/src/photos/PhotoFileSniffer.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/PhotoMetadata.vala b/src/photos/PhotoMetadata.vala index 37804bf..be781b6 100644 --- a/src/photos/PhotoMetadata.vala +++ b/src/photos/PhotoMetadata.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/Photos.vala b/src/photos/Photos.vala index 3033b92..c9eb357 100644 --- a/src/photos/Photos.vala +++ b/src/photos/Photos.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/PngSupport.vala b/src/photos/PngSupport.vala index 2cde6a2..feb409d 100644 --- a/src/photos/PngSupport.vala +++ b/src/photos/PngSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/photos/RawSupport.vala b/src/photos/RawSupport.vala index 98bc982..fb5f864 100644 --- a/src/photos/RawSupport.vala +++ b/src/photos/RawSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/photos/TiffSupport.vala b/src/photos/TiffSupport.vala index ee8b087..ac1eb6d 100644 --- a/src/photos/TiffSupport.vala +++ b/src/photos/TiffSupport.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/plugins/DataImportsInterfaces.vala b/src/plugins/DataImportsInterfaces.vala index 154503b..2f519bd 100644 --- a/src/plugins/DataImportsInterfaces.vala +++ b/src/plugins/DataImportsInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -119,6 +119,8 @@ public interface ImportableMediaItem : GLib.Object {      public abstract string get_folder_path();      public abstract string get_filename(); + +    public abstract time_t? get_exposure_time();  }  /** diff --git a/src/plugins/ManifestWidget.vala b/src/plugins/ManifestWidget.vala index 54f2e56..fe32b91 100644 --- a/src/plugins/ManifestWidget.vala +++ b/src/plugins/ManifestWidget.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/plugins/Plugins.vala b/src/plugins/Plugins.vala index d0f9185..9a8860b 100644 --- a/src/plugins/Plugins.vala +++ b/src/plugins/Plugins.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/plugins/PublishingInterfaces.vala b/src/plugins/PublishingInterfaces.vala index ca74597..7c0a901 100644 --- a/src/plugins/PublishingInterfaces.vala +++ b/src/plugins/PublishingInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/plugins/SpitInterfaces.vala b/src/plugins/SpitInterfaces.vala index f2fce6f..0a432c2 100644 --- a/src/plugins/SpitInterfaces.vala +++ b/src/plugins/SpitInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/plugins/StandardHostInterface.vala b/src/plugins/StandardHostInterface.vala index 9bfc0aa..c14d688 100644 --- a/src/plugins/StandardHostInterface.vala +++ b/src/plugins/StandardHostInterface.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/plugins/TransitionsInterfaces.vala b/src/plugins/TransitionsInterfaces.vala index eae76cf..917f88d 100644 --- a/src/plugins/TransitionsInterfaces.vala +++ b/src/plugins/TransitionsInterfaces.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/publishing/APIGlue.vala b/src/publishing/APIGlue.vala index f282c1f..24e10cc 100644 --- a/src/publishing/APIGlue.vala +++ b/src/publishing/APIGlue.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/publishing/Publishing.vala b/src/publishing/Publishing.vala index fb04eab..c245385 100644 --- a/src/publishing/Publishing.vala +++ b/src/publishing/Publishing.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/publishing/PublishingPluginHost.vala b/src/publishing/PublishingPluginHost.vala index 1a5ed86..1a95ef3 100644 --- a/src/publishing/PublishingPluginHost.vala +++ b/src/publishing/PublishingPluginHost.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/publishing/PublishingUI.vala b/src/publishing/PublishingUI.vala index 4f63f55..a74bfaf 100644 --- a/src/publishing/PublishingUI.vala +++ b/src/publishing/PublishingUI.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -146,7 +146,6 @@ public class PublishingDialog : Gtk.Dialog {      private Gtk.ListStore service_selector_box_model;      private Gtk.ComboBox service_selector_box; -    private Gtk.Label service_selector_box_label;      private Gtk.Box central_area_layouter;      private Gtk.Button close_cancel_button;      private Spit.Publishing.DialogPane active_pane; @@ -157,6 +156,9 @@ public class PublishingDialog : Gtk.Dialog {      protected PublishingDialog(Gee.Collection<MediaSource> to_publish) {          assert(to_publish.size > 0); +        Object(use_header_bar: 1); +        ((Gtk.HeaderBar) get_header_bar()).set_show_close_button(false); +                  resizable = false;          delete_event.connect(on_window_close); @@ -180,7 +182,7 @@ public class PublishingDialog : Gtk.Dialog {          string label = null;          if (has_photos && !has_videos) { -            title = null;_("Publish Photos"); +            title = _("Publish Photos");              label = _("Publish photos _to:");          } else if (!has_photos && has_videos) {              title = _("Publish Videos"); @@ -203,10 +205,6 @@ public class PublishingDialog : Gtk.Dialog {          service_selector_box.add_attribute(renderer_text, "text", 1);          service_selector_box.set_active(0); -         -        service_selector_box_label = new Gtk.Label.with_mnemonic(label); -        service_selector_box_label.set_mnemonic_widget(service_selector_box); -        service_selector_box_label.set_alignment(0.0f, 0.5f);          // get the name of the service the user last used          string? last_used_service = Config.Facade.get_instance().get_last_used_service(); @@ -244,37 +242,16 @@ public class PublishingDialog : Gtk.Dialog {          }          service_selector_box.changed.connect(on_service_changed); - -        /* the wrapper is not an extraneous widget -- it's necessary to prevent the service -           selection box from growing and shrinking whenever its parent's size changes. -           When wrapped inside a Gtk.Alignment, the Alignment grows and shrinks instead of -           the service selection box. */ -        Gtk.Alignment service_selector_box_wrapper = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f); -        service_selector_box_wrapper.add(service_selector_box); - -        Gtk.Box service_selector_layouter = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); -        service_selector_layouter.set_border_width(12); -        service_selector_layouter.add(service_selector_box_label); -        service_selector_layouter.pack_start(service_selector_box_wrapper, true, true, 0); -         -        /* 'service area' is the selector assembly plus the horizontal rule dividing it from the -           rest of the dialog */ -        Gtk.Box service_area_layouter = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); -        service_area_layouter.add(service_selector_layouter); -        service_area_layouter.add(new Gtk.Separator(Gtk.Orientation.HORIZONTAL)); - -        Gtk.Alignment service_area_wrapper = new Gtk.Alignment(0.0f, 0.0f, 1.0f, 0.0f); -        service_area_wrapper.add(service_area_layouter);          central_area_layouter = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); -        get_content_area().pack_start(service_area_wrapper, false, false, 0);          get_content_area().pack_start(central_area_layouter, true, true, 0);          close_cancel_button = new Gtk.Button.with_mnemonic("_Cancel");          close_cancel_button.set_can_default(true);          close_cancel_button.clicked.connect(on_close_cancel_clicked); -        ((Gtk.Container) get_action_area()).add(close_cancel_button); +        ((Gtk.HeaderBar) get_header_bar()).pack_start(close_cancel_button); +        ((Gtk.HeaderBar) get_header_bar()).pack_end(service_selector_box);          set_standard_window_mode(); diff --git a/src/searches/Branch.vala b/src/searches/Branch.vala index 229c710..00a9ea7 100644 --- a/src/searches/Branch.vala +++ b/src/searches/Branch.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -9,7 +9,7 @@ public class Searches.Branch : Sidebar.Branch {          new Gee.HashMap<SavedSearch, Searches.SidebarEntry>();      public Branch() { -        base (new Searches.Grouping(), +        base (new Searches.Header(),              Sidebar.Branch.Options.HIDE_IF_EMPTY                  | Sidebar.Branch.Options.AUTO_OPEN_ON_NEW_CHILD                  | Sidebar.Branch.Options.STARTUP_EXPAND_TO_FIRST_CHILD, @@ -60,12 +60,12 @@ public class Searches.Branch : Sidebar.Branch {      }  } -public class Searches.Grouping : Sidebar.Grouping, Sidebar.Contextable { +public class Searches.Header : Sidebar.Header, Sidebar.Contextable {      private Gtk.UIManager ui = new Gtk.UIManager();      private Gtk.Menu? context_menu = null; -    public Grouping() { -        base (_("Saved Searches"), new ThemedIcon(Gtk.Stock.FIND)); +    public Header() { +        base (_("Saved Searches"));          setup_context_menu();      } @@ -104,7 +104,7 @@ public class Searches.Grouping : Sidebar.Grouping, Sidebar.Contextable {  public class Searches.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntry,      Sidebar.DestroyableEntry { -    private static Icon single_search_icon; +    private static string single_search_icon = "find";      private SavedSearch search; @@ -113,11 +113,9 @@ public class Searches.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.Renameable      }      internal static void init() { -        single_search_icon = new ThemedIcon(Gtk.Stock.FIND);      }      internal static void terminate() { -        single_search_icon = null;      }      public SavedSearch for_saved_search() { @@ -128,7 +126,7 @@ public class Searches.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.Renameable          return search.get_name();      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return single_search_icon;      } @@ -136,6 +134,10 @@ public class Searches.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.Renameable          return new SavedSearchPage(search);      } +    public bool is_user_renameable() { +        return true; +    } +          public void rename(string new_name) {          if (!SavedSearchTable.get_instance().exists(new_name))              AppWindow.get_command_manager().execute(new RenameSavedSearchCommand(search, new_name)); diff --git a/src/searches/SavedSearchDialog.vala b/src/searches/SavedSearchDialog.vala index da7f7db..eb016d3 100644 --- a/src/searches/SavedSearchDialog.vala +++ b/src/searches/SavedSearchDialog.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -48,13 +48,12 @@ public class SavedSearchDialog {              set_type_combo_box(SearchCondition.SearchType.ANY_TEXT); // Sets default.              type_combo.changed.connect(on_type_changed); -            remove_button = new Gtk.Button(); -            remove_button.set_label(" – "); +            remove_button = new Gtk.Button.from_icon_name("list-remove-symbolic", Gtk.IconSize.BUTTON);              remove_button.button_press_event.connect(on_removed);              align = new Gtk.Alignment(0,0,0,0); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(type_combo, false, false, 0);              box.pack_start(align, false, false, 0);              box.pack_start(new Gtk.Alignment(0,0,0,0), true, true, 0); // Fill space. @@ -172,6 +171,7 @@ public class SavedSearchDialog {              text_context.append_text(_("ends with"));              text_context.append_text(_("does not contain"));              text_context.append_text(_("is not set")); +            text_context.append_text(_("is set"));              text_context.set_active(0);              text_context.changed.connect(on_changed); @@ -180,7 +180,7 @@ public class SavedSearchDialog {              entry.set_activates_default(true);              entry.changed.connect(on_changed); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(text_context, false, false, 0);              box.pack_start(entry, false, false, 0);              box.show_all(); @@ -212,7 +212,9 @@ public class SavedSearchDialog {          }          public override bool is_complete() { -            return entry.text.chomp() != "" || get_text_context() == SearchConditionText.Context.IS_NOT_SET; +            return entry.text.chomp() != "" || +                get_text_context() == SearchConditionText.Context.IS_NOT_SET || +                get_text_context() == SearchConditionText.Context.IS_SET;          }          private SearchConditionText.Context get_text_context() { @@ -220,7 +222,8 @@ public class SavedSearchDialog {          }          private void on_changed() { -            if (get_text_context() == SearchConditionText.Context.IS_NOT_SET) { +            if (get_text_context() == SearchConditionText.Context.IS_NOT_SET +                || get_text_context() == SearchConditionText.Context.IS_SET) {                  entry.hide();              } else {                  entry.show(); @@ -255,7 +258,7 @@ public class SavedSearchDialog {              media_type.set_active(0);              media_type.changed.connect(on_changed); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(media_context, false, false, 0);              box.pack_start(media_type, false, false, 0);              box.show_all(); @@ -317,7 +320,7 @@ public class SavedSearchDialog {              modified_state.set_active(0);              modified_state.changed.connect(on_changed); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(modified_context, false, false, 0);              box.pack_start(modified_state, false, false, 0);              box.show_all(); @@ -372,7 +375,7 @@ public class SavedSearchDialog {              flagged_state.set_active(0);              flagged_state.changed.connect(on_changed); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(new Gtk.Label(_("is")), false, false, 0);              box.pack_start(flagged_state, false, false, 0);              box.show_all(); @@ -437,7 +440,7 @@ public class SavedSearchDialog {              context.set_active(0);              context.changed.connect(on_changed); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(new Gtk.Label(_("is")), false, false, 0);              box.pack_start(rating, false, false, 0);              box.pack_start(context, false, false, 0); @@ -512,7 +515,7 @@ public class SavedSearchDialog {              and = new Gtk.Label(_("and")); -            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 8); +            box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 3);              box.pack_start(context, false, false, 0);              box.pack_start(label_one, false, false, 0);              box.pack_start(and, false, false, 0); @@ -604,14 +607,16 @@ public class SavedSearchDialog {              int orig_month = cal.month;              int orig_year = cal.year;              Gtk.Dialog d = new Gtk.Dialog.with_buttons(null, null,  -                Gtk.DialogFlags.MODAL, Gtk.Stock.CANCEL, Gtk.ResponseType.REJECT,  -                Gtk.Stock.OK, Gtk.ResponseType.ACCEPT); +                Gtk.DialogFlags.MODAL, Resources.CANCEL_LABEL, Gtk.ResponseType.REJECT,  +                Resources.OK_LABEL, Gtk.ResponseType.ACCEPT);              d.set_modal(true);              d.set_resizable(false);              d.set_decorated(false);              ((Gtk.Box) d.get_content_area()).add(cal);              ulong id_1 = cal.day_selected.connect(()=>{update_date_labels();}); -            ulong id_2 = cal.day_selected_double_click.connect(()=>{d.close();}); +            ulong id_2 = cal.day_selected_double_click.connect(()=> { +                  d.response(Gtk.ResponseType.ACCEPT); +            });              d.show_all();              int res = d.run();              if (res != Gtk.ResponseType.ACCEPT) { @@ -656,14 +661,7 @@ public class SavedSearchDialog {          // Default is text search.          add_text_search();          row_list.get(0).allow_removal(false); -         -        // Add buttons for new search. -        dialog.add_action_widget(new Gtk.Button.from_stock(Gtk.Stock.CANCEL), Gtk.ResponseType.CANCEL); -        Gtk.Button ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK); -        ok_button.can_default = true; -        dialog.add_action_widget(ok_button, Gtk.ResponseType.OK); -        dialog.set_default_response(Gtk.ResponseType.OK); -         +          dialog.show_all();          set_valid(false);      } @@ -673,12 +671,6 @@ public class SavedSearchDialog {          edit_mode = true;          setup_dialog(); -        // Add close button. -        Gtk.Button close_button = new Gtk.Button.from_stock(Gtk.Stock.CLOSE); -        close_button.can_default = true; -        dialog.add_action_widget(close_button, Gtk.ResponseType.OK); -        dialog.set_default_response(Gtk.ResponseType.OK); -                  dialog.show_all();          // Load existing search into dialog. @@ -701,12 +693,21 @@ public class SavedSearchDialog {      // Builds the dialog UI.  Doesn't add buttons to the dialog or call dialog.show().      private void setup_dialog() {          builder = AppWindow.create_builder(); -         -        dialog = builder.get_object("Search criteria") as Gtk.Dialog; -        dialog.set_parent_window(AppWindow.get_instance().get_parent_window()); + +        dialog = new Gtk.Dialog.with_buttons(_("Search"), +                                         (Gtk.Window) AppWindow.get_instance().get_parent_window(), +                                         Gtk.DialogFlags.MODAL | +                                         Gtk.DialogFlags.DESTROY_WITH_PARENT | +                                         Gtk.DialogFlags.USE_HEADER_BAR, +                                         _("Cancel"), Gtk.ResponseType.CANCEL, +                                         _("OK"), Gtk.ResponseType.OK, +                                         null); +        dialog.set_resizable(false);          dialog.set_transient_for(AppWindow.get_instance()); +        dialog.set_default_response(Gtk.ResponseType.OK);          dialog.response.connect(on_response); -         +        dialog.get_content_area().add(builder.get_object("criteria") as Gtk.Widget); +          add_criteria = builder.get_object("Add search button") as Gtk.Button;          add_criteria.button_press_event.connect(on_add_criteria); diff --git a/src/searches/SavedSearchPage.vala b/src/searches/SavedSearchPage.vala index 8e6672e..99473fb 100644 --- a/src/searches/SavedSearchPage.vala +++ b/src/searches/SavedSearchPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/searches/SearchBoolean.vala b/src/searches/SearchBoolean.vala index 431e398..8031814 100644 --- a/src/searches/SearchBoolean.vala +++ b/src/searches/SearchBoolean.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. @@ -206,7 +206,8 @@ public class SearchConditionText : SearchCondition {          STARTS_WITH,          ENDS_WITH,          DOES_NOT_CONTAIN, -        IS_NOT_SET; +        IS_NOT_SET, +        IS_SET;          public string to_string() {              switch (this) { @@ -228,6 +229,9 @@ public class SearchConditionText : SearchCondition {                  case Context.IS_NOT_SET:                      return "IS_NOT_SET"; +                case Context.IS_SET: +                    return "IS_SET"; +                                  default:                      error("unrecognized text search context enumeration value");              } @@ -252,6 +256,9 @@ public class SearchConditionText : SearchCondition {              else if (str == "IS_NOT_SET")                  return Context.IS_NOT_SET; +            else if (str == "IS_SET") +                return Context.IS_SET; +                          else                  error("unrecognized text search context name: %s", str);          } @@ -287,6 +294,9 @@ public class SearchConditionText : SearchCondition {              case Context.IS_NOT_SET:                  return (is_string_empty(haystack)); +             +            case Context.IS_SET: +                return (!is_string_empty(haystack));          }          return false; @@ -298,10 +308,9 @@ public class SearchConditionText : SearchCondition {          // title          if (SearchType.ANY_TEXT == search_type || SearchType.TITLE == search_type) { -            string title = source.get_title(); -            if(title != null){ -                ret |= string_match(text, String.remove_diacritics(title.down())); -            } +            string? title = (null != source.get_title()) ? +                String.remove_diacritics(source.get_title().down()) : null; +            ret |= string_match(text, title);          }          // tags diff --git a/src/searches/Searches.vala b/src/searches/Searches.vala index 478de86..691bcf0 100644 --- a/src/searches/Searches.vala +++ b/src/searches/Searches.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/sidebar/Branch.vala b/src/sidebar/Branch.vala index 23badda..a6c3ee8 100644 --- a/src/sidebar/Branch.vala +++ b/src/sidebar/Branch.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -39,23 +39,22 @@ public class Sidebar.Branch : Object {          public Sidebar.Entry entry;          public weak Node? parent; -        public CompareDataFunc<Sidebar.Entry> comparator; +        public CompareFunc<Sidebar.Entry> comparator;          public Gee.SortedSet<Node>? children = null; -        public Node(Sidebar.Entry entry, Node? parent, -            owned CompareDataFunc<Sidebar.Entry> comparator) { +        public Node(Sidebar.Entry entry, Node? parent, CompareFunc<Sidebar.Entry> comparator) {              this.entry = entry;              this.parent = parent; -            this.comparator = (owned) comparator; +            this.comparator = comparator;          } -        private static int comparator_wrapper(Node? a, Node? b) { -            if (a == b) +        private static int comparator_wrapper(Node anode, Node bnode) { +            if (anode == bnode)                  return 0; -            assert(a.parent == b.parent); +            assert(anode.parent == bnode.parent); -            return a.parent.comparator(a.entry, b.entry); +            return anode.parent.comparator(anode.entry, bnode.entry);          }          public bool has_children() { @@ -172,16 +171,16 @@ public class Sidebar.Branch : Object {              cb(this);          } -        public void change_comparator(owned CompareDataFunc<Sidebar.Entry> comparator, bool recursive, +        public void change_comparator(CompareFunc<Sidebar.Entry> comparator, bool recursive,              ChildrenReorderedCallback cb) { -            this.comparator = (owned) comparator; +            this.comparator = comparator;              // reorder children, but need to do manual recursion to set comparator              reorder_children(false, cb);              if (recursive) {                  foreach (Node child in children) -                    child.change_comparator((owned) comparator, true, cb); +                    child.change_comparator(comparator, true, cb);              }          }      } @@ -189,7 +188,7 @@ public class Sidebar.Branch : Object {      private Node root;      private Options options;      private bool shown = true; -    private CompareDataFunc<Sidebar.Entry> default_comparator; +    private CompareFunc<Sidebar.Entry> default_comparator;      private Gee.HashMap<Sidebar.Entry, Node> map = new Gee.HashMap<Sidebar.Entry, Node>();      public signal void entry_added(Sidebar.Entry entry); @@ -204,19 +203,11 @@ public class Sidebar.Branch : Object {      public signal void show_branch(bool show); -    public Branch(Sidebar.Entry root, Options options,  -        owned CompareDataFunc<Sidebar.Entry> default_comparator, -        owned CompareDataFunc<Sidebar.Entry>? root_comparator = null) { -        this.default_comparator = (owned) default_comparator; -         -        CompareDataFunc<Sidebar.Entry>? broken_ternary_workaround; -         -        if (root_comparator != null) -            broken_ternary_workaround = (owned) root_comparator; -        else -            broken_ternary_workaround = (owned) default_comparator; - -        this.root = new Node(root, null, (owned) broken_ternary_workaround); +    public Branch(Sidebar.Entry root, Options options, CompareFunc<Sidebar.Entry> default_comparator, +        CompareFunc<Sidebar.Entry>? root_comparator = null) { +        this.default_comparator = default_comparator; +        this.root = new Node(root, null, +            (root_comparator != null) ? root_comparator : default_comparator);          this.options = options;          map.set(root, this.root); @@ -254,7 +245,7 @@ public class Sidebar.Branch : Object {      }      public void graft(Sidebar.Entry parent, Sidebar.Entry entry, -        owned CompareDataFunc<Sidebar.Entry>? comparator = null) { +        CompareFunc<Sidebar.Entry>? comparator = null) {          assert(map.has_key(parent));          assert(!map.has_key(entry)); @@ -262,15 +253,8 @@ public class Sidebar.Branch : Object {              set_show_branch(true);          Node parent_node = map.get(parent); -         -        CompareDataFunc<Sidebar.Entry>? broken_ternary_workaround; -         -        if (comparator != null) -            broken_ternary_workaround = (owned) comparator; -        else -            broken_ternary_workaround = (owned) default_comparator; -         -        Node entry_node = new Node(entry, parent_node, (owned) broken_ternary_workaround); +        Node entry_node = new Node(entry, parent_node, +            (comparator != null) ? comparator : default_comparator);          parent_node.add_child(entry_node);          map.set(entry, entry_node); @@ -347,16 +331,16 @@ public class Sidebar.Branch : Object {          entry_node.reorder_children(recursive, children_reordered_callback);      } -    public void change_all_comparators(owned CompareDataFunc<Sidebar.Entry>? comparator) { -        root.change_comparator((owned) comparator, true, children_reordered_callback); +    public void change_all_comparators(CompareFunc<Sidebar.Entry>? comparator) { +        root.change_comparator(comparator, true, children_reordered_callback);      }      public void change_comparator(Sidebar.Entry entry, bool recursive, -        owned CompareDataFunc<Sidebar.Entry>? comparator) { +        CompareFunc<Sidebar.Entry>? comparator) {          Node? entry_node = map.get(entry);          assert(entry_node != null); -        entry_node.change_comparator((owned) comparator, recursive, children_reordered_callback); +        entry_node.change_comparator(comparator, recursive, children_reordered_callback);      }      public int get_child_count(Sidebar.Entry parent) { diff --git a/src/sidebar/Entry.vala b/src/sidebar/Entry.vala index 4162f21..5a84f74 100644 --- a/src/sidebar/Entry.vala +++ b/src/sidebar/Entry.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -7,13 +7,13 @@  public interface Sidebar.Entry : Object {      public signal void sidebar_tooltip_changed(string? tooltip); -    public signal void sidebar_icon_changed(Icon? icon); +    public signal void sidebar_icon_changed(string? icon);      public abstract string get_sidebar_name();      public abstract string? get_sidebar_tooltip(); -    public abstract Icon? get_sidebar_icon(); +    public abstract string? get_sidebar_icon();      public abstract string to_string(); @@ -25,12 +25,6 @@ public interface Sidebar.Entry : Object {  }  public interface Sidebar.ExpandableEntry : Sidebar.Entry { -    public signal void sidebar_open_closed_icons_changed(Icon? open, Icon? closed); -     -    public abstract Icon? get_sidebar_open_icon(); -     -    public abstract Icon? get_sidebar_closed_icon(); -          public abstract bool expand_on_select();  } @@ -53,6 +47,15 @@ public interface Sidebar.RenameableEntry : Sidebar.Entry {      public signal void sidebar_name_changed(string name);      public abstract void rename(string new_name); +     +    // Return true to allow the user to rename the sidebar entry in the UI. +    public abstract bool is_user_renameable(); +} + +public interface Sidebar.EmphasizableEntry : Sidebar.Entry { +    public signal void is_emphasized_changed(bool emphasized); +     +    public abstract bool is_emphasized();  }  public interface Sidebar.DestroyableEntry : Sidebar.Entry { diff --git a/src/sidebar/Sidebar.vala b/src/sidebar/Sidebar.vala index 8f6904b..0b4c0da 100644 --- a/src/sidebar/Sidebar.vala +++ b/src/sidebar/Sidebar.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/sidebar/Tree.vala b/src/sidebar/Tree.vala index 37da7e0..a020b18 100644 --- a/src/sidebar/Tree.vala +++ b/src/sidebar/Tree.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -37,8 +37,7 @@ public class Sidebar.Tree : Gtk.TreeView {      private class RootWrapper : EntryWrapper {          public int root_position; -        public RootWrapper(Gtk.TreeModel model, Sidebar.Entry entry, Gtk.TreePath path, int root_position)  -            requires (root_position >= 0) { +        public RootWrapper(Gtk.TreeModel model, Sidebar.Entry entry, Gtk.TreePath path, int root_position) {              base (model, entry, path);              this.root_position = root_position; @@ -49,9 +48,7 @@ public class Sidebar.Tree : Gtk.TreeView {          NAME,          TOOLTIP,          WRAPPER, -        PIXBUF, -        CLOSED_PIXBUF, -        OPEN_PIXBUF, +        ICON,          N_COLUMNS      } @@ -59,17 +56,13 @@ public class Sidebar.Tree : Gtk.TreeView {          typeof (string),            // NAME          typeof (string?),           // TOOLTIP          typeof (EntryWrapper),      // WRAPPER -        typeof (Gdk.Pixbuf?),       // PIXBUF -        typeof (Gdk.Pixbuf?),       // CLOSED_PIXBUF -        typeof (Gdk.Pixbuf?)        // OPEN_PIXBUF +        typeof (string?)            // ICON      );      private Gtk.UIManager ui = new Gtk.UIManager(); -    private Gtk.IconTheme icon_theme;      private Gtk.CellRendererText text_renderer;      private unowned ExternalDropHandler drop_handler;      private Gtk.Entry? text_entry = null; -    private Gee.HashMap<string, Gdk.Pixbuf> icon_cache = new Gee.HashMap<string, Gdk.Pixbuf>();      private Gee.HashMap<Sidebar.Entry, EntryWrapper> entry_map =          new Gee.HashMap<Sidebar.Entry, EntryWrapper>();      private Gee.HashMap<Sidebar.Branch, int> branches = new Gee.HashMap<Sidebar.Branch, int>(); @@ -77,8 +70,11 @@ public class Sidebar.Tree : Gtk.TreeView {      private bool mask_entry_selected_signal = false;      private weak EntryWrapper? selected_wrapper = null;      private Gtk.Menu? default_context_menu = null; +    private bool expander_called_manually = false; +    private int expander_special_count = 0;      private bool is_internal_drag_in_progress = false;      private Sidebar.Entry? internal_drag_source_entry = null; +    private Gtk.TreeRowReference? old_path_ref = null;      public signal void entry_selected(Sidebar.SelectableEntry selectable); @@ -97,15 +93,17 @@ public class Sidebar.Tree : Gtk.TreeView {      public Tree(Gtk.TargetEntry[] target_entries, Gdk.DragAction actions,          ExternalDropHandler drop_handler) {          set_model(store); +        get_style_context().add_class("sidebar");          Gtk.TreeViewColumn text_column = new Gtk.TreeViewColumn(); -        text_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED); +        text_column.set_expand(true);          Gtk.CellRendererPixbuf icon_renderer = new Gtk.CellRendererPixbuf(); +        icon_renderer.follow_state = true;          text_column.pack_start(icon_renderer, false); -        text_column.add_attribute(icon_renderer, "pixbuf", Columns.PIXBUF); -        text_column.add_attribute(icon_renderer, "pixbuf_expander_closed", Columns.CLOSED_PIXBUF); -        text_column.add_attribute(icon_renderer, "pixbuf_expander_open", Columns.OPEN_PIXBUF); +        text_column.add_attribute(icon_renderer, "icon_name", Columns.ICON); +        text_column.set_cell_data_func(icon_renderer, icon_renderer_function);          text_renderer = new Gtk.CellRendererText(); +        text_renderer.ellipsize = Pango.EllipsizeMode.END;          text_renderer.editing_canceled.connect(on_editing_canceled);          text_renderer.editing_started.connect(on_editing_started);          text_column.pack_start(text_renderer, true); @@ -131,6 +129,9 @@ public class Sidebar.Tree : Gtk.TreeView {          selection.set_mode(Gtk.SelectionMode.BROWSE);          selection.set_select_function(on_selection); +        test_expand_row.connect(on_toggle_row); +        test_collapse_row.connect(on_toggle_row); +                  // It Would Be Nice if the target entries and actions were gleaned by querying each           // Sidebar.Entry as it was added, but that's a tad too complicated for our needs          // currently @@ -145,9 +146,6 @@ public class Sidebar.Tree : Gtk.TreeView {          popup_menu.connect(on_context_menu_keypress); -        icon_theme = Resources.get_icon_theme_engine(); -        icon_theme.changed.connect(on_theme_change); -                  setup_default_context_menu();          drag_begin.connect(on_drag_begin); @@ -158,7 +156,14 @@ public class Sidebar.Tree : Gtk.TreeView {      ~Tree() {          text_renderer.editing_canceled.disconnect(on_editing_canceled);          text_renderer.editing_started.disconnect(on_editing_started); -        icon_theme.changed.disconnect(on_theme_change); +    } +     +    public void icon_renderer_function(Gtk.CellLayout layout, Gtk.CellRenderer renderer, Gtk.TreeModel model, Gtk.TreeIter iter) { +        EntryWrapper? wrapper = get_wrapper_at_iter(iter); +        if (wrapper == null) { +            return; +        } +        renderer.visible = !(wrapper.entry is Sidebar.Header);      }      private void on_drag_begin(Gdk.DragContext ctx) { @@ -270,41 +275,72 @@ public class Sidebar.Tree : Gtk.TreeView {      public bool is_selected(Sidebar.Entry entry) {          EntryWrapper? wrapper = get_wrapper(entry); -        return (wrapper != null) ? get_selection().path_is_selected(wrapper.get_path()) : false; +        // Even though get_selection() does not report its return type as nullable, it can be null +        // if the window has been destroyed. +        Gtk.TreeSelection selection = get_selection(); +        if (selection == null) +            return false; +         +        return (wrapper != null) ? selection.path_is_selected(wrapper.get_path()) : false;      }      public bool is_any_selected() {          return get_selection().count_selected_rows() != 0;      } -     +      private Gtk.TreePath? get_selected_path() {          Gtk.TreeModel model; -        GLib.List<Gtk.TreePath> rows = get_selection().get_selected_rows(out model); +        Gtk.TreeSelection? selection = get_selection(); +        if (selection == null){ +            return null; +        } +        GLib.List<Gtk.TreePath> rows = selection.get_selected_rows(out model);          assert(rows.length() == 0 || rows.length() == 1); -         +          return rows.length() != 0 ? rows.nth_data(0) : null;      } + +    private string get_name_for_entry(Sidebar.Entry entry) { +        string name = guarded_markup_escape_text(entry.get_sidebar_name()); +         +        Sidebar.EmphasizableEntry? emphasizable_entry = entry as Sidebar.EmphasizableEntry; +        if (emphasizable_entry != null && emphasizable_entry.is_emphasized()) +            name = "<b>%s</b>".printf(name); +         +        return name; +    } +     +    public virtual bool accept_cursor_changed() { +        return true; +    }      public override void cursor_changed() {          Gtk.TreePath? path = get_selected_path();          if (path == null) {              if (base.cursor_changed != null)                  base.cursor_changed(); -                          return;          }          EntryWrapper? wrapper = get_wrapper_at_path(path); -       -        selected_wrapper = wrapper; -         -        if (editing_disabled == 0 && wrapper != null) -            text_renderer.editable = wrapper.entry is Sidebar.RenameableEntry; -        if (wrapper != null && !mask_entry_selected_signal) { -            Sidebar.SelectableEntry? selectable = wrapper.entry as Sidebar.SelectableEntry; -            if (selectable != null) -                entry_selected(selectable); +        if (selected_wrapper != wrapper) { +            EntryWrapper old_wrapper = selected_wrapper; +            selected_wrapper = wrapper; +             +            if (editing_disabled == 0 && wrapper != null && wrapper.entry is Sidebar.RenameableEntry) +                text_renderer.editable = ((Sidebar.RenameableEntry) wrapper.entry).is_user_renameable(); +             +            if (wrapper != null && !mask_entry_selected_signal) { +                Sidebar.SelectableEntry? selectable = wrapper.entry as Sidebar.SelectableEntry; +                if (selectable != null) { +                    if (accept_cursor_changed()) { +                        entry_selected(selectable); +                    } else { +                        place_cursor(old_wrapper.entry, true); +                    } +                } +            }          }          if (base.cursor_changed != null) @@ -320,11 +356,14 @@ public class Sidebar.Tree : Gtk.TreeView {          Gtk.TreePath? path = get_selected_path();          if (path != null && editing_disabled > 0 && --editing_disabled == 0) {              EntryWrapper? wrapper = get_wrapper_at_path(path); -            text_renderer.editable = (wrapper != null && (wrapper.entry is Sidebar.RenameableEntry)); +            if (wrapper != null && (wrapper.entry is Sidebar.RenameableEntry)) +                text_renderer.editable = ((Sidebar.RenameableEntry) wrapper.entry). +                    is_user_renameable();          }      }      public void toggle_branch_expansion(Gtk.TreePath path, bool expand_all) { +        expander_called_manually = true;          if (is_row_expanded(path))              collapse_row(path);          else @@ -332,6 +371,7 @@ public class Sidebar.Tree : Gtk.TreeView {      }      public bool expand_to_entry(Sidebar.Entry entry) { +        expander_called_manually = true;          EntryWrapper? wrapper = get_wrapper(entry);          if (wrapper == null)              return false; @@ -342,6 +382,7 @@ public class Sidebar.Tree : Gtk.TreeView {      }      public void expand_to_first_child(Sidebar.Entry entry) { +        expander_called_manually = true;          EntryWrapper? wrapper = get_wrapper(entry);          if (wrapper == null)              return; @@ -445,7 +486,7 @@ public class Sidebar.Tree : Gtk.TreeView {          assert(!entry_map.has_key(entry));          entry_map.set(entry, wrapper); -        store.set(assoc_iter, Columns.NAME, guarded_markup_escape_text(entry.get_sidebar_name())); +        store.set(assoc_iter, Columns.NAME, get_name_for_entry(entry));          store.set(assoc_iter, Columns.TOOLTIP, guarded_markup_escape_text(entry.get_sidebar_tooltip()));          store.set(assoc_iter, Columns.WRAPPER, wrapper);          load_entry_icons(assoc_iter); @@ -458,15 +499,15 @@ public class Sidebar.Tree : Gtk.TreeView {              pageable.page_created.connect(on_sidebar_page_created);              pageable.destroying_page.connect(on_sidebar_destroying_page);          } + +        Sidebar.EmphasizableEntry? emphasizable = entry as Sidebar.EmphasizableEntry; +        if (emphasizable != null) +            emphasizable.is_emphasized_changed.connect(on_is_emphasized_changed);          Sidebar.RenameableEntry? renameable = entry as Sidebar.RenameableEntry;          if (renameable != null)              renameable.sidebar_name_changed.connect(on_sidebar_name_changed); -         -        Sidebar.ExpandableEntry? expandable = entry as Sidebar.ExpandableEntry; -        if (expandable != null) -            expandable.sidebar_open_closed_icons_changed.connect(on_sidebar_open_closed_icons_changed); -         +                          entry.grafted(this);      } @@ -479,7 +520,7 @@ public class Sidebar.Tree : Gtk.TreeView {          EntryWrapper new_wrapper = new EntryWrapper(store, entry, store.get_path(new_iter));          entry_map.set(entry, new_wrapper); -        store.set(new_iter, Columns.NAME, guarded_markup_escape_text(entry.get_sidebar_name())); +        store.set(new_iter, Columns.NAME, get_name_for_entry(entry));          store.set(new_iter, Columns.TOOLTIP, guarded_markup_escape_text(entry.get_sidebar_tooltip()));          store.set(new_iter, Columns.WRAPPER, new_wrapper);          load_entry_icons(new_iter); @@ -571,9 +612,9 @@ public class Sidebar.Tree : Gtk.TreeView {          if (renameable != null)              renameable.sidebar_name_changed.disconnect(on_sidebar_name_changed); -        Sidebar.ExpandableEntry? expandable = entry as Sidebar.ExpandableEntry; -        if (expandable != null) -            expandable.sidebar_open_closed_icons_changed.disconnect(on_sidebar_open_closed_icons_changed); +        Sidebar.EmphasizableEntry? emphasizable = entry as Sidebar.EmphasizableEntry; +        if (emphasizable != null) +            emphasizable.is_emphasized_changed.disconnect(on_is_emphasized_changed);          bool removed = entry_map.unset(entry);          assert(removed); @@ -703,88 +744,42 @@ public class Sidebar.Tree : Gtk.TreeView {          store.set(wrapper.get_iter(), Columns.TOOLTIP, guarded_markup_escape_text(tooltip));      } -    private void on_sidebar_icon_changed(Sidebar.Entry entry, Icon? icon) { +    private void on_sidebar_icon_changed(Sidebar.Entry entry, string? icon) {          EntryWrapper? wrapper = get_wrapper(entry);          assert(wrapper != null); -        store.set(wrapper.get_iter(), Columns.PIXBUF, fetch_icon_pixbuf(icon)); +        store.set(wrapper.get_iter(), Columns.ICON, icon);      } -     -    private void on_sidebar_page_created(Sidebar.PageRepresentative entry, Page page) { -        page_created(entry, page); + +    private void rename_entry(Sidebar.Entry entry) { +        EntryWrapper? wrapper = get_wrapper(entry); +        assert(wrapper != null); +         +        store.set(wrapper.get_iter(), Columns.NAME, get_name_for_entry(entry));      } -    private void on_sidebar_destroying_page(Sidebar.PageRepresentative entry, Page page) { -        destroying_page(entry, page); +    private void on_sidebar_name_changed(Sidebar.Entry entry, string name) { +        rename_entry(entry);      } -    private void on_sidebar_open_closed_icons_changed(Sidebar.ExpandableEntry entry, Icon? open, -        Icon? closed) { -        EntryWrapper? wrapper = get_wrapper(entry); -        assert(wrapper != null); -         -        store.set(wrapper.get_iter(), Columns.OPEN_PIXBUF, fetch_icon_pixbuf(open)); -        store.set(wrapper.get_iter(), Columns.CLOSED_PIXBUF, fetch_icon_pixbuf(closed)); +    private void on_sidebar_page_created(Sidebar.PageRepresentative entry, Page page) { +        page_created(entry, page);      } -    private void on_sidebar_name_changed(Sidebar.RenameableEntry entry, string name) { -        EntryWrapper? wrapper = get_wrapper(entry); -        assert(wrapper != null); -         -        store.set(wrapper.get_iter(), Columns.NAME, guarded_markup_escape_text(name)); +    private void on_is_emphasized_changed(Sidebar.EmphasizableEntry entry, bool is_emphasized) { +        rename_entry(entry);      } -    private Gdk.Pixbuf? fetch_icon_pixbuf(GLib.Icon? gicon) { -        if (gicon == null) -            return null; -         -        try { -            Gdk.Pixbuf? icon = icon_cache.get(gicon.to_string()); -            if (icon != null) -                return icon; -             -            Gtk.IconInfo? info = icon_theme.lookup_by_gicon(gicon, ICON_SIZE, 0); -            if (info == null) -                return null; -             -            icon = info.load_icon(); -            if (icon == null) -                return null; -             -            icon_cache.set(gicon.to_string(), icon); -             -            return icon; -        } catch (Error err) { -            warning("Unable to load icon %s: %s", gicon.to_string(), err.message); -             -            return null; -        } +    private void on_sidebar_destroying_page(Sidebar.PageRepresentative entry, Page page) { +        destroying_page(entry, page);      }      private void load_entry_icons(Gtk.TreeIter iter) {          EntryWrapper? wrapper = get_wrapper_at_iter(iter);          if (wrapper == null)              return; -         -        Icon? icon = wrapper.entry.get_sidebar_icon(); -        Icon? open = null; -        Icon? closed = null; -         -        Sidebar.ExpandableEntry? expandable = wrapper.entry as Sidebar.ExpandableEntry; -        if (expandable != null) { -            open = expandable.get_sidebar_open_icon(); -            closed = expandable.get_sidebar_closed_icon(); -        } -         -        if (open == null) -            open = icon; -         -        if (closed == null) -            closed = icon; -         -        store.set(iter, Columns.PIXBUF, fetch_icon_pixbuf(icon)); -        store.set(iter, Columns.OPEN_PIXBUF, fetch_icon_pixbuf(open)); -        store.set(iter, Columns.CLOSED_PIXBUF, fetch_icon_pixbuf(closed)); +        string? icon = wrapper.entry.get_sidebar_icon(); +        store.set(iter, Columns.ICON, icon);      }      private void load_branch_icons(Gtk.TreeIter iter) { @@ -798,15 +793,6 @@ public class Sidebar.Tree : Gtk.TreeView {          }      } -    private void on_theme_change() { -        Gtk.TreeIter iter; -        if (store.get_iter_first(out iter)) { -            do { -                load_branch_icons(iter); -            } while (store.iter_next(ref iter)); -        } -    } -          private bool on_selection(Gtk.TreeSelection selection, Gtk.TreeModel model, Gtk.TreePath path,          bool path_currently_selected) {          // only allow selection if a page is selectable @@ -879,6 +865,42 @@ public class Sidebar.Tree : Gtk.TreeView {          return true;      } +    public bool on_toggle_row(Gtk.TreeIter iter, Gtk.TreePath path) { +        // Determine whether to allow the row to toggle +        EntryWrapper? wrapper = get_wrapper_at_iter(iter); +        if (wrapper == null) { +            return false; // don't affect things +        } +         +        // Most of the time, only allow manual toggles +        bool should_allow_toggle = expander_called_manually; +         +        // Cancel out the manual flag +        expander_called_manually = false; +         +        // If we are an expanded parent entry with content +        if (is_row_expanded(path) && store.iter_has_child(iter) && wrapper.entry is Sidebar.SelectableEntry) { +            // We are taking a special action +            expander_special_count++; +            if (expander_special_count == 1) { +                // Workaround that prevents arrows from double-toggling +                return true; +            } else { +                // Toggle only if non-manual, as opposed to the usual behavior +                should_allow_toggle = !should_allow_toggle; +            } +        } else { +            // Reset the special behavior count +            expander_special_count = 0; +        } +         +        if (should_allow_toggle) { +            return false; +        } +        // Prevent branch expansion toggle +        return true; +    } +          public override bool button_press_event(Gdk.EventButton event) {          Gtk.TreePath? path = get_path_from_event(event); @@ -893,19 +915,29 @@ public class Sidebar.Tree : Gtk.TreeView {                  popup_context_menu(path, event);              else                  popup_default_context_menu(event); -        } else if (event.button == 1 && event.type == Gdk.EventType.2BUTTON_PRESS) { -            // double left click -            if (path != null) { +        } else if (event.button == 1 && event.type == Gdk.EventType.BUTTON_PRESS) { +            if (path == null) { +                old_path_ref = null; +                return base.button_press_event(event); +            } +             +            EntryWrapper? wrapper = get_wrapper_at_path(path); +             +            if (wrapper == null) { +                old_path_ref = null; +                return base.button_press_event(event); +            } +             +            // Enable single click to toggle tree entries (bug 4985) +            if (wrapper.entry is Sidebar.ExpandableEntry +                || wrapper.entry is Sidebar.InternalDropTargetEntry) { +                // all labels are InternalDropTargetEntries                  toggle_branch_expansion(path, false); -                 -                if (can_rename_path(path)) -                    return false;              } -        } else if (event.button == 1 && event.type == Gdk.EventType.BUTTON_PRESS) { +                          // Is this a click on an already-highlighted tree item? -            Gtk.TreePath? cursor_path = null; -            get_cursor(out cursor_path, null); -            if ((cursor_path != null) && (cursor_path.compare(path) == 0)) { +            if ((old_path_ref != null) && (old_path_ref.get_path() != null) +                && (old_path_ref.get_path().compare(path) == 0)) {                  // yes, don't allow single-click editing, but                   // pass the event on for dragging.                  text_renderer.editable = false; @@ -914,9 +946,13 @@ public class Sidebar.Tree : Gtk.TreeView {              // Got click on different tree item, make sure it is editable              // if it needs to be. -            if (path != null && get_wrapper_at_path(path).entry is Sidebar.RenameableEntry) { +            if (wrapper.entry is Sidebar.RenameableEntry && +                ((Sidebar.RenameableEntry) wrapper.entry).is_user_renameable()) {                  text_renderer.editable = true;              } +             +            // Remember what tree item is highlighted for next time. +            old_path_ref = new Gtk.TreeRowReference(store, path);          }          return base.button_press_event(event); @@ -1106,6 +1142,9 @@ public class Sidebar.Tree : Gtk.TreeView {          if (renameable == null)              return false; +        if (wrapper.entry is Sidebar.Header) +            return false; +                  get_selection().select_path(path);          return true; diff --git a/src/sidebar/common.vala b/src/sidebar/common.vala index 36adfff..0f1bc05 100644 --- a/src/sidebar/common.vala +++ b/src/sidebar/common.vala @@ -1,39 +1,42 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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.   */  // A simple grouping Entry that is only expandable -public class Sidebar.Grouping : Object, Sidebar.Entry, Sidebar.ExpandableEntry { +public class Sidebar.Grouping : Object, Sidebar.Entry, Sidebar.ExpandableEntry, +    Sidebar.RenameableEntry { +          private string name; -    private Icon? open_icon; -    private Icon? closed_icon; +    private string? tooltip; +    private string? icon; -    public Grouping(string name, Icon? open_icon, Icon? closed_icon = null) { +    public Grouping(string name, string? icon, string? tooltip = null) {          this.name = name; -        this.open_icon = open_icon; -        this.closed_icon = closed_icon ?? open_icon; +        this.icon = icon; +        this.tooltip = tooltip;      } -    public string get_sidebar_name() { -        return name; +    public void rename(string name) { +        this.name = name; +        sidebar_name_changed(name);      } -    public string? get_sidebar_tooltip() { -        return name; +    public bool is_user_renameable() { +        return false;      } -    public Icon? get_sidebar_icon() { -        return null; +    public string get_sidebar_name() { +        return name;      } -    public Icon? get_sidebar_open_icon() { -        return open_icon; +    public string? get_sidebar_tooltip() { +        return tooltip;      } -    public Icon? get_sidebar_closed_icon() { -        return closed_icon; +    public string? get_sidebar_icon() { +        return icon;      }      public string to_string() { @@ -61,7 +64,7 @@ public abstract class Sidebar.SimplePageEntry : Object, Sidebar.Entry, Sidebar.S          return get_sidebar_name();      } -    public abstract Icon? get_sidebar_icon(); +    public abstract string? get_sidebar_icon();      public virtual string to_string() {          return get_sidebar_name(); @@ -107,6 +110,26 @@ public class Sidebar.RootOnlyBranch : Sidebar.Branch {      }  } +/** + * A header is an entry that is visually distinguished from its children. Bug 6397 recommends + * headers to appear bolded and without any icons. To prevent the icons from rendering, we set the + * icons to null in the base class @see Sidebar.Grouping. But we also go a step further by + * using a custom cell_data_function (@see Sidebar.Tree::icon_renderer_function) which ensures that + * header icons won't be rendered. This approach avoids the blank icon spacing issues. + */ +public class Sidebar.Header : Sidebar.Grouping, Sidebar.EmphasizableEntry { +    private bool emphasized; +     +    public Header(string name, bool emphasized = true) { +        base(name, null); +        this.emphasized = emphasized; +    } +     +    public bool is_emphasized() { +        return emphasized; +    } +} +  public interface Sidebar.Contextable : Object {      // Return null if the context menu should not be invoked for this event      public abstract Gtk.Menu? get_sidebar_context_menu(Gdk.EventButton? event); diff --git a/src/slideshow/Slideshow.vala b/src/slideshow/Slideshow.vala index d55e3d6..7d20f91 100644 --- a/src/slideshow/Slideshow.vala +++ b/src/slideshow/Slideshow.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/slideshow/TransitionEffects.vala b/src/slideshow/TransitionEffects.vala index 7b10543..5acc36d 100644 --- a/src/slideshow/TransitionEffects.vala +++ b/src/slideshow/TransitionEffects.vala @@ -1,5 +1,5 @@  /* Copyright 2010 Maxim Kartashev - * Copyright 2011-2014 Yorba Foundation + * Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/tags/Branch.vala b/src/tags/Branch.vala index 71bf424..e68b2b1 100644 --- a/src/tags/Branch.vala +++ b/src/tags/Branch.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. @@ -8,7 +8,7 @@ public class Tags.Branch : Sidebar.Branch {      private Gee.HashMap<Tag, Tags.SidebarEntry> entry_map = new Gee.HashMap<Tag, Tags.SidebarEntry>();      public Branch() { -        base (new Tags.Grouping(), +        base (new Tags.Header(),              Sidebar.Branch.Options.HIDE_IF_EMPTY                  | Sidebar.Branch.Options.AUTO_OPEN_ON_NEW_CHILD                  | Sidebar.Branch.Options.STARTUP_OPEN_GROUPING, @@ -31,6 +31,10 @@ public class Tags.Branch : Sidebar.Branch {          return entry_map.get(tag);      } +    public bool is_user_renameable() { +        return true; +    } +          private static int comparator(Sidebar.Entry a, Sidebar.Entry b) {          if (a == b)              return 0; @@ -118,13 +122,13 @@ public class Tags.Branch : Sidebar.Branch {      }  } -public class Tags.Grouping : Sidebar.Grouping, Sidebar.InternalDropTargetEntry,  +public class Tags.Header : Sidebar.Header, Sidebar.InternalDropTargetEntry,       Sidebar.InternalDragSourceEntry, Sidebar.Contextable {      private Gtk.UIManager ui = new Gtk.UIManager();      private Gtk.Menu? context_menu = null; -    public Grouping() { -        base (_("Tags"), new ThemedIcon(Resources.ICON_TAGS)); +    public Header() { +        base (_("Tags"));          setup_context_menu();      } @@ -199,7 +203,7 @@ public class Tags.Grouping : Sidebar.Grouping, Sidebar.InternalDropTargetEntry,  public class Tags.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntry,      Sidebar.DestroyableEntry, Sidebar.InternalDropTargetEntry, Sidebar.ExpandableEntry,      Sidebar.InternalDragSourceEntry { -    private static Icon single_tag_icon; +    private string single_tag_icon = Resources.ICON_ONE_TAG;      private Tag tag; @@ -208,11 +212,9 @@ public class Tags.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr      }      internal static void init() { -        single_tag_icon = new ThemedIcon(Resources.ICON_ONE_TAG);      }      internal static void terminate() { -        single_tag_icon = null;      }      public Tag for_tag() { @@ -223,7 +225,7 @@ public class Tags.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr          return tag.get_user_visible_name();      } -    public override Icon? get_sidebar_icon() { +    public override string? get_sidebar_icon() {          return single_tag_icon;      } @@ -231,6 +233,10 @@ public class Tags.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr          return new TagPage(tag);      } +    public bool is_user_renameable() { +        return true; +    } +          public void rename(string new_name) {          string? prepped = Tag.prep_tag_name(new_name);          if (prepped == null) @@ -290,14 +296,6 @@ public class Tags.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntr          return false;      } -    public Icon? get_sidebar_open_icon() { -        return single_tag_icon; -    } -     -    public Icon? get_sidebar_closed_icon() { -        return single_tag_icon; -    } -          public bool expand_on_select() {          return false;      } diff --git a/src/tags/HierarchicalTagIndex.vala b/src/tags/HierarchicalTagIndex.vala index 58b5f89..abc1f20 100644 --- a/src/tags/HierarchicalTagIndex.vala +++ b/src/tags/HierarchicalTagIndex.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/tags/HierarchicalTagUtilities.vala b/src/tags/HierarchicalTagUtilities.vala index dbb7165..a455bbf 100644 --- a/src/tags/HierarchicalTagUtilities.vala +++ b/src/tags/HierarchicalTagUtilities.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/tags/TagPage.vala b/src/tags/TagPage.vala index f3ef237..2eebc42 100644 --- a/src/tags/TagPage.vala +++ b/src/tags/TagPage.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/tags/Tags.vala b/src/tags/Tags.vala index 7d02a2f..0639cdc 100644 --- a/src/tags/Tags.vala +++ b/src/tags/Tags.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/threads/BackgroundJob.vala b/src/threads/BackgroundJob.vala index 178211e..8203307 100644 --- a/src/threads/BackgroundJob.vala +++ b/src/threads/BackgroundJob.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/threads/Semaphore.vala b/src/threads/Semaphore.vala index dfb0a2f..31d2b2d 100644 --- a/src/threads/Semaphore.vala +++ b/src/threads/Semaphore.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/threads/Threads.vala b/src/threads/Threads.vala index 0e1b1ec..b9bcd55 100644 --- a/src/threads/Threads.vala +++ b/src/threads/Threads.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/threads/Workers.vala b/src/threads/Workers.vala index 756eb01..a97b557 100644 --- a/src/threads/Workers.vala +++ b/src/threads/Workers.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/unit/Unit.vala b/src/unit/Unit.vala index f297974..e6c7228 100644 --- a/src/unit/Unit.vala +++ b/src/unit/Unit.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/unit/rc/template.vala b/src/unit/rc/template.vala index 4869700..8199c01 100644 --- a/src/unit/rc/template.vala +++ b/src/unit/rc/template.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/util/KeyValueMap.vala b/src/util/KeyValueMap.vala index c1f5a55..cf52719 100644 --- a/src/util/KeyValueMap.vala +++ b/src/util/KeyValueMap.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/util/Util.vala b/src/util/Util.vala index c754ff8..701ca04 100644 --- a/src/util/Util.vala +++ b/src/util/Util.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. diff --git a/src/util/file.vala b/src/util/file.vala index 1b6bb6c..8af5ca1 100644 --- a/src/util/file.vala +++ b/src/util/file.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 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. diff --git a/src/util/image.vala b/src/util/image.vala index e8f93ba..4485fc7 100644 --- a/src/util/image.vala +++ b/src/util/image.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/util/misc.vala b/src/util/misc.vala index 73ce428..1507e02 100644 --- a/src/util/misc.vala +++ b/src/util/misc.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/util/string.vala b/src/util/string.vala index 9fda007..3574249 100644 --- a/src/util/string.vala +++ b/src/util/string.vala @@ -1,4 +1,4 @@ -/* Copyright 2010-2014 Yorba Foundation +/* Copyright 2010-2015 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. diff --git a/src/util/system.vala b/src/util/system.vala index 9407405..8e5a07f 100644 --- a/src/util/system.vala +++ b/src/util/system.vala @@ -1,4 +1,4 @@ -/* Copyright 2009-2014 Yorba Foundation +/* Copyright 2009-2015 Yorba Foundation   *   * This software is licensed under the GNU LGPL (version 2.1 or later).   * See the COPYING file in this distribution. diff --git a/src/util/ui.vala b/src/util/ui.vala index 9f66de8..b846f22 100644 --- a/src/util/ui.vala +++ b/src/util/ui.vala @@ -1,4 +1,4 @@ -/* Copyright 2011-2014 Yorba Foundation +/* Copyright 2011-2015 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. | 
