Add "Load stylesheet"
authorThomas White <taw@bitwiz.org.uk>
Sun, 18 Aug 2013 21:29:17 +0000 (23:29 +0200)
committerThomas White <taw@bitwiz.org.uk>
Sun, 18 Aug 2013 21:29:17 +0000 (23:29 +0200)
data/colloquium.ui
src/mainwindow.c
src/stylesheet.c
src/stylesheet.h

index b2df3f7..afd8702 100644 (file)
@@ -4,9 +4,10 @@
                <menu name="file" action="FileAction">
                        <menuitem name="new" action="NewAction" />
                        <menuitem name="open" action="OpenAction" />
-                       <separator />
                        <menuitem name="save" action="SaveAction" />
                        <menuitem name="saveas" action="SaveAsAction" />
+                       <separator />
+                       <menuitem name="loadstyle" action="LoadStyleAction" />
                        <menuitem name="savestyle" action="SaveStyleAction" />
                        <menuitem name="exportpdf" action="ExportPDFAction" />
                        <separator />
@@ -27,7 +28,6 @@
 
                <menu name="insert" action="InsertAction">
                        <menuitem name="newslide" action="NewSlideAction" />
-                       <separator />
                </menu>
 
                <menu name="tools" action="ToolsAction">
index 95df042..c5d9a9c 100644 (file)
@@ -229,6 +229,151 @@ static gint open_sig(GtkWidget *widget, struct presentation *p)
 }
 
 
+static void do_slide_update(struct presentation *p, PangoContext *pc)
+{
+       rerender_slide(p);
+       redraw_editor(p);
+       if ( (p->slideshow != NULL)
+         && (p->cur_edit_slide == p->cur_proj_slide) )
+       {
+               redraw_slideshow(p);
+       }
+}
+
+
+static gint add_furniture(GtkWidget *widget, struct menu_pl *pl)
+{
+       struct frame *fr;
+       struct style *sty = pl->sty;
+       struct presentation *p = pl->p;
+
+       fr = add_subframe(p->cur_edit_slide->top);
+       fr->style = sty;
+       fr->lop_from_style = 1;
+       set_edit(p, p->cur_edit_slide);
+       fr->sc = strdup("");
+       fr->sc_len = 6;
+       set_selection(p, fr);
+       fr->pos = 0;
+       p->cursor_pos = 0;
+
+       do_slide_update(p, p->pc);
+
+       return 0;
+}
+
+
+static void update_style_menus(struct presentation *p)
+{
+       GtkWidget *menu;
+       GtkWidget *item;
+       struct slide_template *t;
+       TemplateIterator *iter;
+       int i, j, k, n_j, n_k;
+
+       for ( i=0; i<p->n_menu_rebuild; i++ ) {
+               gtk_widget_destroy(p->menu_rebuild_list[i]);
+       }
+       free(p->menu_rebuild_list);
+       free(p->menu_path_list);
+
+       /* Add the styles to the "Insert" menu */
+       menu = gtk_ui_manager_get_widget(p->ui, "/displaywindow/insert");
+       menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
+
+       n_k = 0;  n_j = 0;
+       for ( t = template_first(p->ss, &iter);
+             t != NULL;
+             t = template_next(p->ss, iter) )
+       {
+               n_k += t->n_styles;
+               n_j++;
+       }
+
+       p->menu_rebuild_list = calloc(n_j, sizeof(GtkWidget *));
+       if ( p->menu_rebuild_list == NULL ) return;
+
+       p->menu_path_list = calloc(n_k, sizeof(struct menu_pl));
+       if ( p->menu_path_list == NULL ) return;
+
+       j = 0;
+       k = 0;
+       for ( t = template_first(p->ss, &iter);
+             t != NULL;
+             t = template_next(p->ss, iter) )
+       {
+               GtkWidget *submenu;
+
+               submenu = gtk_menu_new();
+               item = gtk_menu_item_new_with_label(t->name);
+               gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+               gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+               p->menu_rebuild_list[j++] = item;
+
+               for ( i=0; i<t->n_styles; i++ ) {
+
+                       struct style *s = t->styles[i];
+
+                       p->menu_path_list[k].p = p;
+                       p->menu_path_list[k].sty = s;
+
+                       item = gtk_menu_item_new_with_label(s->name);
+                       gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
+                       g_signal_connect(G_OBJECT(item), "activate",
+                                        G_CALLBACK(add_furniture),
+                                        &p->menu_path_list[k]);
+                       k++;
+
+               }
+       }
+
+       gtk_widget_show_all(menu);
+
+       p->n_menu_rebuild = j;
+}
+
+
+static gint loadstyle_response_sig(GtkWidget *d, gint response,
+                             struct presentation *p)
+{
+       if ( response == GTK_RESPONSE_ACCEPT ) {
+
+               char *filename;
+
+               filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+               replace_stylesheet(p, filename);
+               g_free(filename);
+               update_style_menus(p);
+               rerender_slide(p);
+
+       }
+
+       gtk_widget_destroy(d);
+
+       return 0;
+}
+
+
+static gint loadstyle_sig(GtkWidget *widget, struct presentation *p)
+{
+       GtkWidget *d;
+
+       d = gtk_file_chooser_dialog_new("Load Stylesheet",
+                                       GTK_WINDOW(p->window),
+                                       GTK_FILE_CHOOSER_ACTION_OPEN,
+                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                       NULL);
+
+       g_signal_connect(G_OBJECT(d), "response",
+                        G_CALLBACK(loadstyle_response_sig), p);
+
+       gtk_widget_show_all(d);
+
+       return 0;
+}
+
+
 static gint new_sig(GtkWidget *widget, struct presentation *pnn)
 {
        struct presentation *p;
@@ -533,115 +678,12 @@ static gint open_notes_sig(GtkWidget *widget, struct presentation *p)
 }
 
 
