Commit 2ea3dbc6 authored by Jim Nelson's avatar Jim Nelson

#2306: Remove files from the Missing Files page.

parent 84282b93
......@@ -495,6 +495,12 @@ public abstract class AppWindow : PageWindow {
jump_to_file.tooltip = Resources.JUMP_TO_FILE_TOOLTIP;
actions += jump_to_file;
Gtk.ActionEntry select_all = { "CommonSelectAll", Gtk.STOCK_SELECT_ALL, TRANSLATABLE,
"<Ctrl>A", TRANSLATABLE, on_select_all };
select_all.label = Resources.SELECT_ALL_MENU;
select_all.tooltip = Resources.SELECT_ALL_TOOLTIP;
actions += select_all;
return actions;
}
......@@ -694,8 +700,8 @@ public abstract class AppWindow : PageWindow {
present();
}
protected bool set_common_action_sensitive(string name, bool sensitive) {
public bool set_common_action_sensitive(string name, bool sensitive) {
Page? page = get_current_page();
if (page == null) {
warning("No page to set action %s", name);
......@@ -714,20 +720,29 @@ public abstract class AppWindow : PageWindow {
return true;
}
protected override void switched_pages(Page? old_page, Page? new_page) {
set_common_action_sensitive("CommonJumpToFile",
get_current_page().get_view().get_selected_count() == 1);
if (old_page != null)
if (old_page != null) {
old_page.get_view().selection_group_altered.disconnect(on_selection_group_altered);
old_page.get_view().items_state_changed.disconnect(on_items_altered);
if (new_page != null)
}
if (new_page != null) {
new_page.get_view().selection_group_altered.connect(on_selection_group_altered);
new_page.get_view().items_state_changed.connect(on_items_altered);
set_common_action_sensitive("CommonSelectAll", new_page.get_view().get_count() > 0);
set_common_action_sensitive("CommonJumpToFile",
new_page.get_view().get_selected_count() == 1);
}
base.switched_pages(old_page, new_page);
}
private void on_selection_group_altered() {
set_common_action_sensitive("CommonSelectAll", get_current_page().get_view().get_count() > 0);
}
private void on_items_altered() {
set_common_action_sensitive("CommonJumpToFile",
get_current_page().get_view().get_selected_count() == 1);
......@@ -744,7 +759,13 @@ public abstract class AppWindow : PageWindow {
private void on_redo() {
command_manager.redo();
}
private void on_select_all() {
Page? page = get_current_page();
if (page != null)
page.get_view().select_all();
}
private override bool configure_event(Gdk.EventConfigure event) {
if (window.get_state() == Gdk.WindowState.MAXIMIZED)
maximized = !maximized;
......
......@@ -249,22 +249,16 @@ public abstract class CollectionPage : CheckerboardPage {
event.label = _("Even_ts");
actions += event;
Gtk.ActionEntry select_all = { "SelectAll", Gtk.STOCK_SELECT_ALL, TRANSLATABLE,
"<Ctrl>A", TRANSLATABLE, on_select_all };
select_all.label = _("Select _All");
select_all.tooltip = _("Select all the photos in the library");
actions += select_all;
Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Gtk.STOCK_REMOVE, TRANSLATABLE, null,
TRANSLATABLE, on_remove_from_library };
Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Gtk.STOCK_REMOVE, TRANSLATABLE,
null, TRANSLATABLE, on_remove_from_library };
remove_from_library.label = Resources.REMOVE_FROM_LIBRARY_MENU;
remove_from_library.tooltip = _("Remove the selected photos from the library");
remove_from_library.tooltip = Resources.REMOVE_FROM_LIBRARY_PLURAL_TOOLTIP;
actions += remove_from_library;
Gtk.ActionEntry move_to_trash = { "MoveToTrash", "user-trash-full", TRANSLATABLE, "Delete",
TRANSLATABLE, on_move_to_trash };
move_to_trash.label = Resources.MOVE_TO_TRASH_MENU;
move_to_trash.tooltip = _("Move the selected photos to the trash");
move_to_trash.tooltip = Resources.MOVE_TO_TRASH_PLURAL_TOOLTIP;
actions += move_to_trash;
Gtk.ActionEntry photos = { "PhotosMenu", null, TRANSLATABLE, null, null,
......@@ -963,7 +957,6 @@ public abstract class CollectionPage : CheckerboardPage {
private void on_edit_menu() {
decorate_undo_item("/CollectionMenuBar/EditMenu/Undo");
decorate_redo_item("/CollectionMenuBar/EditMenu/Redo");
set_item_sensitive("/CollectionMenuBar/EditMenu/SelectAll", get_view().get_count() > 0);
}
private void on_events_menu() {
......@@ -975,10 +968,6 @@ public abstract class CollectionPage : CheckerboardPage {
set_item_sensitive("/CollectionMenuBar/TagsMenu/ModifyTags", get_view().get_selected_count() == 1);
}
private void on_select_all() {
get_view().select_all();
}
private bool can_revert_selected() {
foreach (DataView view in get_view().get_selected()) {
LibraryPhoto photo = ((Thumbnail) view).get_photo();
......@@ -1064,9 +1053,7 @@ public abstract class CollectionPage : CheckerboardPage {
}
private void on_remove_from_library() {
remove_from_app((Gee.Collection<LibraryPhoto>) get_view().get_selected_sources(),
_("Remove From Library"), ngettext("Removing Photo From Library", "Removing Photos From Library",
get_view().get_selected_count()));
remove_photos_from_library((Gee.Collection<LibraryPhoto>) get_view().get_selected_sources());
}
private void on_move_to_trash() {
......
......@@ -586,6 +586,28 @@ public bool revert_editable_dialog(Gtk.Window owner, Gee.Collection<Photo> photo
return result == Gtk.ResponseType.YES;
}
public bool remove_offline_dialog(Gtk.Window owner, int count) {
if (count == 0)
return false;
string msg = ngettext(
"This will remove the photo from the library. Continue?",
"This will remove %d photos from the library. Continue?",
count).printf(count);
Gtk.MessageDialog dialog = new Gtk.MessageDialog(owner, Gtk.DialogFlags.MODAL,
Gtk.MessageType.WARNING, Gtk.ButtonsType.NONE, "%s", msg);
dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL);
dialog.add_button(_("_Remove"), Gtk.ResponseType.OK);
dialog.title = ngettext("Remove Photo From Library", "Remove Photos From Library", count);
Gtk.ResponseType result = (Gtk.ResponseType) dialog.run();
dialog.destroy();
return result == Gtk.ResponseType.OK;
}
public class ProgressDialog : Gtk.Window {
private Gtk.ProgressBar progress_bar = new Gtk.ProgressBar();
private Gtk.Button cancel_button = null;
......
......@@ -236,12 +236,6 @@ public class EventsDirectoryPage : CheckerboardPage {
merge.tooltip = Resources.MERGE_TOOLTIP;
actions += merge;
Gtk.ActionEntry select_all = { "SelectAll", Gtk.STOCK_SELECT_ALL, TRANSLATABLE,
"<Ctrl>A", TRANSLATABLE, on_select_all };
select_all.label = _("Select _All");
select_all.tooltip = _("Select all the events in the directory");
actions += select_all;
return actions;
}
......@@ -303,10 +297,6 @@ public class EventsDirectoryPage : CheckerboardPage {
get_view().get_selected_count() == 1);
}
private void on_select_all() {
get_view().select_all();
}
private void on_rename() {
// only rename one at a time
if (get_view().get_selected_count() != 1)
......
......@@ -470,12 +470,6 @@ public class ImportPage : CheckerboardPage {
edit.label = _("_Edit");
actions += edit;
Gtk.ActionEntry select_all = { "SelectAll", Gtk.STOCK_SELECT_ALL, TRANSLATABLE,
"<Ctrl>A", TRANSLATABLE, on_select_all };
select_all.label = _("Select _All");
select_all.tooltip = _("Select all the photos for importing");
actions += select_all;
Gtk.ActionEntry view = { "ViewMenu", null, TRANSLATABLE, null, null, null };
view.label = _("_View");
actions += view;
......@@ -1016,11 +1010,8 @@ public class ImportPage : CheckerboardPage {
}
private void on_edit_menu() {
set_item_sensitive("/ImportMenuBar/EditMenu/SelectAll", !busy && (get_view().get_count() > 0));
}
private void on_select_all() {
get_view().select_all();
AppWindow.get_instance().set_common_action_sensitive("CommonSelectAll",
!busy && (get_view().get_count() > 0));
}
private void import(Gee.Iterable<DataObject> items) {
......
......@@ -18,6 +18,16 @@ public class OfflinePage : CheckerboardPage {
init_ui("offline.ui", "/OfflineMenuBar", "OfflineActionGroup", create_actions());
get_view().selection_group_altered.connect(on_selection_group_altered);
Gtk.Toolbar toolbar = get_toolbar();
// delete button
Gtk.ToolButton delete_button = new Gtk.ToolButton.from_stock(Gtk.STOCK_DELETE);
delete_button.set_related_action(action_group.get_action("RemoveFromLibrary"));
toolbar.insert(delete_button, -1);
// monitor offline and initialize view with all items in it
LibraryPhoto.global.offline_contents_altered.connect(on_offline_contents_altered);
on_offline_contents_altered(LibraryPhoto.global.get_offline(), null);
......@@ -34,6 +44,12 @@ public class OfflinePage : CheckerboardPage {
edit.label = _("_Edit");
actions += edit;
Gtk.ActionEntry remove = { "RemoveFromLibrary", Gtk.STOCK_DELETE, TRANSLATABLE, "Delete",
TRANSLATABLE, on_remove_from_library };
remove.label = Resources.DELETE_PHOTOS_MENU;
remove.tooltip = Resources.DELETE_FROM_LIBRARY_TOOLTIP;
actions += remove;
Gtk.ActionEntry view = { "ViewMenu", null, TRANSLATABLE, null, TRANSLATABLE, null };
view.label = _("_View");
actions += view;
......@@ -45,6 +61,22 @@ public class OfflinePage : CheckerboardPage {
return actions;
}
protected override void init_actions(int selected_count, int count) {
update_actions(selected_count, count);
action_group.get_action("RemoveFromLibrary").is_important = true;
base.init_actions(selected_count, count);
}
private void on_selection_group_altered() {
update_actions(get_view().get_selected_count(), get_view().get_count());
}
private void update_actions(int selected_count, int count) {
set_action_sensitive("RemoveFromLibrary", selected_count > 0);
}
private void on_offline_contents_altered(Gee.Collection<LibraryPhoto>? added,
Gee.Collection<LibraryPhoto>? removed) {
if (added != null) {
......@@ -65,6 +97,34 @@ public class OfflinePage : CheckerboardPage {
decorate_redo_item("/OfflineMenuBar/EditMenu/Redo");
}
private void on_remove_from_library() {
Gee.Collection<LibraryPhoto> photos =
(Gee.Collection<LibraryPhoto>) get_view().get_selected_sources();
if (photos.size == 0)
return;
if (!remove_offline_dialog(AppWindow.get_instance(), photos.size))
return;
AppWindow.get_instance().set_busy_cursor();
ProgressDialog progress = null;
if (photos.size >= 20)
progress = new ProgressDialog(AppWindow.get_instance(), _("Deleting..."));
// valac complains about passing an argument for a delegate using ternary operator:
// https://bugzilla.gnome.org/show_bug.cgi?id=599349
if (progress != null)
LibraryPhoto.global.remove_from_app(photos, false, progress.monitor);
else
LibraryPhoto.global.remove_from_app(photos, false);
if (progress != null)
progress.close();
AppWindow.get_instance().set_normal_cursor();
}
public override CheckerboardItem? get_fullscreen_photo() {
return null;
}
......
......@@ -2993,7 +2993,7 @@ public class LibraryPhotoSourceCollection : DatabaseSourceCollection {
if (import_id.is_valid()) {
if (!sorted_import_ids.contains(import_id))
sorted_import_ids.add(import_id);
import_rolls.set(photo.get_import_id(), photo);
import_rolls.set(import_id, photo);
import_roll_changed = true;
}
......@@ -3017,10 +3017,8 @@ public class LibraryPhotoSourceCollection : DatabaseSourceCollection {
if (import_id.is_valid()) {
is_removed = import_rolls.remove(import_id, photo);
assert(is_removed);
if (!import_rolls.contains(import_id)) {
is_removed = sorted_import_ids.remove(import_id);
assert(is_removed);
}
if (!import_rolls.contains(import_id))
sorted_import_ids.remove(import_id);
import_roll_changed = true;
}
......
......@@ -2014,16 +2014,17 @@ public class LibraryPhotoPage : EditingHostPage {
Gtk.ActionEntry edit = { "EditMenu", null, TRANSLATABLE, null, null, on_edit_menu };
edit.label = _("_Edit");
actions += edit;
Gtk.ActionEntry remove_from_library = { "RemoveFromLibrary", Gtk.STOCK_REMOVE, TRANSLATABLE, null,
TRANSLATABLE, on_remove_from_library };
remove_from_library.label = Resources.REMOVE_FROM_LIBRARY_MENU;
remove_from_library.tooltip = _("Remove the photo from the library");
actions += remove_from_library;
remove_from_library.tooltip = Resources.REMOVE_FROM_LIBRARY_SINGULAR_TOOLTIP;
actions += remove_from_library;
Gtk.ActionEntry move_to_trash = { "MoveToTrash", "user-trash-full", TRANSLATABLE, "Delete",
TRANSLATABLE, on_move_to_trash };
move_to_trash.label = Resources.MOVE_TO_TRASH_MENU;
move_to_trash.tooltip = _("Move the photo to the trash");
move_to_trash.tooltip = Resources.MOVE_TO_TRASH_SINGULAR_TOOLTIP;
actions += move_to_trash;
Gtk.ActionEntry view = { "ViewMenu", null, TRANSLATABLE, null, null, on_view_menu };
......
......@@ -512,7 +512,8 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,
private string DISPLAY_FIVE_OR_HIGHER_TOOLTIP;
public const string DELETE_PHOTOS_MENU = _("_Delete");
public const string DELETE_PHOTOS_TOOLTIP = _("Remove the selected photos from the trash");
public const string DELETE_FROM_TRASH_TOOLTIP = _("Remove the selected photos from the trash");
public const string DELETE_FROM_LIBRARY_TOOLTIP = _("Remove the selected photos from the library");
public const string RESTORE_PHOTOS_MENU = _("_Restore");
public const string RESTORE_PHOTOS_TOOLTIP = _("Move the selected photos back into the library");
......@@ -525,7 +526,15 @@ along with Shotwell; if not, write to the Free Software Foundation, Inc.,
}
public const string REMOVE_FROM_LIBRARY_MENU = _("R_emove From Library");
public const string REMOVE_FROM_LIBRARY_PLURAL_TOOLTIP = _("Remove the selected photos from the library");
public const string REMOVE_FROM_LIBRARY_SINGULAR_TOOLTIP = _("Remove the photo from the library");
public const string MOVE_TO_TRASH_MENU = _("_Move to Trash");
public const string MOVE_TO_TRASH_PLURAL_TOOLTIP = _("Move the selected photos to the trash");
public const string MOVE_TO_TRASH_SINGULAR_TOOLTIP = _("Move the photo to the trash");
public const string SELECT_ALL_MENU = _("Select _All");
public const string SELECT_ALL_TOOLTIP = _("Select all items");
private Gtk.IconFactory factory = null;
private Gee.HashMap<string, Gdk.Pixbuf> icon_cache = null;
......
......@@ -41,7 +41,6 @@ public class TrashPage : CheckerboardPage {
toolbar.insert(empty_trash_button, -1);
get_view().selection_group_altered.connect(on_selection_altered);
get_view().contents_altered.connect(on_contents_altered);
// monitor trashcan and initialize view with all items in it
LibraryPhoto.global.trashcan_contents_altered.connect(on_trashcan_contents_altered);
......@@ -62,7 +61,7 @@ public class TrashPage : CheckerboardPage {
Gtk.ActionEntry delete_action = { "Delete", Gtk.STOCK_DELETE, TRANSLATABLE, "Delete",
TRANSLATABLE, on_delete };
delete_action.label = Resources.DELETE_PHOTOS_MENU;
delete_action.tooltip = Resources.DELETE_PHOTOS_TOOLTIP;
delete_action.tooltip = Resources.DELETE_FROM_TRASH_TOOLTIP;
actions += delete_action;
Gtk.ActionEntry restore = { "Restore", Gtk.STOCK_UNDELETE, TRANSLATABLE, null, TRANSLATABLE,
......@@ -71,11 +70,6 @@ public class TrashPage : CheckerboardPage {
restore.tooltip = Resources.RESTORE_PHOTOS_TOOLTIP;
actions += restore;
Gtk.ActionEntry select_all = { "SelectAll", Gtk.STOCK_SELECT_ALL, TRANSLATABLE, "<Ctrl>A",
TRANSLATABLE, on_select_all };
select_all.label = _("Select _All");
actions += select_all;
Gtk.ActionEntry view = { "ViewMenu", null, TRANSLATABLE, null, TRANSLATABLE, null };
view.label = _("_View");
actions += view;
......@@ -90,7 +84,6 @@ public class TrashPage : CheckerboardPage {
protected override void init_actions(int selected_count, int count) {
set_action_sensitive("Delete", selected_count > 0);
set_action_sensitive("Restore", selected_count > 0);
set_action_sensitive("SelectAll", count > 0);
action_group.get_action("Delete").is_important = true;
action_group.get_action("Restore").is_important = true;
......@@ -104,10 +97,6 @@ public class TrashPage : CheckerboardPage {
set_action_sensitive("Restore", get_view().get_selected_count() > 0);
}
private void on_contents_altered() {
set_action_sensitive("SelectAll", get_view().get_count() > 0);
}
private void on_trashcan_contents_altered(Gee.Collection<LibraryPhoto>? added,
Gee.Collection<LibraryPhoto>? removed) {
if (added != null) {
......@@ -136,10 +125,6 @@ public class TrashPage : CheckerboardPage {
(Gee.Collection<LibraryPhoto>) get_view().get_selected_sources(), false));
}
private void on_select_all() {
get_view().select_all();
}
public override CheckerboardItem? get_fullscreen_photo() {
return null;
}
......
......@@ -592,34 +592,39 @@ public class OpTimer {
}
}
private void remove_from_app(Gee.Collection<LibraryPhoto> photos, string dialog_title,
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<LibraryPhoto> photos, string dialog_title,
string progress_dialog_text) {
if (photos.size == 0)
return;
Gtk.ResponseType result = remove_from_library_dialog(AppWindow.get_instance(), dialog_title, photos.size);
if (result != Gtk.ResponseType.YES && result != Gtk.ResponseType.NO)
return;
Gtk.ResponseType result = remove_from_library_dialog(AppWindow.get_instance(), dialog_title, photos.size);
if (result != Gtk.ResponseType.YES && result != Gtk.ResponseType.NO)
return;
bool delete_backing = (result == Gtk.ResponseType.YES);
bool delete_backing = (result == Gtk.ResponseType.YES);
AppWindow.get_instance().set_busy_cursor();
AppWindow.get_instance().set_busy_cursor();
ProgressDialog progress = null;
if (photos.size >= 20)
progress = new ProgressDialog(AppWindow.get_instance(), progress_dialog_text);
ProgressDialog progress = null;
if (photos.size >= 20)
progress = new ProgressDialog(AppWindow.get_instance(), progress_dialog_text);
// valac complains about passing an argument for a delegate using ternary operator:
// https://bugzilla.gnome.org/show_bug.cgi?id=599349
if (progress != null)
LibraryPhoto.global.remove_from_app(photos, delete_backing, progress.monitor);
else
LibraryPhoto.global.remove_from_app(photos, delete_backing);
// valac complains about passing an argument for a delegate using ternary operator:
// https://bugzilla.gnome.org/show_bug.cgi?id=599349
if (progress != null)
LibraryPhoto.global.remove_from_app(photos, delete_backing, progress.monitor);
else
LibraryPhoto.global.remove_from_app(photos, delete_backing);
if (progress != null)
progress.close();
if (progress != null)
progress.close();
AppWindow.get_instance().set_normal_cursor();
AppWindow.get_instance().set_normal_cursor();
}
// compare the app names, case insensitive
......
......@@ -26,7 +26,7 @@
<menuitem name="RemoveFromLibrary" action="RemoveFromLibrary" />
<menuitem name="MoveToTrash" action="MoveToTrash" />
<separator />
<menuitem name="SelectAll" action="SelectAll" />
<menuitem name="SelectAll" action="CommonSelectAll" />
<separator />
<menuitem name="Preferences" action="CommonPreferences" />
</menu>
......
......@@ -13,7 +13,7 @@
<menuitem name="Undo" action="CommonUndo" />
<menuitem name="Redo" action="CommonRedo" />
<separator />
<menuitem name="SelectAll" action="SelectAll" />
<menuitem name="SelectAll" action="CommonSelectAll" />
<separator />
<menuitem name="Preferences" action="CommonPreferences" />
</menu>
......
......@@ -12,7 +12,7 @@
</menu>
<menu name="EditMenu" action="EditMenu">
<menuitem name="SelectAll" action="SelectAll" />
<menuitem name="SelectAll" action="CommonSelectAll" />
<separator />
<menuitem name="Preferences" action="CommonPreferences" />
</menu>
......
......@@ -13,6 +13,10 @@
<menuitem name="Undo" action="CommonUndo" />
<menuitem name="Redo" action="CommonRedo" />
<separator />
<menuitem name="RemoveFromLibrary" action="RemoveFromLibrary" />
<separator />
<menuitem name="SelectAll" action="CommonSelectAll" />
<separator />
<menuitem name="Preferences" action="CommonPreferences" />
</menu>
......
......@@ -17,7 +17,7 @@
<menuitem name="Delete" action="Delete" />
<menuitem name="Restore" action="Restore" />
<separator />
<menuitem name="SelectAll" action="SelectAll" />
<menuitem name="SelectAll" action="CommonSelectAll" />
<separator />
<menuitem name="Preferences" action="CommonPreferences" />
</menu>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment