Commit b2d6cefe authored by Jim Nelson's avatar Jim Nelson

#3188: Find button added to toolbars on pages that show media (but not pages...

#3188: Find button added to toolbars on pages that show media (but not pages that show events).  Some other code cleanup too, including moving to a single Gtk.ActionGroup for common actions, meaning that LibraryWindow doesn't have to synchronize actions when pages are switched from (and that pages can monitor those actions for their own state, which cleans up EventDirectoryPage a bit).
parent 2f11b89a
......@@ -88,7 +88,7 @@ public class FullscreenWindow : PageWindow {
// call to set_default_size() saves one repaint caused by changing
// size from default to full screen. In slideshow mode, this change
// also causes pixbuf cache updates, so it really saves some work.
// also causes pixbuf cache updates, so it really saves some work.
set_default_size(get_screen().get_width(), get_screen().get_height());
// need to create a Gdk.Window to set masks
......@@ -424,11 +424,16 @@ public abstract class AppWindow : PageWindow {
private static FullscreenWindow fullscreen_window = null;
private static CommandManager command_manager = null;
// the AppWindow maintains its own UI manager because the first UIManager an action group is
// added to is the one that claims its accelerators
protected Gtk.UIManager ui = new Gtk.UIManager();
protected bool maximized = false;
protected Dimensions dimensions;
protected int pos_x = 0;
protected int pos_y = 0;
private Gtk.ActionGroup common_action_group = new Gtk.ActionGroup("AppWindowGlobalActionGroup");
public AppWindow() {
// although there are multiple AppWindow types, only one may exist per-process
assert(instance == null);
......@@ -457,9 +462,27 @@ public abstract class AppWindow : PageWindow {
assert(command_manager == null);
command_manager = new CommandManager();
command_manager.altered.connect(on_command_manager_altered);
// Because the first UIManager to associated with an ActionGroup claims the accelerators,
// need to create the AppWindow's ActionGroup early on and add it to an application-wide
// UIManager. In order to activate those accelerators, we need to create a dummy UI string
// that lists all the common actions. We build it on-the-fly from the actions associated
// with each ActionGroup while we're adding the groups to the UIManager.
Gtk.ActionGroup[] groups = create_common_action_groups();
foreach (Gtk.ActionGroup group in groups)
ui.insert_action_group(group, 0);
try {
ui.add_ui_from_string(build_dummy_ui_string("CommonMenuBar", groups), -1);
} catch (Error err) {
error("Unable to add AppWindow UI: %s", err.message);
}
ui.ensure_update();
add_accel_group(ui.get_accel_group());
}
private Gtk.ActionEntry[] create_actions() {
private Gtk.ActionEntry[] create_common_actions() {
Gtk.ActionEntry[] actions = new Gtk.ActionEntry[0];
Gtk.ActionEntry quit = { "CommonQuit", Gtk.STOCK_QUIT, TRANSLATABLE, "<Ctrl>Q",
......@@ -692,11 +715,22 @@ public abstract class AppWindow : PageWindow {
sys_show_uri(window.get_screen(), url);
}
public virtual void add_common_actions(Gtk.ActionGroup action_group) {
action_group.add_actions(create_actions(), this);
protected virtual Gtk.ActionGroup[] create_common_action_groups() {
Gtk.ActionGroup[] groups = new Gtk.ActionGroup[0];
common_action_group.add_actions(create_common_actions(), this);
groups += common_action_group;
return groups;
}
public virtual void add_common_action_groups(Gtk.UIManager ui) {
public Gtk.ActionGroup[] get_common_action_groups() {
Gtk.ActionGroup[] groups = new Gtk.ActionGroup[0];
foreach (Gtk.ActionGroup group in ui.get_action_groups())
groups += group;
return groups;
}
public virtual void replace_common_placeholders(Gtk.UIManager ui) {
......@@ -741,25 +775,27 @@ public abstract class AppWindow : PageWindow {
}
public Gtk.Action? get_common_action(string name) {
Page? page = get_current_page();
if (page == null) {
warning("No page to set action %s", name);
return null;
foreach (Gtk.ActionGroup group in ui.get_action_groups()) {
Gtk.Action? action = group.get_action(name);
if (action != null)
return action;
}
return page.get_common_action(name);
warning("No common action found: %s", name);
return null;
}
public void set_common_action_sensitive(string name, bool sensitive) {
Page? page = get_current_page();
if (page == null) {
warning("No page to set action %s", name);
return;
}
page.set_common_action_sensitive(name, sensitive);
Gtk.Action? action = get_common_action(name);
if (action != null)
action.sensitive = sensitive;
}
public void set_common_action_important(string name, bool important) {
Gtk.Action? action = get_common_action(name);
if (action != null)
action.is_important = important;
}
protected override void switched_pages(Page? old_page, Page? new_page) {
......@@ -856,5 +892,21 @@ public abstract class AppWindow : PageWindow {
return base.configure_event(event);
}
protected override bool pause_keyboard_trapping() {
bool paused = base.pause_keyboard_trapping();
if (paused)
remove_accel_group(ui.get_accel_group());
return paused;
}
protected override bool resume_keyboard_trapping() {
bool unpaused = base.resume_keyboard_trapping();
if (unpaused)
add_accel_group(ui.get_accel_group());
return unpaused;
}
}
......@@ -26,60 +26,33 @@ public abstract class CollectionPage : MediaPage {
}
}
private Gtk.ToolButton rotate_button = null;
private ExporterUI exporter = null;
private CollectionSearchViewFilter search_filter = new CollectionSearchViewFilter();
public CollectionPage(string page_name) {
base (page_name);
get_view().items_altered.connect(on_photos_altered);
init_item_context_menu("/CollectionContextMenu");
// set up page's toolbar (used by AppWindow for layout)
Gtk.Toolbar toolbar = get_toolbar();
// rotate tool
rotate_button = new Gtk.ToolButton.from_stock("");
rotate_button.set_related_action(get_action("RotateClockwise"));
rotate_button.set_label(Resources.ROTATE_CW_LABEL);
toolbar.insert(rotate_button, -1);
// enhance tool
Gtk.ToolButton enhance_button = new Gtk.ToolButton.from_stock(Resources.ENHANCE);
enhance_button.set_related_action(get_action("Enhance"));
toolbar.insert(enhance_button, -1);
// separator
toolbar.insert(new Gtk.SeparatorToolItem(), -1);
// publish button
Gtk.ToolButton publish_button = new Gtk.ToolButton.from_stock("");
publish_button.set_related_action(get_action("Publish"));
publish_button.set_icon_name(Resources.PUBLISH);
publish_button.set_label(Resources.PUBLISH_LABEL);
get_view().items_altered.connect(on_photos_altered);
toolbar.insert(publish_button, -1);
init_item_context_menu("/CollectionContextMenu");
init_toolbar("/CollectionToolbar");
// separator to force slider to right side of toolbar
Gtk.SeparatorToolItem separator = new Gtk.SeparatorToolItem();
separator.set_expand(true);
separator.set_draw(false);
toolbar.insert(separator, -1);
get_toolbar().insert(separator, -1);
Gtk.SeparatorToolItem drawn_separator = new Gtk.SeparatorToolItem();
drawn_separator.set_expand(false);
drawn_separator.set_draw(true);
toolbar.insert(drawn_separator, -1);
get_toolbar().insert(drawn_separator, -1);
// zoom slider assembly
MediaPage.ZoomSliderAssembly zoom_slider_assembly = create_zoom_slider_assembly();
connect_slider(zoom_slider_assembly);
toolbar.insert(zoom_slider_assembly, -1);
get_toolbar().insert(zoom_slider_assembly, -1);
show_all();
......@@ -269,7 +242,20 @@ public abstract class CollectionPage : MediaPage {
private bool selection_has_photo() {
return MediaSourceCollection.has_photo((Gee.Collection<MediaSource>) get_view().get_selected_sources());
}
protected override void init_actions(int selected_count, int count) {
base.init_actions(selected_count, count);
set_action_short_label("RotateClockwise", Resources.ROTATE_CW_LABEL);
set_action_short_label("RotateCounterclockwise", Resources.ROTATE_CCW_LABEL);
set_action_short_label("Publish", Resources.PUBLISH_LABEL);
set_action_important("RotateClockwise", true);
set_action_important("RotateCounterclockwise", true);
set_action_important("Enhance", true);
set_action_important("Publish", true);
}
protected override void update_actions(int selected_count, int count) {
base.update_actions(selected_count, count);
......@@ -297,11 +283,8 @@ public abstract class CollectionPage : MediaPage {
&& !is_string_empty(Config.get_instance().get_external_raw_app()));
set_action_sensitive("Revert", (!selection_has_videos) && can_revert_selected());
set_action_sensitive("Enhance", (!selection_has_videos) && has_selected);
set_action_important("Enhance", true);
set_action_sensitive("RotateClockwise", (!selection_has_videos) && has_selected);
set_action_important("RotateClockwise", true);
set_action_sensitive("RotateCounterclockwise", (!selection_has_videos) && has_selected);
set_action_important("RotateCounterclockwise", true);
set_action_sensitive("FlipHorizontally", (!selection_has_videos) && has_selected);
set_action_sensitive("FlipVertically", (!selection_has_videos) && has_selected);
set_action_sensitive("AdjustDateTime", (!selection_has_videos) && has_selected);
......@@ -309,6 +292,8 @@ public abstract class CollectionPage : MediaPage {
set_action_sensitive("AddTags", has_selected);
set_action_sensitive("ModifyTags", one_selected);
set_action_sensitive("Slideshow", page_has_photos && (!primary_is_video));
set_action_sensitive("Print", (!selection_has_videos) && has_selected);
set_action_sensitive("Publish", has_selected);
set_action_sensitive("SetBackground", (!selection_has_videos) && has_selected );
if (has_selected) {
......@@ -319,11 +304,6 @@ public abstract class CollectionPage : MediaPage {
: Resources.SET_BACKGROUND_SLIDESHOW_MENU;
}
}
set_action_sensitive("Print", (!selection_has_videos) && has_selected);
set_action_sensitive("Publish", has_selected);
set_action_important("Publish", true);
}
private void on_photos_altered() {
......@@ -707,17 +687,21 @@ public abstract class CollectionPage : MediaPage {
AppWindow.get_instance().go_fullscreen(new SlideshowPage(LibraryPhoto.global, get_view(),
photo));
}
protected override bool on_ctrl_pressed(Gdk.EventKey? event) {
rotate_button.set_related_action(get_action("RotateCounterclockwise"));
rotate_button.set_label(Resources.ROTATE_CCW_LABEL);
Gtk.ToolButton? rotate_button = ui.get_widget("/CollectionToolbar/ToolRotate")
as Gtk.ToolButton;
if (rotate_button != null)
rotate_button.set_related_action(get_action("RotateCounterclockwise"));
return base.on_ctrl_pressed(event);
}
protected override bool on_ctrl_released(Gdk.EventKey? event) {
rotate_button.set_related_action(get_action("RotateClockwise"));
rotate_button.set_label(Resources.ROTATE_CW_LABEL);
Gtk.ToolButton? rotate_button = ui.get_widget("/CollectionToolbar/ToolRotate")
as Gtk.ToolButton;
if (rotate_button != null)
rotate_button.set_related_action(get_action("RotateClockwise"));
return base.on_ctrl_released(event);
}
......
......@@ -2034,3 +2034,91 @@ public Gtk.ResponseType copy_files_dialog() {
return result;
}
public void remove_photos_from_library(Gee.Collection<LibraryPhoto> photos) {
remove_from_app(photos, _("Remove From Library"),
ngettext("Removing Photo From Library", "Removing Photos From Library", photos.size));
}
public void remove_from_app(Gee.Collection<MediaSource> sources, string dialog_title,
string progress_dialog_text) {
if (sources.size == 0)
return;
Gee.ArrayList<LibraryPhoto> photos = new Gee.ArrayList<LibraryPhoto>();
Gee.ArrayList<Video> videos = new Gee.ArrayList<Video>();
MediaSourceCollection.filter_media(sources, photos, videos);
string? user_message = null;
if ((!photos.is_empty) && (!videos.is_empty)) {
user_message = ngettext("This will remove the photo/video from your Shotwell library. Would you also like to move the file to your desktop trash?\n\nThis action cannot be undone.",
"This will remove %d photos/videos from your Shotwell library. Would you also like to move the files to your desktop trash?\n\nThis action cannot be undone.",
sources.size).printf(sources.size);
} else if (!videos.is_empty) {
user_message = ngettext("This will remove the video from your Shotwell library. Would you also like to move the file to your desktop trash?\n\nThis action cannot be undone.",
"This will remove %d videos from your Shotwell library. Would you also like to move the files to your desktop trash?\n\nThis action cannot be undone.",
sources.size).printf(sources.size);
} else {
user_message = ngettext("This will remove the photo from your Shotwell library. Would you also like to move the file to your desktop trash?\n\nThis action cannot be undone.",
"This will remove %d photos from your Shotwell library. Would you also like to move the files to your desktop trash?\n\nThis action cannot be undone.",
sources.size).printf(sources.size);
}
Gtk.ResponseType result = remove_from_library_dialog(AppWindow.get_instance(), dialog_title,
user_message, sources.size);
if (result != Gtk.ResponseType.YES && result != Gtk.ResponseType.NO)
return;
bool delete_backing = (result == Gtk.ResponseType.YES);
AppWindow.get_instance().set_busy_cursor();
ProgressDialog progress = null;
ProgressMonitor monitor = null;
if (sources.size >= 20) {
progress = new ProgressDialog(AppWindow.get_instance(), progress_dialog_text);
monitor = progress.monitor;
}
Gee.ArrayList<LibraryPhoto> not_removed_photos = new Gee.ArrayList<LibraryPhoto>();
Gee.ArrayList<Video> not_removed_videos = new Gee.ArrayList<Video>();
// Remove and attempt to trash.
LibraryPhoto.global.remove_from_app(photos, delete_backing, monitor, not_removed_photos);
Video.global.remove_from_app(videos, delete_backing, monitor, not_removed_videos);
// Check for files we couldn't trash.
int num_not_removed = not_removed_photos.size + not_removed_videos.size;
if (delete_backing && num_not_removed > 0) {
string not_deleted_message =
ngettext("The photo or video cannot be moved to your desktop trash. Delete this file?",
"%d photos/videos cannot be moved to your desktop trash. Delete these files?",
num_not_removed).printf(num_not_removed);
Gtk.ResponseType result_delete = remove_from_filesystem_dialog(AppWindow.get_instance(),
dialog_title, not_deleted_message);
if (Gtk.ResponseType.YES == result_delete) {
// Attempt to delete the files.
Gee.ArrayList<LibraryPhoto> not_deleted_photos = new Gee.ArrayList<LibraryPhoto>();
Gee.ArrayList<Video> not_deleted_videos = new Gee.ArrayList<Video>();
LibraryPhoto.global.delete_backing_files(not_removed_photos, monitor, not_deleted_photos);
Video.global.delete_backing_files(not_removed_videos, monitor, not_deleted_videos);
int num_not_deleted = not_deleted_photos.size + not_deleted_videos.size;
if (num_not_deleted > 0) {
// Alert the user that the files were not removed.
string delete_failed_message =
ngettext("The photo or video cannot be deleted.",
"%d photos/videos cannot be deleted.",
num_not_deleted).printf(num_not_deleted);
AppWindow.error_message_with_title(dialog_title, delete_failed_message, AppWindow.get_instance());
}
}
}
if (progress != null)
progress.close();
AppWindow.get_instance().set_normal_cursor();
}
......@@ -148,7 +148,7 @@ class EventDirectoryItem : CheckerboardItem {
}
}
public class EventsDirectoryPage : CheckerboardPage {
public abstract class EventsDirectoryPage : CheckerboardPage {
public class EventDirectoryManager : ViewManager {
public override DataView create_view(DataSource source) {
return new EventDirectoryItem((Event) source);
......@@ -183,7 +183,7 @@ public class EventsDirectoryPage : CheckerboardPage {
base (page_name);
// set comparator before monitoring source collection, to prevent a re-sort
get_view().set_comparator(get_event_comparator(), event_comparator_predicate);
get_view().set_comparator(get_event_comparator(true), event_comparator_predicate);
get_view().monitor_source_collection(Event.global, view_manager, null, initial_events);
init_item_context_menu("/EventsDirectoryContextMenu");
......@@ -195,17 +195,27 @@ public class EventsDirectoryPage : CheckerboardPage {
// merge tool
Gtk.ToolButton merge_button = new Gtk.ToolButton.from_stock(Resources.MERGE);
merge_button.set_related_action(action_group.get_action("Merge"));
merge_button.set_related_action(get_action("Merge"));
toolbar.insert(merge_button, -1);
}
~EventsDirectoryPage() {
Gtk.RadioAction? action = get_action("CommonSortEventsAscending") as Gtk.RadioAction;
assert(action != null);
action.changed.disconnect(on_sort_changed);
}
protected override void init_collect_ui_filenames(Gee.List<string> ui_filenames) {
ui_filenames.add("events_directory.ui");
base.init_collect_ui_filenames(ui_filenames);
}
protected static bool event_comparator_predicate(DataObject object, Alteration alteration) {
return alteration.has_detail("metadata", "time");
}
private static int64 event_ascending_comparator(void *a, void *b) {
time_t start_a = ((EventDirectoryItem *) a)->event.get_start_time();
time_t start_b = ((EventDirectoryItem *) b)->event.get_start_time();
......@@ -213,16 +223,12 @@ public class EventsDirectoryPage : CheckerboardPage {
return start_a - start_b;
}
protected static bool event_comparator_predicate(DataObject object, Alteration alteration) {
return alteration.has_detail("metadata", "time");
}
private int64 event_descending_comparator(void *a, void *b) {
private static int64 event_descending_comparator(void *a, void *b) {
return event_ascending_comparator(b, a);
}
private Comparator get_event_comparator() {
if (Config.get_instance().get_events_sort_ascending())
private static Comparator get_event_comparator(bool ascending) {
if (ascending)
return event_ascending_comparator;
else
return event_descending_comparator;
......@@ -265,6 +271,14 @@ public class EventsDirectoryPage : CheckerboardPage {
return actions;
}
protected override void init_actions(int selected_count, int count) {
base.init_actions(selected_count, count);
Gtk.RadioAction? action = get_action("CommonSortEventsAscending") as Gtk.RadioAction;
assert(action != null);
action.changed.connect(on_sort_changed);
}
protected override void update_actions(int selected_count, int count) {
set_action_sensitive("Merge", selected_count > 1);
set_action_important("Merge", true);
......@@ -314,8 +328,12 @@ public class EventsDirectoryPage : CheckerboardPage {
return (page != null) ? page.get_fullscreen_photo() : null;
}
public void notify_sort_changed() {
get_view().set_comparator(get_event_comparator(), event_comparator_predicate);
private void on_sort_changed(Gtk.Action action, Gtk.Action c) {
Gtk.RadioAction current = (Gtk.RadioAction) c;
get_view().set_comparator(
get_event_comparator(current.current_value == LibraryWindow.SORT_EVENTS_ORDER_ASCENDING),
event_comparator_predicate);
}
private void on_rename() {
......
......@@ -564,6 +564,7 @@ public class ImportPage : CheckerboardPage {
toolbar.insert(separator, -1);
// progress bar in center of toolbar
progress_bar.set_orientation(Gtk.ProgressBarOrientation.LEFT_TO_RIGHT);
progress_bar.visible = false;
Gtk.ToolItem progress_item = new Gtk.ToolItem();
......@@ -571,14 +572,25 @@ public class ImportPage : CheckerboardPage {
progress_item.add(progress_bar);
toolbar.insert(progress_item, -1);
// Find button
Gtk.ToggleToolButton find_button = new Gtk.ToggleToolButton();
find_button.set_related_action(get_action("CommonDisplaySearchbar"));
toolbar.insert(find_button, -1);
// Separator
toolbar.insert(new Gtk.SeparatorToolItem(), -1);
// Import selected
Gtk.ToolButton import_selected_button = new Gtk.ToolButton.from_stock(Resources.IMPORT);
import_selected_button.set_related_action(action_group.get_action("ImportSelected"));
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);
import_all_button.set_related_action(action_group.get_action("ImportAll"));
import_all_button.set_related_action(get_action("ImportAll"));
toolbar.insert(import_all_button, -1);
......@@ -1355,7 +1367,7 @@ public class ImportPage : CheckerboardPage {
public override void set_display_titles(bool display) {
base.set_display_titles(display);
Gtk.ToggleAction action = (Gtk.ToggleAction) action_group.get_action("ViewTitle");
Gtk.ToggleAction? action = get_action("ViewTitle") as Gtk.ToggleAction;
if (action != null)
action.set_active(display);
}
......@@ -1385,7 +1397,7 @@ public class ImportQueuePage : SinglePhotoPage {
// Stop button
Gtk.ToolButton stop_button = new Gtk.ToolButton.from_stock(Gtk.STOCK_STOP);
stop_button.set_related_action(action_group.get_action("Stop"));
stop_button.set_related_action(get_action("Stop"));
toolbar.insert(stop_button, -1);
......
......@@ -121,6 +121,7 @@ public class LibraryWindow : AppWindow {
private Gtk.Frame bottom_frame = new Gtk.Frame(null);
private Gtk.AccelGroup? paused_accel_group = null;
private Gtk.ActionGroup common_action_group = new Gtk.ActionGroup("LibraryWindowGlobalActionGroup");
// Static (default) pages
private LibraryPage library_page = null;
......@@ -153,8 +154,11 @@ public class LibraryWindow : AppWindow {
private SidebarMarker tags_marker = null;
private bool is_search_toolbar_visible = Config.get_instance().get_search_bar_hidden();
private SearchFilterToolbar search_toolbar = new SearchFilterToolbar();
// Want to instantiate this in the constructor rather than here because the search bar has its
// own UIManager which will suck up the accelerators, and we want them to be associated with
// AppWindows instead.
private SearchFilterToolbar search_toolbar;
private Gtk.VBox top_section = new Gtk.VBox(false, 0);
private Gtk.Frame background_progress_frame = new Gtk.Frame(null);
......@@ -167,7 +171,6 @@ public class LibraryWindow : AppWindow {
private Gtk.Notebook notebook = new Gtk.Notebook();
private Gtk.Box layout = new Gtk.VBox(false, 0);
private bool events_sort_ascending = false;
private int current_progress_priority = 0;
private uint background_progress_pulse_id = 0;
......@@ -220,8 +223,8 @@ public class LibraryWindow : AppWindow {
sidebar.cursor_changed.connect(on_sidebar_cursor_changed);
// set search bar's visibility to default state and add its accelerators to the window
search_toolbar = new SearchFilterToolbar();
search_toolbar.visible = is_search_toolbar_visible;
add_accel_group(search_toolbar.ui.get_accel_group());
create_layout(library_page);
......@@ -337,7 +340,7 @@ public class LibraryWindow : AppWindow {
monitor.auto_import_progress.disconnect(on_library_monitor_auto_import_progress);
}
private Gtk.ActionEntry[] create_actions() {
private Gtk.ActionEntry[] create_common_actions() {
Gtk.ActionEntry[] actions = new Gtk.ActionEntry[0];
Gtk.ActionEntry import = { "CommonFileImport", Resources.IMPORT,
......@@ -352,8 +355,7 @@ public class LibraryWindow : AppWindow {
actions += import_from_alien_db;
}
Gtk.ActionEntry sort = { "CommonSortEvents", null, TRANSLATABLE, null, null,
on_sort_events };
Gtk.ActionEntry sort = { "CommonSortEvents", null, TRANSLATABLE, null, null, null };
sort.label = _("Sort _Events");
actions += sort;
......@@ -390,9 +392,9 @@ public class LibraryWindow : AppWindow {
return actions;
}
private Gtk.ToggleActionEntry[] create_toggle_actions() {
private Gtk.ToggleActionEntry[] create_common_toggle_actions() {
Gtk.ToggleActionEntry[] actions = new Gtk.ToggleActionEntry[0];
Gtk.ToggleActionEntry basic_props = { "CommonDisplayBasicProperties", null,
TRANSLATABLE, "<Ctrl><Shift>I", TRANSLATABLE, on_display_basic_properties, false };
basic_props.label = _("_Basic Information");
......@@ -405,7 +407,7 @@ public class LibraryWindow : AppWindow {
extended_props.tooltip = _("Display extended information for the selection");
actions += extended_props;
Gtk.ToggleActionEntry searchbar = { "CommonDisplaySearchbar", null, TRANSLATABLE,
Gtk.ToggleActionEntry searchbar = { "CommonDisplaySearchbar", Gtk.STOCK_FIND, TRANSLATABLE,
"F8", TRANSLATABLE, on_display_searchbar, is_search_toolbar_visible };
searchbar.label = _("_Search Bar");
searchbar.tooltip = _("Display the search bar");
......@@ -413,10 +415,10 @@ public class LibraryWindow : AppWindow {
return actions;
}
private Gtk.RadioActionEntry[] create_order_actions() {
private void add_common_radio_actions(Gtk.ActionGroup group) {
Gtk.RadioActionEntry[] actions = new Gtk.RadioActionEntry[0];
Gtk.RadioActionEntry ascending = { "CommonSortEventsAscending",
Gtk.STOCK_SORT_ASCENDING, TRANSLATABLE, null, TRANSLATABLE,
SORT_EVENTS_ORDER_ASCENDING };
......@@ -430,8 +432,36 @@ public class LibraryWindow : AppWindow {
descending.label = _("D_escending");
descending.tooltip = _("Sort photos in a descending order");
actions += descending;
return actions;
group.add_radio_actions(actions, SORT_EVENTS_ORDER_ASCENDING, on_events_sort_changed);
}
protected override Gtk.ActionGroup[] create_common_action_groups() {
Gtk.ActionGroup[] groups = base.create_common_action_groups();
common_action_group.add_actions(create_common_actions(), this);
common_action_group.add_toggle_actions(create_common_toggle_actions(), this);
add_common_radio_actions(common_action_group);
Gtk.Action? action = common_action_group.get_action("CommonDisplaySearchbar");
if (action != null) {
action.short_label = Resources.FIND_LABEL;
action.is_important = true;
}
groups += common_action_group;
groups += SearchFilterActions.get_instance().get_action_group();
return groups;
}
public override void replace_common_placeholders(Gtk.UIManager ui) {
base.replace_common_placeholders(ui);
// Adds one menu entry per alien database driver
AlienDb.AlienDatabaseHandler.get_instance().add_menu_entries(
ui, "/MenuBar/FileMenu/CommonImportFromAlienDbPlaceholder"
);
}
// show_all() may make visible certain items we wish to keep programmatically hidden
......@@ -459,7 +489,7 @@ public class LibraryWindow : AppWindow {
return (LibraryWindow) instance;
}
private int64 get_event_directory_page_time(SubEventsDirectoryPage.Stub *stub) {
private static int64 get_event_directory_page_time(SubEventsDirectoryPage.Stub *stub) {
return (stub->get_year() * 100) + stub->get_month();
}
......@@ -473,10 +503,10 @@ public class LibraryWindow : AppWindow {
start_b = get_event_directory_page_time((SubEventsDirectoryPage.Stub *) b);
} else if (a is NoEventPage.Stub) {
assert(b is SubEventsDirectoryPage.Stub || b is EventPage.Stub);
return events_sort_ascending ? 1 : -1;
return get_events_sort() == SORT_EVENTS_ORDER_ASCENDING ? 1 : -1;
} else if (b is NoEventPage.Stub) {
assert(a is SubEventsDirectoryPage.Stub || a is EventPage.Stub);
return events_sort_ascending ? -1 : 1;
return get_events_sort() == SORT_EVENTS_ORDER_ASCENDING ? -1 : 1;
} else {
assert(a is EventPage.Stub);
assert(b is EventPage.Stub);
......@@ -516,30 +546,6 @@ public class LibraryWindow : AppWindow {
return false;
}
public override void add_common_actions(Gtk.ActionGroup action_group) {
base.add_common_actions(action_group);
action_group.add_actions(create_actions(), this);
action_group.add_toggle_actions(create_toggle_actions(), this);
action_group.add_radio_actions(create_order_actions(),
SORT_EVENTS_ORDER_ASCENDING, on_events_sort_changed);
}
public override void add_common_action_groups(Gtk.UIManager ui) {
base.add_common_action_groups(ui);
ui.insert_action_group(SearchFilterActions.get_instance().get_action_group(), 0);
}
public override void replace_common_placeholders(Gtk.UIManager ui) {
base.replace_common_placeholders(ui);
// Adds one menu entry per alien database driver
AlienDb.AlienDatabaseHandler.get_instance().add_menu_entries(
ui, "/MenuBar/FileMenu/CommonImportFromAlienDbPlaceholder"
);
}
public override string get_app_role() {
return Resources.APP_LIBRARY_ROLE;
}
......@@ -707,49 +713,23 @@ public class LibraryWindow : AppWindow {
}
public int get_events_sort() {
return events_sort_ascending ? SORT_EVENTS_ORDER_ASCENDING : SORT_EVENTS_ORDER_DESCENDING;
}
private void on_sort_events() {
// any member of the group can be told the current value
Gtk.RadioAction action = (Gtk.RadioAction) get_current_page().common_action_group.get_action(
"CommonSortEventsAscending");