-static void do_slide_update(struct presentation *p, PangoContext *pc)
-{
-       rerender_slide(p);
-       redraw_editor(p);
-       if ( (p->slideshow != NULL)
-         && (p->cur_edit_slide == p->cur_proj_slide) )
-       {
-               redraw_slideshow(p);
-       }
-}
-
-
-
-static gint add_furniture(GtkWidget *widget, struct menu_pl *pl)
-{
-       struct frame *fr;
-       struct style *sty = pl->sty;
-       struct presentation *p = pl->p;
-
-       fr = add_subframe(p->cur_edit_slide->top);
-       fr->style = sty;
-       fr->lop_from_style = 1;
-       set_edit(p, p->cur_edit_slide);
-       fr->sc = strdup("");
-       fr->sc_len = 6;
-       set_selection(p, fr);
-       fr->pos = 0;
-       p->cursor_pos = 0;
-
-       do_slide_update(p, p->pc);
-
-       return 0;
-}
-
-
-static void update_style_menus(struct presentation *p)
-{
-       GtkWidget *menu;
-       GtkWidget *item;
-       struct slide_template *t;
-       TemplateIterator *iter;
-       int i, j, n;
-
-       for ( i=0; i<p->n_menu_rebuild; i++ ) {
-               gtk_widget_destroy(p->menu_rebuild_list[i]);
-       }
-       free(p->menu_rebuild_list);
-       free(p->menu_path_list);
-
-       /* Add the styles to the "Insert" menu */
-       menu = gtk_ui_manager_get_widget(p->ui, "/displaywindow/insert");
-       menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
-       item = gtk_separator_menu_item_new();
-       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-
-       n = 0;
-       for ( t = template_first(p->ss, &iter);
-             t != NULL;
-             t = template_next(p->ss, iter) )
-       {
-               n += t->n_styles;
-               n += 1;  /* The top level */
-       }
-
-       p->menu_rebuild_list = calloc(n, sizeof(GtkWidget *));
-       if ( p->menu_rebuild_list == NULL ) return;
-
-       p->menu_path_list = calloc(n, sizeof(struct menu_pl));
-       if ( p->menu_path_list == NULL ) return;
-
-       j = 0;
-       for ( t = template_first(p->ss, &iter);
-             t != NULL;
-             t = template_next(p->ss, iter) )
-       {
-               GtkWidget *submenu;
-
-               submenu = gtk_menu_new();
-               item = gtk_menu_item_new_with_label(t->name);
-               gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-                       gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
-               p->menu_rebuild_list[j++] = item;
-
-               for ( i=0; i<t->n_styles; i++ ) {
-
-                       struct style *s = t->styles[i];
-
-                       p->menu_path_list[j].p = p;
-                       p->menu_path_list[j].sty = s;
-
-                       item = gtk_menu_item_new_with_label(s->name);
-                       gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
-                       p->menu_rebuild_list[j] = item;
-                       g_signal_connect(G_OBJECT(item), "activate",
-                                        G_CALLBACK(add_furniture),
-                                        &p->menu_path_list[j]);
-                       j++;
-
-               }
-       }
-
-       p->n_menu_rebuild = j;
-}
-
-
 static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
 {
        GError *error = NULL;
        GtkWidget *toolbar;
+       GtkWidget *menu;
+       GtkWidget *item;
 
        GtkActionEntry entries[] = {
 
@@ -650,13 +692,15 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
                        NULL, NULL, G_CALLBACK(new_sig) },
                { "OpenAction", GTK_STOCK_OPEN, "_Open...",
                        NULL, NULL, G_CALLBACK(open_sig) },
+               { "LoadStyleAction", NULL, "_Load Stylesheet...",
+                       NULL, NULL, G_CALLBACK(loadstyle_sig) },
                { "SaveAction", GTK_STOCK_SAVE, "_Save",
                        NULL, NULL, G_CALLBACK(save_sig) },
                { "SaveAsAction", GTK_STOCK_SAVE_AS, "Save _As...",
                        NULL, NULL, G_CALLBACK(saveas_sig) },
-               { "SaveStyleAction", GTK_STOCK_SAVE_AS, "Save St_ylesheet",
+               { "SaveStyleAction", NULL, "Save St_ylesheet",
                        NULL, NULL, G_CALLBACK(save_ss_sig) },
-               { "ExportPDFAction", GTK_STOCK_SAVE_AS, "Export PDF",
+               { "ExportPDFAction", NULL, "Export PDF",
                        NULL, NULL, G_CALLBACK(export_pdf_sig) },
                { "QuitAction", GTK_STOCK_QUIT, "_Quit",
                        NULL, NULL, G_CALLBACK(quit_sig) },
@@ -730,6 +774,11 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox)
        gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                           gtk_separator_tool_item_new(), -1);
 
+       menu = gtk_ui_manager_get_widget(p->ui, "/displaywindow/insert");
+       menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
+       item = gtk_separator_menu_item_new();
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
        update_style_menus(p);
        update_toolbar(p);
 }
