/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * pikasessioninfo-book.c * Copyright (C) 2001-2007 Michael Natterer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include "libpikaconfig/pikaconfig.h" #include "widgets-types.h" #include "core/pikacontext.h" #include "menus/menus.h" #include "pikadialogfactory.h" #include "pikadock.h" #include "pikadockbook.h" #include "pikasessioninfo.h" #include "pikasessioninfo-book.h" #include "pikasessioninfo-dockable.h" enum { SESSION_INFO_BOOK_POSITION, SESSION_INFO_BOOK_CURRENT_PAGE, SESSION_INFO_BOOK_DOCKABLE }; /* public functions */ PikaSessionInfoBook * pika_session_info_book_new (void) { return g_slice_new0 (PikaSessionInfoBook); } void pika_session_info_book_free (PikaSessionInfoBook *info) { g_return_if_fail (info != NULL); if (info->dockables) { g_list_free_full (info->dockables, (GDestroyNotify) pika_session_info_dockable_free); info->dockables = NULL; } g_slice_free (PikaSessionInfoBook, info); } void pika_session_info_book_serialize (PikaConfigWriter *writer, PikaSessionInfoBook *info) { GList *pages; g_return_if_fail (writer != NULL); g_return_if_fail (info != NULL); pika_config_writer_open (writer, "book"); if (info->position != 0) { gint position; position = pika_session_info_apply_position_accuracy (info->position); pika_config_writer_open (writer, "position"); pika_config_writer_printf (writer, "%d", position); pika_config_writer_close (writer); } pika_config_writer_open (writer, "current-page"); pika_config_writer_printf (writer, "%d", info->current_page); pika_config_writer_close (writer); for (pages = info->dockables; pages; pages = g_list_next (pages)) pika_session_info_dockable_serialize (writer, pages->data); pika_config_writer_close (writer); } GTokenType pika_session_info_book_deserialize (GScanner *scanner, gint scope, PikaSessionInfoBook **book) { PikaSessionInfoBook *info; GTokenType token; g_return_val_if_fail (scanner != NULL, G_TOKEN_LEFT_PAREN); g_return_val_if_fail (book != NULL, G_TOKEN_LEFT_PAREN); g_scanner_scope_add_symbol (scanner, scope, "position", GINT_TO_POINTER (SESSION_INFO_BOOK_POSITION)); g_scanner_scope_add_symbol (scanner, scope, "current-page", GINT_TO_POINTER (SESSION_INFO_BOOK_CURRENT_PAGE)); g_scanner_scope_add_symbol (scanner, scope, "dockable", GINT_TO_POINTER (SESSION_INFO_BOOK_DOCKABLE)); info = pika_session_info_book_new (); token = G_TOKEN_LEFT_PAREN; while (g_scanner_peek_next_token (scanner) == token) { token = g_scanner_get_next_token (scanner); switch (token) { case G_TOKEN_LEFT_PAREN: token = G_TOKEN_SYMBOL; break; case G_TOKEN_SYMBOL: switch (GPOINTER_TO_INT (scanner->value.v_symbol)) { PikaSessionInfoDockable *dockable; case SESSION_INFO_BOOK_POSITION: token = G_TOKEN_INT; if (! pika_scanner_parse_int (scanner, &info->position)) goto error; break; case SESSION_INFO_BOOK_CURRENT_PAGE: token = G_TOKEN_INT; if (! pika_scanner_parse_int (scanner, &info->current_page)) goto error; break; case SESSION_INFO_BOOK_DOCKABLE: g_scanner_set_scope (scanner, scope + 1); token = pika_session_info_dockable_deserialize (scanner, scope + 1, &dockable); if (token == G_TOKEN_LEFT_PAREN) { info->dockables = g_list_append (info->dockables, dockable); g_scanner_set_scope (scanner, scope); } else goto error; break; default: goto error; } token = G_TOKEN_RIGHT_PAREN; break; case G_TOKEN_RIGHT_PAREN: token = G_TOKEN_LEFT_PAREN; break; default: break; } } *book = info; g_scanner_scope_remove_symbol (scanner, scope, "position"); g_scanner_scope_remove_symbol (scanner, scope, "current-page"); g_scanner_scope_remove_symbol (scanner, scope, "dockable"); return token; error: *book = NULL; pika_session_info_book_free (info); return token; } PikaSessionInfoBook * pika_session_info_book_from_widget (PikaDockbook *dockbook) { PikaSessionInfoBook *info; GtkWidget *parent; GList *children; GList *list; g_return_val_if_fail (PIKA_IS_DOCKBOOK (dockbook), NULL); info = pika_session_info_book_new (); parent = gtk_widget_get_parent (GTK_WIDGET (dockbook)); if (GTK_IS_PANED (parent)) { GtkPaned *paned = GTK_PANED (parent); if (GTK_WIDGET (dockbook) == gtk_paned_get_child2 (paned)) info->position = gtk_paned_get_position (paned); } info->current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook)); children = gtk_container_get_children (GTK_CONTAINER (dockbook)); for (list = children; list; list = g_list_next (list)) { PikaSessionInfoDockable *dockable; dockable = pika_session_info_dockable_from_widget (list->data); info->dockables = g_list_prepend (info->dockables, dockable); } info->dockables = g_list_reverse (info->dockables); g_list_free (children); return info; } PikaDockbook * pika_session_info_book_restore (PikaSessionInfoBook *info, PikaDock *dock) { PikaDialogFactory *dialog_factory; PikaMenuFactory *menu_factory; GtkWidget *dockbook; GList *pages; gint n_dockables = 0; g_return_val_if_fail (info != NULL, NULL); g_return_val_if_fail (PIKA_IS_DOCK (dock), NULL); dialog_factory = pika_dock_get_dialog_factory (dock); menu_factory = menus_get_global_menu_factory (pika_dialog_factory_get_context (dialog_factory)->pika); dockbook = pika_dockbook_new (menu_factory); pika_dock_add_book (dock, PIKA_DOCKBOOK (dockbook), -1); for (pages = info->dockables; pages; pages = g_list_next (pages)) { PikaSessionInfoDockable *dockable_info = pages->data; PikaDockable *dockable; dockable = pika_session_info_dockable_restore (dockable_info, dock); if (dockable) { gtk_notebook_append_page (GTK_NOTEBOOK (dockbook), GTK_WIDGET (dockable), NULL); n_dockables++; } } if (info->current_page < gtk_notebook_get_n_pages (GTK_NOTEBOOK (dockbook))) { gtk_notebook_set_current_page (GTK_NOTEBOOK (dockbook), info->current_page); } else if (n_dockables > 1) { gtk_notebook_set_current_page (GTK_NOTEBOOK (dockbook), 0); } /* Return the dockbook even if no dockable could be restored * (n_dockables == 0) because otherwise we would have to remove it * from the dock right here, which could implicitly destroy the * dock and make catching restore errors much harder on higher * levels. Instead, we check for restored empty dockbooks in our * caller. */ return PIKA_DOCKBOOK (dockbook); }