From 9af6e06992969133fd81942a376be904e7e46319 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sun, 18 Aug 2013 23:29:17 +0200 Subject: Add "Load stylesheet" --- src/mainwindow.c | 263 +++++++++++++++++++++++++++++++++---------------------- src/stylesheet.c | 103 ++++++++++++++++++++++ src/stylesheet.h | 1 + 3 files changed, 260 insertions(+), 107 deletions(-) (limited to 'src') diff --git a/src/mainwindow.c b/src/mainwindow.c index 95df042..c5d9a9c 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -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; in_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; in_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; in_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; in_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); } diff --git a/src/stylesheet.c b/src/stylesheet.c index 18a55b2..9d81e20 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -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; in_styles; i++ ) { + if ( strcmp(t, ss->styles[i]->name) == 0 ) { + fr->style = ss->styles[i]; + n = 1; + break; + } + } + } + + for ( i=0; inum_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; in_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; inum_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; diff --git a/src/stylesheet.h b/src/stylesheet.h index cea714b..6879a95 100644 --- a/src/stylesheet.h +++ b/src/stylesheet.h @@ -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); -- cgit v1.2.3