index 18a55b2..9d81e20 100644 (file)
@@ -303,6 +303,109 @@ StyleSheet *tree_to_stylesheet(struct ds_node *root)
 }
 
 
+static int fixup_styles(struct frame *fr, StyleSheet *ss)
+{
+       int i;
+       char *t;
+       int n = 0;
+
+       if ( fr->style != NULL ) {
+
+               /* FIXME: Horrible to do this using names and string comparisons
+                *  - what if the stylesheets are in different languages?
+                * Better would be to have "roles" for common types of style
+                * and match using those. */
+
+               t = fr->style->name;
+
+               for ( i=0; i<ss->n_styles; i++ ) {
+                       if ( strcmp(t, ss->styles[i]->name) == 0 ) {
+                               fr->style = ss->styles[i];
+                               n = 1;
+                               break;
+                       }
+               }
+       }
+
+       for ( i=0; i<fr->num_children; i++ ) {
+               n += fixup_styles(fr->children[i], ss);
+       }
+
+       return n;
+}
+
+
+static void fixup_templates(struct slide *s, StyleSheet *ss)
+{
+       int i;
+       char *t;
+
+       if ( s->st != NULL ) {
+
+               /* FIXME: Horrible to do this using names and string comparisons
+                *  - what if the stylesheets are in different languages?
+                * Better would be to have "roles" for common types of template
+                * and match using those. */
+
+               t = s->st->name;
+
+               for ( i=0; i<ss->n_templates; i++ ) {
+                       if ( strcmp(t, ss->templates[i]->name) == 0 ) {
+                               s->st = ss->templates[i];
+                               break;
+                       }
+               }
+       }
+}
+
+
+int replace_stylesheet(struct presentation *p, const char *filename)
+{
+       FILE *fh;
+       struct ds_node *root;
+       struct ds_node *node;
+       StyleSheet *ss;
+       int i;
+
+       fh = fopen(filename, "r");
+       if ( fh == NULL ) return 1;
+
+       root = new_ds_node("root");
+       if ( root == NULL ) return 1;
+
+       if ( deserialize_file(fh, root) ) {
+               fclose(fh);
+               return 1;
+       }
+
+       fclose(fh);
+
+       node = find_node(root, "stylesheet", 0);
+       if ( node == NULL ) {
+               free_ds_tree(root);
+               return 1;
+       }
+       ss = tree_to_stylesheet(node);
+       if ( ss == NULL ) {
+               fprintf(stderr, "Invalid style sheet\n");
+               return 1;
+       }
+       free_ds_tree(root);
+
+       for ( i=0; i<p->num_slides; i++ ) {
+               int n;
+               n = fixup_styles(p->slides[i]->top, ss);
+               printf("Fixed up %i styles\n", n);
+               fixup_templates(p->slides[i], ss);
+       }
+
+       free_stylesheet(p->ss);
+       p->ss = ss;
+
+       return 0;
+}
+
+
 StyleSheet *new_stylesheet()
 {
        StyleSheet *ss;
index cea714b..6879a95 100644 (file)
@@ -61,6 +61,7 @@ extern StyleSheet *new_stylesheet();
 extern StyleSheet *load_stylesheet(const char *filename);
 extern void free_stylesheet(StyleSheet *ss);
 extern StyleSheet *default_stylesheet(void);
+extern int replace_stylesheet(struct presentation *p, const char *filename);
 
 extern struct style *new_style(StyleSheet *ss, const char *name);
 extern struct style *default_style(StyleSheet *ss);