Commit 482b586a authored by Jim Nelson's avatar Jim Nelson

#1069: Pages are now destroyed when removed from LibraryWindow, and each Page...

#1069: Pages are now destroyed when removed from LibraryWindow, and each Page destroys all the widgets it 
creates that are not contained/parented when the Page is destroyed (i.e. the menu bar).  This issue was 
exacerbated by drag-and-drop, which obtains references on all widgets in the application and releases them after 
the Page was deref'ed.
parent d6a8f33f
......@@ -68,7 +68,6 @@ public class CollectionPage : CheckerboardPage {
private static Gtk.Adjustment slider_adjustment = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.HScale slider = null;
private Gtk.ToolButton new_event_button = null;
private Gtk.ToolButton rotate_button = null;
......@@ -114,7 +113,8 @@ public class CollectionPage : CheckerboardPage {
scale_to_slider(Thumbnail.MAX_SCALE), 1, 10, 0);
// set up page's toolbar (used by AppWindow for layout)
//
Gtk.Toolbar toolbar = get_toolbar();
// rotate tool
rotate_button = new Gtk.ToolButton.from_stock(Resources.CLOCKWISE);
rotate_button.set_label(Resources.ROTATE_CW_LABEL);
......@@ -371,10 +371,6 @@ public class CollectionPage : CheckerboardPage {
return sort_order_actions;
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
// This method is called by CollectionViewManager to create thumbnails for the DataSource
// (Photo) objects.
public virtual Thumbnail create_thumbnail(LibraryPhoto photo) {
......
......@@ -15,12 +15,12 @@ public abstract class PageCommand : Command {
page = AppWindow.get_instance().get_current_page();
if (page != null)
page.removed += on_page_removed;
page.destroy += on_page_destroyed;
}
~PageCommand() {
if (page != null)
page.removed -= on_page_removed;
page.destroy -= on_page_destroyed;
}
public void set_auto_return_to_page(bool auto_return) {
......@@ -39,8 +39,8 @@ public abstract class PageCommand : Command {
AppWindow.get_instance().set_current_page(page);
}
private void on_page_removed() {
page.removed -= on_page_removed;
private void on_page_destroyed() {
page.destroy -= on_page_destroyed;
page = null;
}
}
......@@ -522,11 +522,11 @@ public abstract class MovePhotosCommand : Command {
}
public override void execute() {
// switch to new event page first (to prevent flicker if other pages are destroyed)
LibraryWindow.get_app().switch_to_event((Event) new_event_proxy.get_source());
// create the new event
base.execute();
// switch to new event page
LibraryWindow.get_app().switch_to_event((Event) new_event_proxy.get_source());
}
public override void execute_on_source(DataSource source) {
......
......@@ -99,7 +99,6 @@ public class EventsDirectoryPage : CheckerboardPage {
private const int MIN_PHOTOS_FOR_PROGRESS_WINDOW = 50;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.ToolButton merge_button;
protected ViewManager view_manager;
......@@ -120,7 +119,8 @@ public class EventsDirectoryPage : CheckerboardPage {
this.view_manager = view_manager;
// set up page's toolbar (used by AppWindow for layout and FullscreenWindow as a popup)
//
Gtk.Toolbar toolbar = get_toolbar();
// merge tool
merge_button = new Gtk.ToolButton.from_stock(Gtk.STOCK_ADD);
merge_button.set_label(Resources.MERGE_LABEL);
......@@ -177,10 +177,6 @@ public class EventsDirectoryPage : CheckerboardPage {
return actions;
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
public override void on_item_activated(LayoutItem item) {
EventDirectoryItem event = (EventDirectoryItem) item;
LibraryWindow.get_app().switch_to_event(event.event);
......
......@@ -205,7 +205,6 @@ public class ImportPage : CheckerboardPage {
private static GPhoto.ContextWrapper null_context = null;
private SourceCollection import_sources = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.Label camera_label = new Gtk.Label(null);
private Gtk.CheckButton hide_imported;
private Gtk.ToolButton import_selected_button;
......@@ -252,7 +251,9 @@ public class ImportPage : CheckerboardPage {
init_ui("import.ui", "/ImportMenuBar", "ImportActionGroup", create_actions(),
create_toggle_actions());
// toolbar
// Set up toolbar
Gtk.Toolbar toolbar = get_toolbar();
// hide duplicates checkbox
hide_imported = new Gtk.CheckButton.with_label(_("Hide photos already imported"));
hide_imported.set_tooltip_text(_("Only display photos that have not been imported"));
......@@ -397,10 +398,6 @@ public class ImportPage : CheckerboardPage {
return msg;
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
private void on_view_changed() {
hide_imported.sensitive = !busy && refreshed && (get_view().get_count() > 0);
import_selected_button.sensitive = !busy && refreshed && (get_view().get_selected_count() > 0);
......@@ -984,7 +981,6 @@ public class ImportPage : CheckerboardPage {
#endif
public class ImportQueuePage : SinglePhotoPage {
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.ToolButton stop_button = null;
private Gee.ArrayList<BatchImport> queue = new Gee.ArrayList<BatchImport>();
private BatchImport current_batch = null;
......@@ -998,6 +994,10 @@ public class ImportQueuePage : SinglePhotoPage {
init_ui("import_queue.ui", "/ImportQueueMenuBar", "ImportQueueActionGroup",
create_actions());
// Set up toolbar
Gtk.Toolbar toolbar = get_toolbar();
// Stop button
stop_button = new Gtk.ToolButton.from_stock(Gtk.STOCK_STOP);
stop_button.set_tooltip_text(_("Stop importing photos"));
stop_button.clicked += on_stop;
......@@ -1012,6 +1012,7 @@ public class ImportQueuePage : SinglePhotoPage {
toolbar.insert(separator, -1);
// Progress bar
Gtk.ToolItem progress_item = new Gtk.ToolItem();
progress_item.add(progress_bar);
......@@ -1046,10 +1047,6 @@ public class ImportQueuePage : SinglePhotoPage {
public signal void batch_removed(BatchImport batch_import);
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
public void enqueue_and_schedule(BatchImport batch_import) {
assert(!queue.contains(batch_import));
......
......@@ -49,6 +49,38 @@ public class LibraryWindow : AppWindow {
}
}
private class PageLayout : Gtk.VBox {
private string page_name;
private Gtk.Toolbar toolbar;
public PageLayout(Page page) {
page_name = page.get_page_name();
toolbar = page.get_toolbar();
set_homogeneous(false);
set_spacing(0);
pack_start(page, true, true, 0);
pack_end(toolbar, false, false, 0);
}
~PageLayout() {
#if TRACE_DTORS
debug("DTOR: PageLayout for %s", page_name);
#endif
}
public override void destroy() {
// because Page destroys all its own widgets, need to prevent a double-destroy on
// the toolbar
if (toolbar is Gtk.Widget)
remove(toolbar);
toolbar = null;
base.destroy();
}
}
public static Gdk.Color SIDEBAR_BG_COLOR = parse_color("#EEE");
private string import_dir = Environment.get_home_dir();
......@@ -233,6 +265,7 @@ public class LibraryWindow : AppWindow {
private bool displaying_import_queue_page = false;
// Dynamically added/removed pages
private Gee.HashMap<Page, PageLayout> page_layouts = new Gee.HashMap<Page, PageLayout>();
private Gee.ArrayList<EventPageStub> event_list = new Gee.ArrayList<EventPageStub>();
private Gee.ArrayList<SubEventsDirectoryPageStub> events_dir_list =
new Gee.ArrayList<SubEventsDirectoryPageStub>();
......@@ -240,9 +273,6 @@ public class LibraryWindow : AppWindow {
private Gee.HashMap<string, ImportPage> camera_pages = new Gee.HashMap<string, ImportPage>(
str_hash, str_equal, direct_equal);
#endif
private OneShotScheduler page_removal_scheduler = null;
private Gee.HashSet<Page> pages_to_be_removed = new Gee.HashSet<Page>();
private Gee.HashSet<Page> pages_to_be_hidden = new Gee.HashSet<Page>();
private Sidebar sidebar = new Sidebar();
#if !NO_CAMERA
......@@ -313,9 +343,6 @@ public class LibraryWindow : AppWindow {
extended_properties.hide += hide_extended_properties;
extended_properties.show += show_extended_properties;
page_removal_scheduler = new OneShotScheduler("Hide/Remove Pages Scheduler",
hide_remove_pages_internal);
}
~LibraryWindow() {
......@@ -332,8 +359,6 @@ public class LibraryWindow : AppWindow {
extended_properties.hide -= hide_extended_properties;
extended_properties.show -= show_extended_properties;
page_removal_scheduler.cancel();
}
private Gtk.ActionEntry[] create_actions() {
......@@ -640,43 +665,42 @@ public class LibraryWindow : AppWindow {
Gtk.SelectionData selection_data, uint info, uint time, SidebarPage? page = null) {
// determine if drag is internal or external
if (Gtk.drag_get_source_widget(context) != null)
drag_internal(context, x, y, selection_data, info, time, page);
drop_internal(context, x, y, selection_data, info, time, page);
else
drag_external(context, x, y, selection_data, info, time);
drop_external(context, x, y, selection_data, info, time);
}
private void drag_internal(Gdk.DragContext context, int x, int y,
private void drop_internal(Gdk.DragContext context, int x, int y,
Gtk.SelectionData selection_data, uint info, uint time, SidebarPage? page = null) {
if (page != null && page is EventPageStub) {
bool success = false;
if (page is EventPageStub) {
Event event = ((EventPageStub) page).event;
Gee.ArrayList<PhotoView> photos = new Gee.ArrayList<PhotoView>();
bool move_photos = false;
Gee.List<PhotoID?>? photo_ids = unserialize_photo_ids(selection_data.data,
selection_data.get_length());
Gee.ArrayList<PhotoView> photos = new Gee.ArrayList<PhotoView>();
foreach (PhotoID photo_id in photo_ids) {
LibraryPhoto photo = LibraryPhoto.global.fetch(photo_id);
photos.add(new PhotoView(photo));
// don't move a photo into the event it already exists in
if (!photo.get_event().equals(event))
move_photos = true;
photos.add(new PhotoView(photo));
}
if (move_photos) {
SetEventCommand command = new SetEventCommand(photos, event);
if (photos.size > 0) {
Command command = new SetEventCommand(photos, event);
get_command_manager().execute(command);
Gtk.drag_finish(context, true, false, time);
return;
success = true;
}
}
Gtk.drag_finish(context, false, false, time);
Gtk.drag_finish(context, success, false, time);
}
private void drag_external(Gdk.DragContext context, int x, int y,
private void drop_external(Gdk.DragContext context, int x, int y,
Gtk.SelectionData selection_data, uint info, uint time) {
// We extract the URI list using Uri.list_extract_uris() rather than
// Gtk.SelectionData.get_uris() to work around this bug on Windows:
......@@ -898,9 +922,9 @@ public class LibraryWindow : AppWindow {
// remove from notebook and sidebar
if (delete_stub)
remove_stub(stub);
remove_stub(stub, events_directory_page);
else
sidebar.remove_page(stub);
sidebar.remove_page(stub);
// remove parent if empty
if (parent != null && !(parent is MasterEventsDirectoryPage)) {
......@@ -940,12 +964,43 @@ public class LibraryWindow : AppWindow {
}
}
#endif
private PageLayout? get_page_layout(Page page) {
return page_layouts.get(page);
}
private PageLayout create_page_layout(Page page) {
PageLayout layout = new PageLayout(page);
page_layouts.set(page, layout);
return layout;
}
private bool destroy_page_layout(Page page) {
PageLayout? layout = get_page_layout(page);
if (layout == null)
return false;
// destroy the layout, which destroys the page
layout.destroy();
bool unset = page_layouts.unset(page);
assert(unset);
return true;
}
private void add_to_notebook(Page page) {
// shouldn't already be laid out
assert(get_page_layout(page) == null);
// create layout for this page
PageLayout layout = create_page_layout(page);
// need to show all before handing over to notebook
page.show_all();
layout.show_all();
int pos = notebook.append_page(page.get_layout(), null);
int pos = notebook.append_page(layout, null);
assert(pos >= 0);
// need to show_all() after pages are added and removed
......@@ -960,7 +1015,10 @@ public class LibraryWindow : AppWindow {
}
private int get_notebook_pos(Page page) {
int pos = notebook.page_num(page.get_layout());
PageLayout? layout = get_page_layout(page);
assert(layout != null);
int pos = notebook.page_num(layout);
assert(pos != -1);
return pos;
......@@ -995,12 +1053,15 @@ public class LibraryWindow : AppWindow {
// This removes the page from the notebook and the sidebar, but does not actually notify it
// that it's been removed from the system, allowing it to be added back later.
private void hide_page(Page page, Page fallback_page) {
// See note in remove_page for the necessity of doing this
pages_to_be_hidden.add(page);
page_removal_scheduler.at_priority_idle(Priority.LOW);
if (get_current_page() == page)
switch_to_page(fallback_page);
debug("Hiding page %s", page.get_page_name());
remove_from_notebook(page);
sidebar.remove_page(page);
debug("Hid page %s", page.get_page_name());
}
private void remove_page(Page page, Page fallback_page) {
......@@ -1010,27 +1071,24 @@ public class LibraryWindow : AppWindow {
assert(page != photo_page);
assert(page != import_queue_page);
// because removing a page while executing inside a signal or from a call from the page
// itself causes problems (i.e. the page being unref'd beneath its feet), schedule all
// removals outside of UI event and in Idle handler
pages_to_be_removed.add(page);
page_removal_scheduler.at_priority_idle(Priority.LOW);
// switch away if necessary to collection page (which is always present)
// switch away if necessary to ensure Page is fully detached from system
if (get_current_page() == page)
switch_to_page(fallback_page);
debug("Removing page %s", page.get_page_name());
// detach from notebook and sidebar
sidebar.remove_page(page);
remove_from_notebook(page);
// destroy layout if it exists, otherwise just the page
if (!destroy_page_layout(page))
page.destroy();
debug("Removed page %s", page.get_page_name());
}
private void remove_stub(PageStub stub) {
// see note in remove_page() for why this is done
if (stub.has_page()) {
pages_to_be_removed.add(stub.get_page());
page_removal_scheduler.at_priority_idle(Priority.LOW);
}
// remove stub (which holds a marker) from the sidebar
sidebar.remove_page(stub);
private void remove_stub(PageStub stub, Page fallback_page) {
// remove from appropriate list
if (stub is SubEventsDirectoryPageStub) {
// remove from events directory list
......@@ -1041,32 +1099,26 @@ public class LibraryWindow : AppWindow {
bool removed = event_list.remove((EventPageStub) stub);
assert(removed);
}
}
private void hide_remove_pages_internal() {
foreach (Page page in pages_to_be_removed) {
debug("Removing page %s", page.get_page_name());
remove_from_notebook(page);
sidebar.remove_page(page);
page.notify_removed();
debug("Removed page %s", page.get_page_name());
}
pages_to_be_removed.clear();
// remove stub (which holds a marker) from the sidebar
sidebar.remove_page(stub);
foreach (Page page in pages_to_be_hidden) {
debug("Hiding page %s", page.get_page_name());
if (stub.has_page()) {
// ensure the page is fully detached
if (get_current_page() == stub.get_page())
switch_to_page(fallback_page);
debug("Removing stubbed page %s", stub.get_page().get_page_name());
remove_from_notebook(page);
sidebar.remove_page(page);
// detach from notebook
remove_from_notebook(stub.get_page());
debug("Hid page %s", page.get_page_name());
// destroy page layout if it exists, otherwise just the page
if (!destroy_page_layout(stub.get_page()))
stub.get_page().destroy();
debug("Removed stubbed page %s", stub.get_page().get_page_name());
}
pages_to_be_hidden.clear();
}
// check for settings that should persist between instances
......@@ -1152,8 +1204,10 @@ public class LibraryWindow : AppWindow {
if (get_current_page() != null) {
get_current_page().switching_from();
remove_accel_group(get_current_page().ui.get_accel_group());
Gtk.AccelGroup accel_group = get_current_page().ui.get_accel_group();
if (accel_group != null)
remove_accel_group(accel_group);
// carry over menubar toggle activity between pages
Gtk.ToggleAction old_basic_display_action =
......@@ -1202,8 +1256,10 @@ public class LibraryWindow : AppWindow {
// do this prior to changing selection, as the change will fire a cursor-changed event,
// which will then call this function again
base.set_current_page(page);
Idle.add_full(Priority.HIGH, place_sidebar_cursor);
sidebar.cursor_changed -= on_sidebar_cursor_changed;
sidebar.place_cursor(page);
sidebar.cursor_changed += on_sidebar_cursor_changed;
on_selection_changed();
......@@ -1215,11 +1271,6 @@ public class LibraryWindow : AppWindow {
page.switched_to();
}
private bool place_sidebar_cursor() {
sidebar.place_cursor(get_current_page());
return false;
}
private bool is_page_selected(SidebarPage page, Gtk.TreePath path) {
SidebarMarker? marker = page.get_marker();
if (marker == null)
......
......@@ -4,17 +4,6 @@
* See the COPYING file in this distribution.
*/
public class PageLayout : Gtk.VBox {
public PageLayout(Page page) {
set_homogeneous(false);
set_spacing(0);
pack_start(page, true, true, 0);
if (page.get_toolbar() != null)
pack_end(page.get_toolbar(), false, false, 0);
}
}
public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
public const uint KEY_CTRL_L = Gdk.keyval_from_name("Control_L");
public const uint KEY_CTRL_R = Gdk.keyval_from_name("Control_R");
......@@ -43,7 +32,7 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
private string page_name;
private ViewCollection view = null;
private Gtk.Window container = null;
private PageLayout layout = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private string menubar_path = null;
private SidebarMarker marker = null;
private Gdk.Rectangle last_position = Gdk.Rectangle();
......@@ -58,9 +47,6 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
private bool alt_pressed = false;
private bool shift_pressed = false;
public virtual signal void removed() {
}
public Page(string page_name) {
this.page_name = page_name;
this.view = new ViewCollection("ViewCollection for Page %s".printf(page_name));
......@@ -76,20 +62,42 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
#endif
}
private void destroy_ui_manager_widgets(Gtk.UIManagerItemType item_type) {
unowned SList<Gtk.Widget> toplevels = ui.get_toplevels(item_type);
for (int ctr = 0; ctr < toplevels.length(); ctr++)
toplevels.nth(ctr).data.destroy();
}
// This is called by the page controller when it has removed this page ... pages should override
// this (or the signal) to clean up
public virtual void notify_removed() {
// signal prior to shutdown
removed();
public override void destroy() {
debug("Destroying Page %s", get_page_name());
// untie signals
detach_event_source();
view.close();
// remove refs to external objects which may be pointing to the Page
layout = null;
clear_marker();
clear_container();
// Without destroying the menubar, Gtk spits out an assertion related to
// a Gtk.AccelLabel being unable to disconnect a signal from the UI Manager's
// Gtk.AccelGroup because the AccelGroup has already been finalized. This only
// happens during a drag-and-drop operation where the Page is destroyed.
// Destroying the menubar explicitly solves this problem. These calls go through and
// ensure *all* widgets created by the UI manager are destroyed.
destroy_ui_manager_widgets(Gtk.UIManagerItemType.MENUBAR);
destroy_ui_manager_widgets(Gtk.UIManagerItemType.TOOLBAR);
destroy_ui_manager_widgets(Gtk.UIManagerItemType.POPUP);
// toolbars (as of yet) are not created by the UI Manager and need to be destroyed
// explicitly
toolbar.destroy();
debug("Destroyed Page %s", get_page_name());
base.destroy();
}
public string get_page_name() {
......@@ -127,19 +135,6 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
container = null;
}
public PageLayout get_layout() {
// This only places the Page into a PageLayout if requested;
// this is how a Page can live inside AppWindow's notebook or
// on its own in another window with a separate layout.
if (layout != null)
return layout;
assert(parent == null);
layout = new PageLayout(this);
return layout;
}
public void set_event_source(Gtk.Widget event_source) {
assert(this.event_source == null);
......@@ -194,7 +189,13 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
return (Gtk.MenuBar) ui.get_widget(menubar_path);
}
public abstract Gtk.Toolbar get_toolbar();
public virtual Gtk.Toolbar get_toolbar() {
return toolbar;
}
public virtual Gtk.Menu? get_page_context_menu() {
return null;
}
public virtual void switching_from() {
in_view = false;
......@@ -219,7 +220,7 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
ui.get_widget(path).sensitive = sensitive;
}
private virtual void update_modifiers() {
private virtual void update_modifiers() {
int x, y;
Gdk.ModifierType mask;
AppWindow.get_instance().window.get_pointer(out x, out y, out mask);
......@@ -648,10 +649,6 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
return on_motion(event, x, y, mask);
}
public virtual Gtk.Menu? get_page_context_menu() {
return null;
}
}
public abstract class CheckerboardPage : Page {
......
......@@ -31,7 +31,6 @@ public abstract class EditingHostPage : SinglePhotoPage {
private ViewCollection controller = null;
private Gdk.Pixbuf swapped = null;
private bool pixbuf_dirty = true;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.ToolButton rotate_button = null;
private Gtk.ToggleToolButton crop_button = null;
private Gtk.ToggleToolButton redeye_button = null;
......@@ -64,7 +63,8 @@ public abstract class EditingHostPage : SinglePhotoPage {
sources.item_altered += on_photo_altered;
// set up page's toolbar (used by AppWindow for layout and FullscreenWindow as a popup)
//
Gtk.Toolbar toolbar = get_toolbar();
// rotate tool
rotate_button = new Gtk.ToolButton.from_stock(Resources.CLOCKWISE);
rotate_button.set_label(Resources.ROTATE_CW_LABEL);
......@@ -97,7 +97,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
adjust_button.is_important = true;
toolbar.insert(adjust_button, -1);
// ehance tool
// enhance tool
enhance_button = new Gtk.ToolButton.from_stock(Resources.ENHANCE);
enhance_button.set_label(Resources.ENHANCE_LABEL);
enhance_button.set_tooltip_text(Resources.ENHANCE_TOOLTIP);
......@@ -134,10 +134,6 @@ public abstract class EditingHostPage : SinglePhotoPage {
enable_drag_source(Gdk.DragAction.COPY);
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
public override ViewCollection get_controller() {
return controller;
}
......@@ -1072,7 +1068,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
// Fullscreen: position crop tool window centered on screen at the bottom, just above the
// toolbar
Gtk.Allocation toolbar_alloc = toolbar.allocation;
Gtk.Allocation toolbar_alloc = get_toolbar().allocation;
Gdk.Screen screen = get_container().get_screen();
......
......@@ -11,7 +11,6 @@ class SlideshowPage : SinglePhotoPage {
private Thumbnail current;
private Gdk.Pixbuf next_pixbuf = null;
private Thumbnail next_thumbnail = null;
private Gtk.Toolbar toolbar = new Gtk.Toolbar();
private Gtk.ToolButton play_pause_button;
private Gtk.ToolButton settings_button;
private Timer timer = new Timer();
......@@ -92,6 +91,9 @@ class SlideshowPage : SinglePhotoPage {
this.controller = controller;
current = start;
// Set up toolbar
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"));
......@@ -123,10 +125,6 @@ class SlideshowPage : SinglePhotoPage {
toolbar.insert(settings_button, -1);
}
public override Gtk.Toolbar get_toolbar() {
return toolbar;
}
public override void switched_to() {
base.switched_to();
......
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