1 /*
2  *  Copyright (c) 2009 Giuseppe Torelli <colossus73@gmail.com>
3  *  Copyright (c) 2009 Tadej Borovšak 	<tadeboro@gmail.com>
4  *  Copyright (c) 2011 Robert Chéramy   <robert@cheramy.net>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License,or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not,write to the Free Software
18  *  Foundation,Inc.,59 Temple Place - Suite 330,Boston,MA 02111-1307,USA.
19  *
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25 #include <assert.h>
26 
27 #include "main-window.h"
28 #include "callbacks.h"
29 #include "export.h"
30 #include "subtitles.h"
31 #include "imgcellrendererpixbuf.h"
32 
33 static const GtkTargetEntry drop_targets[] =
34 {
35 	{ "text/uri-list",0,0 },
36 };
37 
38 /* ****************************************************************************
39  * Local function declarations
40  * ************************************************************************* */
41 static void img_combo_box_transition_type_changed (GtkComboBox *, img_window_struct *);
42 static void img_random_button_clicked(GtkButton *, img_window_struct *);
43 static GdkPixbuf *img_set_random_transition(img_window_struct *, slide_struct *);
44 static void img_combo_box_speed_changed (GtkComboBox *,  img_window_struct *);
45 static void img_spinbutton_value_changed (GtkSpinButton *, img_window_struct *);
46 static void img_slide_cut(GtkMenuItem * , img_window_struct *);
47 static void img_slide_copy(GtkMenuItem * , img_window_struct *);
48 static void img_slide_paste(GtkMenuItem* , img_window_struct *);
49 static void img_report_slides_transitions(img_window_struct *);
50 static void img_clear_audio_files(GtkButton *, img_window_struct *);
51 static void img_expand_button_clicked(GtkButton *, img_window_struct *);
52 static void img_on_drag_audio_data_received (GtkWidget *,GdkDragContext *, int, int, GtkSelectionData *, unsigned int, unsigned int, img_window_struct *);
53 static gboolean img_sub_textview_focus_in (GtkWidget *, GdkEventFocus *, img_window_struct *);
54 static gboolean img_sub_textview_focus_out(GtkWidget *, GdkEventFocus *, img_window_struct *);
55 static void img_activate_remove_button_music_liststore(GtkTreeModel *, GtkTreePath *, GtkTreeIter *, img_window_struct *);
56 static void img_quit_menu(GtkMenuItem *, img_window_struct *);
57 static void img_select_all_thumbnails(GtkMenuItem *, img_window_struct *);
58 static void img_unselect_all_thumbnails(GtkMenuItem *, img_window_struct *);
59 static void img_goto_line_entry_activate(GtkWidget *, img_window_struct *);
60 static gint img_sort_none_before_other(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer);
61 static void img_check_numeric_entry (GtkEditable *entry, gchar *text, gint lenght, gint *position, gpointer data);
62 static void img_show_uri(GtkMenuItem *, img_window_struct *);
63 static void img_select_slide_from_slide_report_dialog(GtkButton *, img_window_struct *);
64 static void img_show_slides_report_dialog(GtkMenuItem *, img_window_struct *);
65 
66 static gboolean
67 img_iconview_selection_button_press( GtkWidget         *widget,
68 									 GdkEventButton    *button,
69 									 img_window_struct *img );
70 
71 static gboolean
72 img_scroll_thumb( GtkWidget         *widget,
73 				  GdkEventScroll    *scroll,
74 				  img_window_struct *img );
75 
76 static gboolean
77 img_subtitle_update( img_window_struct *img );
78 
79 static GtkWidget *
80 img_create_subtitle_animation_combo( void );
81 
82 static void
83 img_toggle_mode( GtkCheckMenuItem  *item,
84 				 img_window_struct *img );
85 
86 static gint
87 img_sort_report_transitions( gconstpointer a,
88 							 gconstpointer b );
89 
90 static void
91 img_toggle_frame_rate( GtkCheckMenuItem  *item,
92 					   img_window_struct *img );
93 
94 
95 /* ****************************************************************************
96  * Function definitions
97  * ************************************************************************* */
img_create_window(void)98 img_window_struct *img_create_window (void)
99 {
100 	img_window_struct *img_struct = NULL;
101 	GtkWidget *vbox1;
102 	GtkWidget *menubar;
103 	GtkWidget *menuitem1;
104 	GtkWidget *menu1;
105 	GtkWidget *imagemenuitem1;
106 	GtkWidget *imagemenuitem5;
107 	GtkWidget *separatormenuitem1;
108 	GtkWidget *menuitem2;
109 	GtkWidget *slide_menu;
110 	GtkWidget *separator_slide_menu;
111 	GtkWidget *image_menu;
112 	GtkWidget *select_all_menu;
113 	GtkWidget *deselect_all_menu;
114 	GtkWidget *menuitem3;
115 	GtkWidget *tmp_image;
116 	GtkWidget *menu3;
117 	GtkWidget *about;
118 	GtkWidget *contents;
119 	GtkWidget *toolbar;
120 	GtkWidget *new_button;
121 	GtkWidget *add_slide;
122 	GtkWidget *separatortoolitem;
123 	GtkWidget *toolbutton_slide_goto;
124 	GtkWidget *first_slide, *last_slide, *prev_slide, *next_slide, *label_of;
125 	GtkWidget *notebook;
126 	GtkWidget *video_tab;
127 	GtkWidget *audio_tab;
128 	GtkWidget *swindow, *scrollable_window;
129 	GtkWidget *viewport;
130 	GtkWidget *align;
131 	GtkWidget *image_area_frame;
132 	GtkWidget *vbox_frames, *vbox_audio_frames, *frame1_alignment, *frame2_alignment, *frame3_alignment,*frame4_alignment;
133 	GtkWidget *frame1, *frame2, *frame3, *frame4, *frame_label;
134 	GtkWidget *transition_label;
135 	GtkWidget *vbox_info_slide, *vbox_slide_motion, *vbox_slide_caption;
136 	GtkWidget *table;
137 	GtkWidget *duration_label;
138 	GtkWidget *trans_duration_label;
139 	GtkWidget *total_time;
140 	GtkWidget *hbox_stop_points, *stop_points_label;
141 	GtkWidget *hbox_time_offset, *time_offset_label;
142 	GtkWidget *hbox_textview, *text_animation_hbox;
143 	GtkWidget *hbox_music_label;
144 	GtkWidget *music_time;
145 	GtkWidget *hbox_buttons, *move_up_button;
146 	GtkWidget *move_down_button, *clear_button, *image_buttons, *vbox2, *scrolledwindow1;
147     GtkWidget *message_scroll, *message_view;
148 	GtkCellRenderer *renderer, *pixbuf_cell;
149 	GtkTreeSelection *selection;
150 	GtkTreeViewColumn *column;
151 	GtkIconSize tmp_toolbar_icon_size;
152 	GtkIconTheme *icon_theme;
153 	GdkPixbuf *icon;
154 	gint x;
155 	GtkWidget *eventbox;
156 	GtkWidget *a_label;
157 	GtkWidget *a_hbox;
158 	GtkWidget *modes_vbox;
159 
160 	/* Added after cleaning up the img_window_struct */
161 	GtkWidget *properties_menu;
162 	GtkWidget *import_menu;
163 	GtkWidget *import_audio_menu;
164 	GtkWidget *import_button;
165 	GtkWidget *import_audio_button;
166 	GtkWidget *remove_button;
167 	GtkWidget *zoom_in_button, *zoom_out_button, *zoom_normal, *zoom_fit;
168 	GtkWidget *export_menu;
169 	GtkWidget *thumb_scrolledwindow;
170 	GdkPixbuf *pixbuf;
171 	GtkWidget *rotate_left_menu;
172 	GtkWidget *rotate_right_menu;
173 	GtkWidget *rotate_left_button;
174 	GtkWidget *rotate_right_button;
175 
176 	GtkWidget *tmp_checks[PREVIEW_FPS_NO_PRESETS];
177 
178 	img_struct = g_new0(img_window_struct, 1);
179 
180 	/* Set some default values */
181 	img_struct->background_color[0] = 0;
182 	img_struct->background_color[1] = 0;
183 	img_struct->background_color[2] = 0;
184 	img_struct->slides_nr = 0;
185 	img_struct->distort_images = TRUE;
186 
187 	img_struct->maxoffx = 0;
188 	img_struct->maxoffy = 0;
189 	img_struct->current_point.offx = 0;
190 	img_struct->current_point.offy = 0;
191 	img_struct->current_point.zoom = 1;
192 
193 	img_struct->video_size[0] = 720;
194 	img_struct->video_size[1] = 576;
195 	img_struct->video_ratio = (gdouble)720 / 576;
196 
197 	img_struct->final_transition.duration = 0;
198 	img_struct->final_transition.render = NULL;
199 	img_struct->final_transition.speed = NORMAL;
200 
201 
202 	/* GUI STUFF */
203 	icon_theme = gtk_icon_theme_get_default();
204 	icon = gtk_icon_theme_load_icon(icon_theme, "imagination", 24, 0, NULL);
205 
206 	img_struct->imagination_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
207 	gtk_window_set_icon (GTK_WINDOW(img_struct->imagination_window),icon);
208 	gtk_window_set_position (GTK_WINDOW(img_struct->imagination_window),GTK_WIN_POS_CENTER);
209 	img_set_window_title(img_struct,NULL);
210 	g_signal_connect (G_OBJECT (img_struct->imagination_window),"delete-event",G_CALLBACK (img_quit_application),img_struct);
211 	g_signal_connect (G_OBJECT (img_struct->imagination_window), "destroy", G_CALLBACK (gtk_main_quit), NULL );
212 	img_struct->accel_group = gtk_accel_group_new();
213 
214 	vbox1 = gtk_vbox_new (FALSE, 0);
215 	gtk_widget_show (vbox1);
216 	gtk_container_add (GTK_CONTAINER (img_struct->imagination_window), vbox1);
217 
218 	/* Create the menu items */
219 	menubar = gtk_menu_bar_new ();
220 	gtk_box_pack_start (GTK_BOX (vbox1), menubar, FALSE, TRUE, 0);
221 
222 	menuitem1 = gtk_menu_item_new_with_mnemonic (_("_Slideshow"));
223 	gtk_container_add (GTK_CONTAINER (menubar), menuitem1);
224 
225 	menu1 = gtk_menu_new ();
226 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menu1);
227 
228 	imagemenuitem1 = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, img_struct->accel_group);
229 	gtk_container_add (GTK_CONTAINER (menu1), imagemenuitem1);
230 	g_signal_connect (G_OBJECT (imagemenuitem1),"activate",G_CALLBACK (img_new_slideshow),img_struct);
231 
232 	img_struct->open_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_OPEN, img_struct->accel_group);
233 	gtk_container_add (GTK_CONTAINER (menu1), img_struct->open_menu);
234 	g_signal_connect (G_OBJECT (img_struct->open_menu),"activate",G_CALLBACK (img_choose_slideshow_filename),img_struct);
235 
236     img_struct->import_project_menu = gtk_image_menu_item_new_with_label (_("Import slideshow"));
237     gtk_container_add (GTK_CONTAINER (menu1),img_struct->import_project_menu);
238     g_signal_connect (G_OBJECT (img_struct->import_project_menu),"activate",G_CALLBACK (img_choose_slideshow_filename),img_struct);
239 
240     pixbuf = gtk_icon_theme_load_icon(icon_theme, GTK_STOCK_ADD, 18, 0, NULL);
241     image_menu = gtk_image_new_from_pixbuf(pixbuf);
242     g_object_unref(pixbuf);
243     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (img_struct->import_project_menu),image_menu);
244 
245 	img_struct->save_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE, img_struct->accel_group);
246 	gtk_container_add (GTK_CONTAINER (menu1), img_struct->save_menu);
247 	g_signal_connect (G_OBJECT (img_struct->save_menu),"activate",G_CALLBACK (img_choose_slideshow_filename),img_struct);
248 
249 	img_struct->save_as_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, img_struct->accel_group);
250 	gtk_container_add (GTK_CONTAINER (menu1), img_struct->save_as_menu);
251 	g_signal_connect (G_OBJECT (img_struct->save_as_menu),"activate",G_CALLBACK (img_choose_slideshow_filename),img_struct);
252 
253 	img_struct->close_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLOSE, img_struct->accel_group);
254 	gtk_container_add (GTK_CONTAINER (menu1), img_struct->close_menu);
255 	g_signal_connect (G_OBJECT (img_struct->close_menu),"activate",G_CALLBACK (img_close_slideshow),img_struct);
256 
257 	separatormenuitem1 = gtk_separator_menu_item_new ();
258 	gtk_container_add (GTK_CONTAINER (menu1), separatormenuitem1);
259 
260 	import_menu = gtk_image_menu_item_new_with_mnemonic (_("Import p_ictures"));
261 	gtk_container_add (GTK_CONTAINER (menu1),import_menu);
262 	gtk_widget_add_accelerator (import_menu,"activate",img_struct->accel_group,GDK_i,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
263 	g_signal_connect (G_OBJECT (import_menu),"activate",G_CALLBACK (img_add_slides_thumbnails),img_struct);
264 
265 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"image", 18, 0, NULL);
266 	image_menu = gtk_image_new_from_pixbuf(pixbuf);
267 	g_object_unref(pixbuf);
268 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (import_menu),image_menu);
269 
270 	import_audio_menu = gtk_image_menu_item_new_with_mnemonic (_("Import _music"));
271 	gtk_container_add (GTK_CONTAINER (menu1),import_audio_menu);
272 	gtk_widget_add_accelerator (import_audio_menu,"activate",img_struct->accel_group,GDK_m,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
273 	g_signal_connect (G_OBJECT (import_audio_menu),"activate",G_CALLBACK (img_select_audio_files_to_add),img_struct);
274 
275 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"sound", 18, 0, NULL);
276 	image_menu = gtk_image_new_from_pixbuf(pixbuf);
277 	g_object_unref(pixbuf);
278 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (import_audio_menu),image_menu);
279 
280 	properties_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_PROPERTIES, img_struct->accel_group);
281 	gtk_container_add (GTK_CONTAINER (menu1), properties_menu);
282 	g_signal_connect (G_OBJECT (properties_menu), "activate", G_CALLBACK (img_project_properties), img_struct);
283 
284 	separatormenuitem1 = gtk_separator_menu_item_new ();
285 	gtk_container_add (GTK_CONTAINER (menu1), separatormenuitem1);
286 
287 	img_struct->preview_menu = gtk_image_menu_item_new_with_mnemonic (_("_Preview"));
288 	gtk_container_add (GTK_CONTAINER (menu1), img_struct->preview_menu);
289 	gtk_widget_add_accelerator (img_struct->preview_menu, "activate",img_struct->accel_group,GDK_p,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
290 	g_signal_connect (G_OBJECT (img_struct->preview_menu),"activate",G_CALLBACK (img_start_stop_preview),img_struct);
291 
292 	tmp_image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY,GTK_ICON_SIZE_MENU);
293 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (img_struct->preview_menu),tmp_image);
294 
295 	export_menu = gtk_image_menu_item_new_with_mnemonic (_("Export"));
296 	gtk_container_add (GTK_CONTAINER (menu1), export_menu);
297 	g_signal_connect (G_OBJECT (export_menu),"activate",G_CALLBACK (img_choose_exporter),img_struct);
298 
299 	image_menu = img_load_icon ("imagination-generate.png",GTK_ICON_SIZE_MENU);
300 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (export_menu),image_menu);
301 
302 	separatormenuitem1 = gtk_separator_menu_item_new ();
303 	gtk_container_add (GTK_CONTAINER (menu1), separatormenuitem1);
304 
305 	imagemenuitem5 = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, img_struct->accel_group);
306 	gtk_container_add (GTK_CONTAINER (menu1), imagemenuitem5);
307 	g_signal_connect (G_OBJECT (imagemenuitem5),"activate",G_CALLBACK (img_quit_menu),img_struct);
308 
309 	/* Slide menu */
310 	menuitem2 = gtk_menu_item_new_with_mnemonic (_("_Slide"));
311 	gtk_container_add (GTK_CONTAINER (menubar), menuitem2);
312 
313 	slide_menu = gtk_menu_new ();
314 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem2), slide_menu);
315 
316 	img_struct->cut = gtk_image_menu_item_new_from_stock (GTK_STOCK_CUT, img_struct->accel_group);
317 	gtk_container_add (GTK_CONTAINER (slide_menu), img_struct->cut);
318 	g_signal_connect (G_OBJECT (img_struct->cut), "activate", G_CALLBACK (img_slide_cut), img_struct);
319 
320 	img_struct->copy = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, img_struct->accel_group);
321 	gtk_container_add (GTK_CONTAINER (slide_menu), img_struct->copy);
322 	g_signal_connect (G_OBJECT (img_struct->copy), "activate", G_CALLBACK (img_slide_copy), img_struct);
323 
324 	img_struct->paste = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, img_struct->accel_group);
325 	gtk_container_add (GTK_CONTAINER (slide_menu), img_struct->paste);
326 	g_signal_connect (G_OBJECT (img_struct->paste), "activate", G_CALLBACK (img_slide_paste), img_struct);
327 
328 	separator_slide_menu = gtk_separator_menu_item_new ();
329 	gtk_container_add (GTK_CONTAINER (slide_menu),separator_slide_menu);
330 
331 	/* Preview quality menu */
332 	menuitem1 = gtk_menu_item_new_with_mnemonic( _("Preview quality") );
333 	gtk_menu_shell_append( GTK_MENU_SHELL( slide_menu ), menuitem1 );
334 
335 	menu3 = gtk_menu_new();
336 	gtk_menu_item_set_submenu( GTK_MENU_ITEM( menuitem1 ), menu3 );
337 
338 	menuitem2 = gtk_radio_menu_item_new_with_mnemonic( NULL, _("_Low") );
339 	gtk_menu_shell_append( GTK_MENU_SHELL( menu3 ), menuitem2 );
340 	g_signal_connect( G_OBJECT( menuitem2 ), "toggled",
341 					  G_CALLBACK( img_quality_toggled ), img_struct );
342 	menuitem3 = gtk_radio_menu_item_new_with_mnemonic_from_widget(GTK_RADIO_MENU_ITEM( menuitem2 ), _("High") );
343 	gtk_menu_shell_append( GTK_MENU_SHELL( menu3 ), menuitem3 );
344 
345 	/* Zoom controls */
346 	menuitem1 = gtk_menu_item_new_with_mnemonic( _("_Zoom") );
347 	gtk_menu_shell_append( GTK_MENU_SHELL( slide_menu ), menuitem1 );
348 
349 	menu3 = gtk_menu_new();
350 	gtk_menu_item_set_submenu( GTK_MENU_ITEM( menuitem1 ), menu3 );
351 
352 	menuitem2 = gtk_image_menu_item_new_from_stock( GTK_STOCK_ZOOM_IN,img_struct->accel_group );
353 	gtk_widget_add_accelerator( menuitem2, "activate", img_struct->accel_group, GDK_plus,GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
354 	g_signal_connect( G_OBJECT( menuitem2 ), "activate",
355 					  G_CALLBACK( img_zoom_in ), img_struct );
356 	gtk_menu_shell_append( GTK_MENU_SHELL( menu3 ), menuitem2 );
357 
358 	menuitem2 = gtk_image_menu_item_new_from_stock( GTK_STOCK_ZOOM_OUT, img_struct->accel_group );
359 	gtk_widget_add_accelerator( menuitem2, "activate", img_struct->accel_group, GDK_minus, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
360 	g_signal_connect( G_OBJECT( menuitem2 ), "activate",
361 					  G_CALLBACK( img_zoom_out ), img_struct );
362 	gtk_menu_shell_append( GTK_MENU_SHELL( menu3 ), menuitem2 );
363 
364 	menuitem2 = gtk_image_menu_item_new_from_stock( GTK_STOCK_ZOOM_100,	img_struct->accel_group );
365 	gtk_widget_add_accelerator( menuitem2, "activate", img_struct->accel_group, GDK_0,GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
366 	g_signal_connect( G_OBJECT( menuitem2 ), "activate",
367 					  G_CALLBACK( img_zoom_reset ), img_struct );
368 	gtk_menu_shell_append( GTK_MENU_SHELL( menu3 ), menuitem2 );
369 
370 	separator_slide_menu = gtk_separator_menu_item_new ();
371 	gtk_container_add (GTK_CONTAINER (slide_menu),separator_slide_menu);
372 
373 	add_slide = gtk_image_menu_item_new_with_mnemonic (_("Add empt_y slide"));
374 	gtk_container_add (GTK_CONTAINER (slide_menu), add_slide);
375 	gtk_widget_add_accelerator( add_slide, "activate", img_struct->accel_group,	GDK_y, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
376 	g_signal_connect( G_OBJECT( add_slide ), "activate",
377 					  G_CALLBACK( img_add_empty_slide ), img_struct );
378 
379 	image_menu = img_load_icon ("imagination-add-new-slide.png",GTK_ICON_SIZE_MENU);
380 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_slide), image_menu);
381 
382 	img_struct->remove_menu = gtk_image_menu_item_new_with_mnemonic (_("Dele_te"));
383 	gtk_container_add (GTK_CONTAINER (slide_menu), img_struct->remove_menu);
384 	gtk_widget_add_accelerator (img_struct->remove_menu,"activate",img_struct->accel_group, GDK_Delete,0,GTK_ACCEL_VISIBLE);
385 	g_signal_connect (G_OBJECT (img_struct->remove_menu),"activate",G_CALLBACK (img_delete_selected_slides),img_struct);
386 
387 	tmp_image = gtk_image_new_from_stock (GTK_STOCK_DELETE,GTK_ICON_SIZE_MENU);
388 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (img_struct->remove_menu),tmp_image);
389 
390 	img_struct->report_menu = gtk_image_menu_item_new_with_mnemonic (_("Repor_t"));
391 	gtk_container_add (GTK_CONTAINER (slide_menu), img_struct->report_menu);
392 	gtk_widget_add_accelerator( img_struct->report_menu, "activate", img_struct->accel_group, GDK_t, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
393 	g_signal_connect (G_OBJECT (img_struct->report_menu),"activate",G_CALLBACK (img_show_slides_report_dialog),img_struct);
394 
395 	tmp_image = gtk_image_new_from_stock (GTK_STOCK_INDEX,GTK_ICON_SIZE_MENU);
396 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (img_struct->report_menu),tmp_image);
397 
398 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"object-rotate-left",18,0,NULL);
399 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
400 	g_object_unref(pixbuf);
401 
402 	rotate_left_menu = gtk_image_menu_item_new_with_mnemonic (_("Rotate co_unter-clockwise"));
403 	gtk_container_add (GTK_CONTAINER (slide_menu),rotate_left_menu);
404 	gtk_widget_add_accelerator (rotate_left_menu,"activate",img_struct->accel_group, GDK_u,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
405 	g_signal_connect( G_OBJECT( rotate_left_menu ), "activate",
406 					  G_CALLBACK( img_rotate_slides_left), img_struct );
407 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (rotate_left_menu),tmp_image);
408 
409 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"object-rotate-right",18,0,NULL);
410 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
411 	g_object_unref(pixbuf);
412 
413 	rotate_right_menu = gtk_image_menu_item_new_with_mnemonic (_("_Rotate clockwise"));
414 	gtk_container_add (GTK_CONTAINER (slide_menu),rotate_right_menu);
415 	gtk_widget_add_accelerator (rotate_right_menu,"activate",img_struct->accel_group, GDK_r,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
416 	g_signal_connect( G_OBJECT( rotate_right_menu ), "activate",
417 					  G_CALLBACK ( img_rotate_slides_right ), img_struct );
418 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (rotate_right_menu),tmp_image);
419 
420 	separator_slide_menu = gtk_separator_menu_item_new ();
421 	gtk_container_add (GTK_CONTAINER (slide_menu),separator_slide_menu);
422 
423 	select_all_menu = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, img_struct->accel_group);
424 	gtk_container_add (GTK_CONTAINER (slide_menu),select_all_menu);
425 	gtk_widget_add_accelerator (select_all_menu,"activate",img_struct->accel_group,GDK_a,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
426 	g_signal_connect (G_OBJECT (select_all_menu),"activate",G_CALLBACK (img_select_all_thumbnails),img_struct);
427 
428 	deselect_all_menu = gtk_image_menu_item_new_with_mnemonic (_("Un_select all"));
429 	gtk_container_add (GTK_CONTAINER (slide_menu),deselect_all_menu);
430 	gtk_widget_add_accelerator (deselect_all_menu,"activate",img_struct->accel_group,GDK_e,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
431 	g_signal_connect (G_OBJECT (deselect_all_menu),"activate",G_CALLBACK (img_unselect_all_thumbnails),img_struct);
432 
433 	/* View menu */
434 	menuitem1 = gtk_menu_item_new_with_mnemonic (_("_View"));
435 	gtk_container_add (GTK_CONTAINER (menubar), menuitem1);
436 
437 	menu1 = gtk_menu_new ();
438 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menu1);
439 
440 	img_struct->menu_preview_mode = gtk_radio_menu_item_new_with_label( NULL, _("Preview mode") );
441 	g_signal_connect( G_OBJECT( img_struct->menu_preview_mode ), "toggled",
442 					  G_CALLBACK( img_toggle_mode ), img_struct );
443 	gtk_menu_shell_append( GTK_MENU_SHELL( menu1 ), img_struct->menu_preview_mode );
444 
445 	img_struct->menu_overview_mode = gtk_radio_menu_item_new_with_label_from_widget(
446 							GTK_RADIO_MENU_ITEM( img_struct->menu_preview_mode ), _("Overview mode") );
447 	gtk_menu_shell_append( GTK_MENU_SHELL( menu1 ), img_struct->menu_overview_mode );
448 
449 	menuitem1 = gtk_separator_menu_item_new();
450 	gtk_menu_shell_append( GTK_MENU_SHELL( menu1 ), menuitem1 );
451 
452 	menuitem1 = gtk_menu_item_new_with_mnemonic( _("Preview _frame rate") );
453 	gtk_menu_shell_append( GTK_MENU_SHELL( menu1 ), menuitem1 );
454 
455 	menu1 = gtk_menu_new();
456 	gtk_menu_item_set_submenu( GTK_MENU_ITEM( menuitem1 ), menu1 );
457 
458 	{
459 		gint       i,
460 				   j;
461 		GtkWidget *item;
462 		gchar     *label;
463 		GSList    *group = NULL;
464 
465 		for( i = 0, j = PREVIEW_FPS_MIN;
466 			 i < PREVIEW_FPS_NO_PRESETS;
467 			 i++, j += PREVIEW_FPS_STEP )
468 		{
469 			label = g_strdup_printf( ngettext( "%d frame per second",
470 											   "%d frames per second",
471 											   j ),
472 									 j );
473 			item = gtk_radio_menu_item_new_with_label( group, label );
474 			tmp_checks[i] = item;
475 			g_signal_connect( G_OBJECT( item ), "toggled",
476 							  G_CALLBACK( img_toggle_frame_rate ), img_struct );
477 			g_object_set_data( G_OBJECT( item ), "index",
478 							   GINT_TO_POINTER( j ) );
479 			gtk_menu_shell_append( GTK_MENU_SHELL( menu1 ), item );
480 			g_free( label );
481 			group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM( item ) );
482 		}
483 	}
484 
485 	/* Help menu */
486 	menuitem3 = gtk_menu_item_new_with_mnemonic (_("_Help"));
487 	gtk_container_add (GTK_CONTAINER (menubar), menuitem3);
488 	menu3 = gtk_menu_new ();
489 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem3), menu3);
490 
491 	contents = gtk_image_menu_item_new_with_mnemonic (_("Contents"));
492 	gtk_container_add (GTK_CONTAINER (menu3),contents);
493 	gtk_widget_add_accelerator (contents,"activate",img_struct->accel_group,GDK_F1,GDK_MODE_DISABLED,GTK_ACCEL_VISIBLE);
494 	g_signal_connect (G_OBJECT (contents),"activate",G_CALLBACK (img_show_uri),img_struct);
495 
496 	tmp_image = gtk_image_new_from_stock ("gtk-help",GTK_ICON_SIZE_MENU);
497 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (contents),tmp_image);
498 
499 	about = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, img_struct->accel_group);
500 	gtk_container_add (GTK_CONTAINER (menu3), about);
501 	gtk_widget_show_all (menubar);
502 	g_signal_connect (G_OBJECT (about),"activate",G_CALLBACK (img_show_about_dialog),img_struct);
503 
504 	/* Create the toolbar */
505 	toolbar = gtk_toolbar_new ();
506 	gtk_box_pack_start (GTK_BOX (vbox1), toolbar, FALSE, FALSE, 0);
507 	gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
508 	tmp_toolbar_icon_size = gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar));
509 
510 	new_button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_NEW));
511 	gtk_container_add (GTK_CONTAINER (toolbar),new_button);
512 	gtk_widget_set_tooltip_text(new_button, _("Create a new slideshow"));
513 	g_signal_connect (G_OBJECT (new_button),"clicked",G_CALLBACK (img_new_slideshow),img_struct);
514 
515 	img_struct->open_button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_OPEN));
516 	gtk_container_add (GTK_CONTAINER (toolbar),img_struct->open_button);
517 	gtk_widget_set_tooltip_text(img_struct->open_button, _("Open a slideshow"));
518 	g_signal_connect (G_OBJECT (img_struct->open_button),"clicked",G_CALLBACK (img_choose_slideshow_filename),img_struct);
519 
520 	img_struct->save_button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_SAVE));
521 	gtk_container_add (GTK_CONTAINER (toolbar), img_struct->save_button);
522 	gtk_widget_set_tooltip_text(img_struct->save_button, _("Save the slideshow"));
523 	g_signal_connect (G_OBJECT (img_struct->save_button),"clicked",G_CALLBACK (img_choose_slideshow_filename),img_struct);
524 
525 	separatortoolitem = GTK_WIDGET (gtk_separator_tool_item_new());
526 	gtk_widget_show (separatortoolitem);
527 	gtk_container_add (GTK_CONTAINER (toolbar),separatortoolitem);
528 
529 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"image", 20, 0, NULL);
530 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
531 	g_object_unref(pixbuf);
532 
533 	import_button = GTK_WIDGET (gtk_tool_button_new (tmp_image,""));
534 	gtk_container_add (GTK_CONTAINER (toolbar),import_button);
535 	gtk_widget_set_tooltip_text(import_button, _("Import pictures"));
536 	g_signal_connect ((gpointer)import_button, "clicked", G_CALLBACK (img_add_slides_thumbnails),img_struct);
537 
538 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"sound", 20, 0, NULL);
539 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
540 	g_object_unref(pixbuf);
541 
542 	import_audio_button = GTK_WIDGET (gtk_tool_button_new (tmp_image,""));
543 	gtk_container_add (GTK_CONTAINER (toolbar),import_audio_button);
544 	gtk_widget_set_tooltip_text(import_audio_button, _("Import music"));
545 	g_signal_connect(G_OBJECT(import_audio_button), "clicked", G_CALLBACK(img_select_audio_files_to_add), img_struct);
546 
547 	remove_button = GTK_WIDGET (gtk_tool_button_new_from_stock ("gtk-delete"));
548 	gtk_container_add (GTK_CONTAINER (toolbar),remove_button);
549 	gtk_widget_set_tooltip_text(remove_button, _("Delete the selected slides"));
550 	g_signal_connect (G_OBJECT (remove_button),"clicked",G_CALLBACK (img_delete_selected_slides),img_struct);
551 
552 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"object-rotate-left",22,0,NULL);
553 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
554 	g_object_unref(pixbuf);
555 
556 	rotate_left_button = GTK_WIDGET (gtk_tool_button_new(tmp_image,""));
557 	gtk_container_add (GTK_CONTAINER (toolbar), rotate_left_button);
558 	gtk_widget_set_tooltip_text( rotate_left_button,
559 								 _("Rotate the slide 90 degrees to the left") );
560 	g_signal_connect( G_OBJECT( rotate_left_button ), "clicked",
561 					  G_CALLBACK (img_rotate_slides_left ), img_struct );
562 
563 	pixbuf = gtk_icon_theme_load_icon(icon_theme,"object-rotate-right",22,0,NULL);
564 	tmp_image = gtk_image_new_from_pixbuf(pixbuf);
565 	g_object_unref(pixbuf);
566 
567 	rotate_right_button = GTK_WIDGET (gtk_tool_button_new(tmp_image,""));
568 	gtk_container_add (GTK_CONTAINER (toolbar),rotate_right_button);
569 	gtk_widget_set_tooltip_text( rotate_right_button,
570 								 _("Rotate the slide 90 degrees to the right") );
571 	g_signal_connect( G_OBJECT( rotate_right_button ), "clicked",
572 					  G_CALLBACK( img_rotate_slides_right ), img_struct );
573 
574 	zoom_in_button = GTK_WIDGET (gtk_tool_button_new_from_stock ("gtk-zoom-in"));
575 	gtk_container_add (GTK_CONTAINER (toolbar),zoom_in_button);
576 	gtk_widget_set_tooltip_text(zoom_in_button, _("Zoom In"));
577 	g_signal_connect (G_OBJECT (zoom_in_button),"clicked",G_CALLBACK (img_zoom_in),img_struct);
578 
579 	zoom_out_button = GTK_WIDGET (gtk_tool_button_new_from_stock ("gtk-zoom-out"));
580 	gtk_container_add (GTK_CONTAINER (toolbar),zoom_out_button);
581 	gtk_widget_set_tooltip_text(zoom_out_button, _("Zoom Out"));
582 	g_signal_connect (G_OBJECT (zoom_out_button),"clicked",G_CALLBACK (img_zoom_out),img_struct);
583 
584 	zoom_normal = GTK_WIDGET (gtk_tool_button_new_from_stock ("gtk-zoom-100"));
585 	gtk_container_add (GTK_CONTAINER (toolbar),zoom_normal);
586 	gtk_widget_set_tooltip_text(zoom_normal, _("Normal Size"));
587 	g_signal_connect (G_OBJECT (zoom_normal),"clicked",G_CALLBACK (img_zoom_reset),img_struct);
588 
589     zoom_fit = GTK_WIDGET (gtk_tool_button_new_from_stock ("gtk-zoom-fit"));
590     gtk_container_add (GTK_CONTAINER (toolbar),zoom_fit);
591     gtk_widget_set_tooltip_text(zoom_fit, _("Fit Zoom in Window"));
592     g_signal_connect (G_OBJECT (zoom_fit),"clicked",G_CALLBACK (img_zoom_fit),img_struct);
593 
594 	separatortoolitem = GTK_WIDGET (gtk_separator_tool_item_new());
595 	gtk_container_add (GTK_CONTAINER (toolbar),separatortoolitem);
596 
597 	img_struct->preview_button = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_PLAY));
598 	gtk_container_add (GTK_CONTAINER (toolbar),img_struct->preview_button);
599 	gtk_widget_set_tooltip_text(img_struct->preview_button, _("Starts the preview"));
600 	g_signal_connect (G_OBJECT (img_struct->preview_button),"clicked",G_CALLBACK (img_start_stop_preview),img_struct);
601 
602 	separatortoolitem = GTK_WIDGET (gtk_separator_tool_item_new());
603 	gtk_container_add (GTK_CONTAINER (toolbar),separatortoolitem);
604 
605 	first_slide = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GOTO_FIRST));
606 	gtk_container_add (GTK_CONTAINER (toolbar),first_slide);
607 	gtk_widget_set_tooltip_text( first_slide,
608 								 _("Go to the first slide of the slideshow") );
609 	g_signal_connect (G_OBJECT (first_slide),"clicked",G_CALLBACK (img_goto_first_slide),img_struct);
610 
611 	prev_slide = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK));
612 	gtk_container_add (GTK_CONTAINER (toolbar),prev_slide);
613 	gtk_widget_set_tooltip_text( prev_slide,
614 								 _("Go to the previous slide of the slideshow") );
615 	g_signal_connect (G_OBJECT (prev_slide),"clicked",G_CALLBACK (img_goto_prev_slide),img_struct);
616 
617 	toolbutton_slide_goto = GTK_WIDGET(gtk_tool_item_new ());
618 	gtk_container_add (GTK_CONTAINER (toolbar), toolbutton_slide_goto);
619 
620 	img_struct->slide_number_entry = gtk_entry_new();
621 	gtk_entry_set_max_length(GTK_ENTRY (img_struct->slide_number_entry), 4);
622 	gtk_entry_set_width_chars(GTK_ENTRY (img_struct->slide_number_entry), 6);
623 	gtk_container_add(GTK_CONTAINER(toolbutton_slide_goto),img_struct->slide_number_entry);
624 	g_signal_connect(G_OBJECT (img_struct->slide_number_entry), "activate", G_CALLBACK(img_goto_line_entry_activate), img_struct);
625 	g_signal_connect(G_OBJECT (img_struct->slide_number_entry), "insert-text", G_CALLBACK (img_check_numeric_entry), NULL );
626 
627 	toolbutton_slide_goto = GTK_WIDGET(gtk_tool_item_new ());
628 	gtk_container_add (GTK_CONTAINER (toolbar), toolbutton_slide_goto);
629 
630 	label_of = gtk_label_new(_(" of "));
631 	gtk_container_add (GTK_CONTAINER (toolbutton_slide_goto),label_of);
632 
633 	toolbutton_slide_goto = GTK_WIDGET(gtk_tool_item_new ());
634 	gtk_container_add (GTK_CONTAINER (toolbar), toolbutton_slide_goto);
635 
636 	img_struct->total_slide_number_label = gtk_label_new(NULL);
637 	gtk_container_add (GTK_CONTAINER (toolbutton_slide_goto),img_struct->total_slide_number_label);
638 
639 	next_slide = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD));
640 	gtk_container_add (GTK_CONTAINER (toolbar),next_slide);
641 	gtk_widget_set_tooltip_text( next_slide,
642 								 _("Go to the next slide of the slideshow") );
643 	g_signal_connect (G_OBJECT (next_slide),"clicked",G_CALLBACK (img_goto_next_slide),img_struct);
644 
645 	last_slide = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GOTO_LAST));
646 	gtk_container_add (GTK_CONTAINER (toolbar),last_slide);
647 	gtk_widget_set_tooltip_text( last_slide,
648 								 _("Go to the last slide of the slideshow") );
649 	g_signal_connect (G_OBJECT (last_slide),"clicked",G_CALLBACK (img_goto_last_slide),img_struct);
650 
651 	gtk_widget_show_all (toolbar);
652 
653 	/* Create the image area and the other widgets */
654 	img_struct->paned = gtk_hpaned_new();
655 	gtk_box_pack_start (GTK_BOX (vbox1), img_struct->paned, TRUE, TRUE, 0);
656 
657 	modes_vbox = gtk_vbox_new( FALSE, 0 );
658 	gtk_paned_add1( GTK_PANED( img_struct->paned ), modes_vbox );
659 
660 	swindow = gtk_scrolled_window_new(NULL, NULL);
661 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
662 	gtk_box_pack_start( GTK_BOX( modes_vbox ), swindow, TRUE, TRUE, 0 );
663 	img_struct->prev_root = swindow;
664 
665 	viewport = gtk_viewport_new( NULL, NULL );
666 	gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
667 	gtk_container_add( GTK_CONTAINER( swindow ), viewport );
668 
669 	align = gtk_alignment_new(0.5, 0.5, 0, 0);
670 	gtk_container_add( GTK_CONTAINER( viewport ), align );
671 
672 	image_area_frame = gtk_frame_new(NULL);
673 	gtk_frame_set_shadow_type(GTK_FRAME(image_area_frame), GTK_SHADOW_IN);
674 	gtk_container_add(GTK_CONTAINER(align), image_area_frame);
675 
676 	align = gtk_event_box_new();
677 	gtk_container_add(GTK_CONTAINER(image_area_frame), align);
678 
679 	img_struct->image_area = gtk_drawing_area_new();
680 	gtk_widget_set_size_request( img_struct->image_area,
681 								 img_struct->video_size[0],
682 								 img_struct->video_size[1] );
683 	gtk_container_add(GTK_CONTAINER(align), img_struct->image_area);
684 	gtk_widget_add_events( img_struct->image_area, GDK_BUTTON1_MOTION_MASK
685 												 | GDK_POINTER_MOTION_HINT_MASK
686 												 | GDK_BUTTON_PRESS_MASK );
687 	g_signal_connect( G_OBJECT( img_struct->image_area ), "expose-event",
688 					  G_CALLBACK( img_on_expose_event ), img_struct );
689 	g_signal_connect( G_OBJECT( img_struct->image_area ), "button-press-event",
690 					  G_CALLBACK( img_image_area_button_press ), img_struct );
691 	g_signal_connect( G_OBJECT( img_struct->image_area ), "motion-notify-event",
692 					  G_CALLBACK( img_image_area_motion ), img_struct );
693 
694 	vbox_frames = gtk_vbox_new(FALSE, 10);
695 	scrollable_window = gtk_scrolled_window_new(NULL, NULL);
696 	g_object_set (G_OBJECT (scrollable_window),"hscrollbar-policy",GTK_POLICY_AUTOMATIC,"vscrollbar-policy",GTK_POLICY_AUTOMATIC,NULL);
697 	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollable_window), vbox_frames);
698 
699 	video_tab = gtk_label_new (_("Video"));
700 	notebook = gtk_notebook_new();
701 	gtk_paned_add2( GTK_PANED( img_struct->paned ), notebook );
702 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrollable_window, video_tab);
703 
704 	viewport = gtk_bin_get_child(GTK_BIN(scrollable_window));
705 	gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
706 	gtk_container_set_border_width( GTK_CONTAINER( viewport ), 10 );
707 
708 	/* Slide frame */
709 	frame1 = gtk_frame_new (NULL);
710 	gtk_box_pack_start (GTK_BOX (vbox_frames), frame1, FALSE, FALSE, 0);
711 	gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_OUT);
712 
713 	frame1_alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
714 	gtk_container_add (GTK_CONTAINER (frame1), frame1_alignment);
715 	gtk_alignment_set_padding (GTK_ALIGNMENT (frame1_alignment), 2, 2, 5, 5);
716 
717 	frame_label = gtk_label_new (_("<b>Slide Settings</b>"));
718 	gtk_frame_set_label_widget (GTK_FRAME (frame1), frame_label);
719 	gtk_label_set_use_markup (GTK_LABEL (frame_label), TRUE);
720 	gtk_misc_set_padding (GTK_MISC (frame_label), 2, 2);
721 
722 	vbox_info_slide = gtk_vbox_new (FALSE, 2);
723 	gtk_container_add (GTK_CONTAINER (frame1_alignment), vbox_info_slide);
724 	gtk_container_set_border_width (GTK_CONTAINER (vbox_info_slide), 2);
725 
726 	/* Transition types label */
727 	transition_label = gtk_label_new (_("Transition Type:"));
728 	gtk_box_pack_start (GTK_BOX (vbox_info_slide), transition_label, FALSE, FALSE, 0);
729 	gtk_misc_set_alignment (GTK_MISC (transition_label), 0, -1);
730 
731 	/* Slide selected, slide resolution, slide type and slide total duration */
732 	table = gtk_table_new (4, 2, FALSE);
733 	gtk_box_pack_start (GTK_BOX (vbox_info_slide), table, TRUE, TRUE, 0);
734 	gtk_table_set_row_spacings (GTK_TABLE (table), 4);
735 	gtk_table_set_col_spacings (GTK_TABLE (table), 4);
736 
737 	/* Transition type */
738 	img_struct->transition_type = _gtk_combo_box_new_text( TRUE );
739 	gtk_table_attach (GTK_TABLE (table), img_struct->transition_type, 0, 1, 0, 1,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (GTK_FILL), 0, 0);
740 	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(gtk_combo_box_get_model(GTK_COMBO_BOX(img_struct->transition_type))),
741 										1, GTK_SORT_ASCENDING);
742 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(gtk_combo_box_get_model(GTK_COMBO_BOX(img_struct->transition_type))),1, img_sort_none_before_other,NULL,NULL);
743 
744 	gtk_widget_set_sensitive(img_struct->transition_type, FALSE);
745 	g_signal_connect (G_OBJECT (img_struct->transition_type), "changed",G_CALLBACK (img_combo_box_transition_type_changed),img_struct);
746 
747 	img_struct->random_button = gtk_button_new_with_mnemonic (_("Random"));
748 	gtk_widget_set_tooltip_text(img_struct->random_button,_("Imagination randomly decides which transition to apply"));
749 	gtk_table_attach (GTK_TABLE (table), img_struct->random_button, 1, 2, 0, 1,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
750 	gtk_widget_set_sensitive(img_struct->random_button, FALSE);
751 	g_signal_connect (G_OBJECT (img_struct->random_button),"clicked",G_CALLBACK (img_random_button_clicked),img_struct);
752 
753 	/* Transition duration */
754 	trans_duration_label = gtk_label_new (_("Transition Speed:"));
755 	gtk_table_attach (GTK_TABLE (table), trans_duration_label, 0, 1, 1, 2,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
756 	gtk_misc_set_alignment (GTK_MISC (trans_duration_label), 0, 0.5);
757 
758 	img_struct->trans_duration = _gtk_combo_box_new_text(FALSE);
759 	gtk_table_attach (GTK_TABLE (table), img_struct->trans_duration, 1, 2, 1, 2,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (GTK_FILL), 0, 0);
760 	{
761 		GtkTreeIter   iter;
762 		GtkListStore *store = GTK_LIST_STORE( gtk_combo_box_get_model( GTK_COMBO_BOX( img_struct->trans_duration ) ) );
763 
764 		gtk_list_store_append( store, &iter );
765 		gtk_list_store_set( store, &iter, 0, _("Fast"), -1 );
766 		gtk_list_store_append( store, &iter );
767 		gtk_list_store_set( store, &iter, 0, _("Normal"), -1 );
768 		gtk_list_store_append( store, &iter );
769 		gtk_list_store_set( store, &iter, 0, _("Slow"), -1 );
770 	}
771 	gtk_combo_box_set_active(GTK_COMBO_BOX(img_struct->trans_duration),1);
772 	gtk_widget_set_sensitive(img_struct->trans_duration, FALSE);
773 	g_signal_connect (G_OBJECT (img_struct->trans_duration),"changed",G_CALLBACK (img_combo_box_speed_changed),img_struct);
774 
775 	/* Slide duration */
776 	duration_label = gtk_label_new (_("Slide Duration in sec:"));
777 	gtk_table_attach (GTK_TABLE (table), duration_label, 0, 1, 2, 3,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
778 	gtk_misc_set_alignment (GTK_MISC (duration_label), 0, 0.5);
779 
780 	img_struct->duration = gtk_spin_button_new_with_range (1, 300, 1);
781 	gtk_table_attach (GTK_TABLE (table), img_struct->duration, 1, 2, 2, 3,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
782 	gtk_widget_set_sensitive(img_struct->duration, FALSE);
783 	gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (img_struct->duration),TRUE);
784 	g_signal_connect (G_OBJECT (img_struct->duration),"value-changed",G_CALLBACK (img_spinbutton_value_changed),img_struct);
785 
786 	/* Slide Total Duration */
787 	total_time = gtk_label_new (_("Slideshow Length:"));
788 	gtk_table_attach (GTK_TABLE (table), total_time, 0, 1, 3, 4,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
789 	gtk_misc_set_alignment (GTK_MISC (total_time), 0, 0.5);
790 
791 	img_struct->total_time_data = gtk_label_new ("");
792 	gtk_table_attach (GTK_TABLE (table), img_struct->total_time_data, 1, 2, 3, 4,(GtkAttachOptions) (GTK_FILL),(GtkAttachOptions) (0), 0, 0);
793 	gtk_misc_set_alignment (GTK_MISC (img_struct->total_time_data), 0, 0.5);
794 
795 	/* Slide motion frame */
796 	frame2 = gtk_frame_new (NULL);
797 	gtk_box_pack_start (GTK_BOX (vbox_frames), frame2, FALSE, FALSE, 0);
798 	gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_OUT);
799 
800 	frame2_alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
801 	gtk_container_add (GTK_CONTAINER (frame2), frame2_alignment);
802 	gtk_alignment_set_padding (GTK_ALIGNMENT (frame2_alignment), 2, 2, 5, 5);
803 
804 	frame_label = gtk_label_new (_("<b>Slide Motion</b>"));
805 	gtk_frame_set_label_widget (GTK_FRAME (frame2), frame_label);
806 	gtk_label_set_use_markup (GTK_LABEL (frame_label), TRUE);
807 	gtk_misc_set_padding (GTK_MISC (frame_label), 2, 2);
808 
809 	vbox_slide_motion = gtk_vbox_new (FALSE, 2);
810 	gtk_container_add (GTK_CONTAINER (frame2_alignment), vbox_slide_motion);
811 
812 	hbox_stop_points = gtk_hbox_new(FALSE,5);
813 	gtk_box_pack_start (GTK_BOX (vbox_slide_motion), hbox_stop_points, TRUE, FALSE, 0);
814 	stop_points_label = gtk_label_new(_("Stop Point:"));
815 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), stop_points_label, TRUE, TRUE, 0);
816 	gtk_misc_set_alignment(GTK_MISC(stop_points_label),0.0, 0.5);
817 
818 	img_struct->ken_left = gtk_button_new();
819 	g_signal_connect( G_OBJECT( img_struct->ken_left ), "clicked",
820 					  G_CALLBACK( img_goto_prev_point ), img_struct );
821 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), img_struct->ken_left, FALSE, TRUE, 0);
822 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU);
823 	gtk_button_set_image(GTK_BUTTON(img_struct->ken_left), image_buttons);
824 
825 	img_struct->ken_entry = gtk_entry_new();
826 	gtk_entry_set_max_length(GTK_ENTRY (img_struct->ken_entry), 2);
827 	gtk_entry_set_width_chars(GTK_ENTRY (img_struct->ken_entry), 4);
828 	{
829 		GObject *object = G_OBJECT( img_struct->ken_entry );
830 
831 		g_signal_connect( object, "activate",
832 						  G_CALLBACK( img_goto_point ), img_struct );
833 		g_signal_connect( object, "insert-text",
834 						  G_CALLBACK( img_check_numeric_entry ), NULL );
835 	}
836 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), img_struct->ken_entry, FALSE, TRUE, 0);
837 	label_of = gtk_label_new(_(" of "));
838 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), label_of, FALSE, FALSE, 0);
839 	img_struct->total_stop_points_label = gtk_label_new(NULL);
840 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), img_struct->total_stop_points_label, FALSE, FALSE, 0);
841 
842 	img_struct->ken_right = gtk_button_new();
843 	g_signal_connect( G_OBJECT( img_struct->ken_right ), "clicked",
844 					  G_CALLBACK( img_goto_next_point ), img_struct );
845 	gtk_box_pack_start (GTK_BOX (hbox_stop_points), img_struct->ken_right, FALSE, TRUE, 0);
846 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU);
847 	gtk_button_set_image(GTK_BUTTON(img_struct->ken_right), image_buttons);
848 
849 	hbox_time_offset = gtk_hbox_new(FALSE,0);
850 	gtk_box_pack_start (GTK_BOX (vbox_slide_motion), hbox_time_offset, FALSE, FALSE, 0);
851 	time_offset_label = gtk_label_new(_("Duration:"));
852 	gtk_box_pack_start (GTK_BOX (hbox_time_offset), time_offset_label, TRUE, TRUE, 0);
853 	gtk_misc_set_alignment(GTK_MISC(time_offset_label),0.0, 0.5);
854 	img_struct->ken_duration = gtk_spin_button_new_with_range (1, 60, 1);
855 	gtk_box_pack_start (GTK_BOX (hbox_time_offset), img_struct->ken_duration, FALSE, FALSE, 0);
856 	gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (img_struct->ken_duration),TRUE);
857 	GtkWidget *hbox_zoom = gtk_hbox_new(FALSE,0);
858 	gtk_box_pack_start (GTK_BOX (vbox_slide_motion), hbox_zoom, FALSE, FALSE, 0);
859 
860 	GtkWidget *label = gtk_label_new(_("Zoom: "));
861 	gtk_misc_set_alignment(GTK_MISC(label),0.0, 0.5);
862 	gtk_box_pack_start (GTK_BOX (hbox_zoom), label, FALSE, TRUE, 0);
863 
864 	img_struct->ken_zoom = gtk_hscale_new_with_range(1,30,0.10000000000000001);
865 	gtk_scale_set_value_pos (GTK_SCALE(img_struct->ken_zoom), GTK_POS_LEFT);
866 	gtk_box_pack_start (GTK_BOX (hbox_zoom), img_struct->ken_zoom, TRUE, TRUE, 0);
867 	g_signal_connect( G_OBJECT( img_struct->ken_zoom ), "value-changed",
868 					  G_CALLBACK( img_ken_burns_zoom_changed ), img_struct );
869 
870 	hbox_buttons = gtk_hbutton_box_new();
871 	gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox_buttons), GTK_BUTTONBOX_SPREAD);
872 	gtk_box_pack_start (GTK_BOX (vbox_slide_motion), hbox_buttons, FALSE, FALSE, 0);
873 
874 	img_struct->ken_add = gtk_button_new_with_label(_("Add"));
875 	g_signal_connect( G_OBJECT( img_struct->ken_add ), "clicked",
876 					  G_CALLBACK( img_add_stop_point ), img_struct );
877 	gtk_box_pack_start (GTK_BOX (hbox_buttons), img_struct->ken_add, FALSE, FALSE, 0);
878 	img_struct->ken_update = gtk_button_new_with_label( _("Update") );
879 	g_signal_connect( G_OBJECT( img_struct->ken_update ), "clicked",
880 					  G_CALLBACK( img_update_stop_point ), img_struct );
881 	gtk_box_pack_start( GTK_BOX( hbox_buttons ), img_struct->ken_update,
882 						FALSE, FALSE, 0 );
883 	img_struct->ken_remove = gtk_button_new_with_label(_("Remove"));
884 	g_signal_connect( G_OBJECT( img_struct->ken_remove ), "clicked",
885 					  G_CALLBACK( img_delete_stop_point ), img_struct );
886 	gtk_box_pack_start (GTK_BOX (hbox_buttons), img_struct->ken_remove, FALSE, FALSE, 0);
887 
888 	/* Slide text frame */
889 	frame4 = gtk_frame_new (NULL);
890 	gtk_box_pack_start (GTK_BOX (vbox_frames), frame4, FALSE, FALSE, 0);
891 	gtk_frame_set_shadow_type (GTK_FRAME (frame4), GTK_SHADOW_OUT);
892 
893 	frame4_alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
894 	gtk_container_add (GTK_CONTAINER (frame4), frame4_alignment);
895 	gtk_alignment_set_padding (GTK_ALIGNMENT (frame4_alignment), 5, 5, 5, 5);
896 
897 	frame_label = gtk_label_new (_("<b>Slide Text</b>"));
898 	gtk_frame_set_label_widget (GTK_FRAME (frame4), frame_label);
899 	gtk_label_set_use_markup (GTK_LABEL (frame_label), TRUE);
900 	gtk_misc_set_padding (GTK_MISC (frame_label), 2, 2);
901 
902 	vbox_slide_caption = gtk_vbox_new (FALSE, 2);
903 	gtk_container_add (GTK_CONTAINER (frame4_alignment), vbox_slide_caption);
904 
905 	hbox_textview = gtk_hbox_new(FALSE, 2);
906 	gtk_box_pack_start (GTK_BOX (vbox_slide_caption), hbox_textview, FALSE, FALSE, 0);
907 
908 	img_struct->sub_textview = gtk_text_view_new();
909 	gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(img_struct->sub_textview), FALSE);
910 	img_struct->slide_text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(img_struct->sub_textview));
911 	g_signal_connect( G_OBJECT( img_struct->slide_text_buffer ), "changed",
912 					  G_CALLBACK( img_queue_subtitle_update ), img_struct );
913 	/* Let's connect the focus-in and focus-out events to prevent the
914 	 * DEL key when pressed inside the textview delete the selected slide */
915 	g_signal_connect( G_OBJECT( img_struct->sub_textview ), "focus-in-event",
916 					  G_CALLBACK( img_sub_textview_focus_in ), img_struct );
917 	g_signal_connect( G_OBJECT( img_struct->sub_textview ), "focus-out-event",
918 					  G_CALLBACK( img_sub_textview_focus_out ), img_struct );
919 	img_struct->scrolled_win = gtk_scrolled_window_new(NULL, NULL);
920 	gtk_widget_set_size_request(img_struct->scrolled_win, -1, 18);
921 	g_object_set (G_OBJECT (img_struct->scrolled_win),"hscrollbar-policy",GTK_POLICY_AUTOMATIC,"vscrollbar-policy",GTK_POLICY_AUTOMATIC,"shadow-type",GTK_SHADOW_IN,NULL);
922 	gtk_container_add(GTK_CONTAINER (img_struct->scrolled_win), img_struct->sub_textview);
923 	gtk_box_pack_start (GTK_BOX (hbox_textview), img_struct->scrolled_win, TRUE, TRUE, 0);
924 
925 	img_struct->expand_button = gtk_button_new();
926 	gtk_widget_set_tooltip_text(img_struct->expand_button, _("Click to expand the area"));
927 	gtk_button_set_relief(GTK_BUTTON(img_struct->expand_button), GTK_RELIEF_NONE);
928 	gtk_widget_set_size_request(img_struct->expand_button, 22, 20);
929 	g_signal_connect (G_OBJECT (img_struct->expand_button),"clicked",G_CALLBACK (img_expand_button_clicked),img_struct);
930 
931 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
932 	gtk_widget_set_size_request(image_buttons, 14, 14);
933 	gtk_button_set_image(GTK_BUTTON(img_struct->expand_button),image_buttons);
934 	gtk_box_pack_start (GTK_BOX (hbox_textview), img_struct->expand_button, FALSE, FALSE, 0);
935 
936 	text_animation_hbox = gtk_hbox_new( FALSE, 6 );
937 	gtk_box_pack_start( GTK_BOX( vbox_slide_caption ), text_animation_hbox, FALSE, FALSE, 0 );
938 
939 	img_struct->sub_font = gtk_font_button_new();
940 	g_signal_connect( G_OBJECT( img_struct->sub_font ), "font-set",
941 					  G_CALLBACK( img_text_font_set ), img_struct );
942 	gtk_box_pack_start (GTK_BOX (text_animation_hbox), img_struct->sub_font, TRUE, TRUE, 0);
943 	gtk_widget_set_tooltip_text(img_struct->sub_font, _("Click to choose the font"));
944 
945 	img_struct->sub_color = gtk_color_button_new();
946 	gtk_color_button_set_use_alpha( GTK_COLOR_BUTTON( img_struct->sub_color ), TRUE );
947 	g_signal_connect( G_OBJECT( img_struct->sub_color ), "color-set",
948 					  G_CALLBACK( img_font_color_changed ), img_struct );
949 	gtk_box_pack_start( GTK_BOX( text_animation_hbox ), img_struct->sub_color, FALSE, FALSE, 0 );
950     gtk_widget_set_tooltip_text(img_struct->sub_color, _("Click to choose the font color"));
951 
952     img_struct->sub_bgcolor = gtk_color_button_new();
953     gtk_color_button_set_use_alpha( GTK_COLOR_BUTTON( img_struct->sub_bgcolor ), TRUE );
954     g_signal_connect( G_OBJECT( img_struct->sub_bgcolor ), "color-set",
955                       G_CALLBACK( img_font_bgcolor_changed ), img_struct );
956     gtk_box_pack_start( GTK_BOX( text_animation_hbox ), img_struct->sub_bgcolor, FALSE, FALSE, 0 );
957     gtk_widget_set_tooltip_text(img_struct->sub_bgcolor, _("Click to choose the font background color"));
958 
959 	a_hbox = gtk_hbox_new(FALSE, 6);
960 	gtk_box_pack_start (GTK_BOX (vbox_slide_caption), a_hbox, FALSE, FALSE, 0);
961 	a_label = gtk_label_new(_("Animation:"));
962 	gtk_misc_set_alignment(GTK_MISC(a_label), 0.0, 0.5);
963 	gtk_box_pack_start (GTK_BOX (a_hbox), a_label, TRUE, TRUE, 0);
964 	img_struct->sub_anim = img_create_subtitle_animation_combo();
965 	gtk_combo_box_set_active(GTK_COMBO_BOX(img_struct->sub_anim), 0);
966 	g_signal_connect( G_OBJECT( img_struct->sub_anim ), "changed",
967 					  G_CALLBACK( img_text_anim_set ), img_struct );
968 	gtk_box_pack_start (GTK_BOX (a_hbox), img_struct->sub_anim, FALSE, FALSE, 0);
969 
970 	a_hbox = gtk_hbox_new(FALSE, 6);
971 	gtk_box_pack_start (GTK_BOX (vbox_slide_caption), a_hbox, FALSE, FALSE, 0);
972 
973 	a_label = gtk_label_new( _("Animation Speed:") );
974 	gtk_misc_set_alignment( GTK_MISC( a_label ), 0, 0.5 );
975 	gtk_box_pack_start( GTK_BOX( a_hbox ), a_label, TRUE, TRUE, 0 );
976 
977 	img_struct->sub_anim_duration = gtk_spin_button_new_with_range (1, 60, 1);
978 	gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (img_struct->sub_anim_duration),TRUE);
979 	gtk_box_pack_start( GTK_BOX( a_hbox ), img_struct->sub_anim_duration,
980 						FALSE, FALSE, 0 );
981 
982 	gtk_widget_set_sensitive( img_struct->sub_anim_duration, FALSE );
983 	g_signal_connect( G_OBJECT( img_struct->sub_anim_duration ), "value-changed",
984 					  G_CALLBACK( img_combo_box_anim_speed_changed ), img_struct );
985 
986 	a_hbox = gtk_hbox_new(FALSE, 6);
987 	gtk_box_pack_start( GTK_BOX( vbox_slide_caption ), a_hbox, FALSE, FALSE, 0 );
988 
989 	a_label = gtk_label_new( _("Placing is relative to:") );
990 	gtk_misc_set_alignment( GTK_MISC( a_label ), 0, 0.5 );
991 	gtk_box_pack_start( GTK_BOX( a_hbox ), a_label, TRUE, TRUE, 0 );
992 
993 	img_struct->sub_placing = _gtk_combo_box_new_text( FALSE );
994 	gtk_box_pack_start( GTK_BOX( a_hbox ), img_struct->sub_placing,
995 						FALSE, FALSE, 0 );
996 	{
997 		GtkTreeIter   iter;
998 		GtkListStore *store =
999 				GTK_LIST_STORE( gtk_combo_box_get_model(
1000 						GTK_COMBO_BOX( img_struct->sub_placing ) ) );
1001 
1002 		gtk_list_store_append( store, &iter );
1003 		gtk_list_store_set( store, &iter, 0, _("Exported video"), -1 );
1004 		gtk_list_store_append( store, &iter );
1005 		gtk_list_store_set( store, &iter, 0, _("Original image"), -1 );
1006 	}
1007 	gtk_combo_box_set_active( GTK_COMBO_BOX( img_struct->sub_placing ), 1 );
1008 	g_signal_connect( G_OBJECT( img_struct->sub_placing ), "changed",
1009 					  G_CALLBACK( img_placing_changed ), img_struct );
1010 
1011 	a_hbox = gtk_hbox_new(FALSE, 6);
1012 	gtk_box_pack_start( GTK_BOX( vbox_slide_caption ), a_hbox, FALSE, FALSE, 0 );
1013 
1014 	a_label = gtk_label_new( _("Subtitle position:") );
1015 	gtk_misc_set_alignment( GTK_MISC( a_label ), 0, 0.5 );
1016 	gtk_box_pack_start( GTK_BOX( a_hbox ), a_label, TRUE, TRUE, 0 );
1017 
1018 	img_struct->sub_pos = img_table_button_new();
1019 	gtk_box_pack_start( GTK_BOX( a_hbox ), img_struct->sub_pos,
1020 						FALSE, FALSE, 0 );
1021 	{
1022 		/* Load position icons */
1023 		GdkPixbuf *pixs[9];
1024 		gint       i;
1025 		gchar     *path;
1026 
1027 		/* First code snippet is in use for development version,
1028 		 * while second is intendeded for releases */
1029 #if PLUGINS_INSTALLED
1030 		path = g_strconcat( DATADIR, "/imagination/pixmaps/imagination-pos", NULL );
1031 #else
1032 		path = g_strconcat( "pixmaps/imagination-pos", NULL );
1033 #endif
1034 		for( i = 0; i < 9; i++ )
1035 		{
1036 			gchar *file;
1037 
1038 			file = g_strdup_printf( "%s-%d.png", path, i );
1039 			pixs[i] = gdk_pixbuf_new_from_file( file, NULL );
1040 			g_free( file );
1041 		}
1042 		g_free( path );
1043 
1044 		img_table_button_set_pixbufs( IMG_TABLE_BUTTON( img_struct->sub_pos ),
1045 									  9, pixs );
1046 
1047 		for( i = 0; i < 9; i++ )
1048 			g_object_unref( G_OBJECT( pixs[i] ) );
1049 	}
1050 	img_table_button_set_active_item( IMG_TABLE_BUTTON( img_struct->sub_pos ), 4 );
1051 	g_signal_connect( G_OBJECT( img_struct->sub_pos ), "active-item-changed",
1052 					  G_CALLBACK( img_text_pos_changed ), img_struct );
1053 
1054 	/* Background music frame */
1055 	audio_tab = gtk_label_new (_("Audio"));
1056 	vbox_audio_frames = gtk_vbox_new(FALSE, 0);
1057 	gtk_container_set_border_width(GTK_CONTAINER(vbox_audio_frames), 10);
1058 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_audio_frames, audio_tab);
1059 
1060 	frame3 = gtk_frame_new (NULL);
1061 	gtk_box_pack_start (GTK_BOX (vbox_audio_frames), frame3, TRUE, TRUE, 0);
1062 	gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_OUT);
1063 
1064 	frame3_alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
1065 	gtk_container_add (GTK_CONTAINER (frame3), frame3_alignment);
1066 	gtk_alignment_set_padding (GTK_ALIGNMENT (frame3_alignment), 2, 2, 5, 5);
1067 
1068 	frame_label = gtk_label_new (_("<b>Background Music</b>"));
1069 	gtk_frame_set_label_widget (GTK_FRAME (frame3), frame_label);
1070 	gtk_label_set_use_markup (GTK_LABEL (frame_label), TRUE);
1071 	gtk_misc_set_padding (GTK_MISC (frame_label), 2, 2);
1072 
1073 	/* Add the liststore */
1074 	vbox2 = gtk_vbox_new (FALSE, 5);
1075 	gtk_container_add (GTK_CONTAINER (frame3_alignment), vbox2);
1076 	gtk_container_set_border_width (GTK_CONTAINER (vbox2), 0);
1077 
1078 	scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
1079 	gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow1, TRUE, TRUE, 0);
1080 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1081 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN);
1082 
1083 	img_struct->music_file_liststore = gtk_list_store_new (6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING);
1084 	g_signal_connect (G_OBJECT (img_struct->music_file_liststore), "row-inserted",	G_CALLBACK (img_activate_remove_button_music_liststore) , img_struct);
1085 
1086 	img_struct->music_file_treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(img_struct->music_file_liststore));
1087 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(img_struct->music_file_treeview));
1088 
1089 	gtk_drag_dest_set (GTK_WIDGET(img_struct->music_file_treeview),GTK_DEST_DEFAULT_ALL,drop_targets,1,GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
1090 	g_signal_connect (G_OBJECT (img_struct->music_file_treeview),"drag-data-received",G_CALLBACK (img_on_drag_audio_data_received), img_struct);
1091 
1092 	/* First and last three columns aren't displayed, so we
1093 	 * only need two columns. */
1094 	for (x = 1; x < 3; x++)
1095 	{
1096 		column = gtk_tree_view_column_new();
1097 		renderer = gtk_cell_renderer_text_new();
1098 		gtk_tree_view_column_pack_start(column, renderer, TRUE);
1099 		gtk_tree_view_column_set_attributes(column, renderer, "text", x,
1100 															  "foreground", 4,
1101 															  NULL );
1102 		gtk_tree_view_append_column (GTK_TREE_VIEW (img_struct->music_file_treeview), column);
1103 	}
1104 
1105 	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(img_struct->music_file_treeview), TRUE);
1106 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (img_struct->music_file_treeview), FALSE);
1107 	gtk_tree_view_set_tooltip_column( GTK_TREE_VIEW( img_struct->music_file_treeview ), 5 );
1108 	gtk_container_add (GTK_CONTAINER (scrolledwindow1), img_struct->music_file_treeview);
1109 
1110 	/* Add the total music labels and the buttons */
1111 	hbox_music_label = gtk_hbox_new(FALSE, 2);
1112 	gtk_box_pack_start( GTK_BOX( vbox2 ), hbox_music_label, FALSE, FALSE, 0 );
1113 
1114 	music_time = gtk_label_new(_("Music Duration:"));
1115 	gtk_box_pack_start(GTK_BOX(hbox_music_label), music_time, TRUE, TRUE, 0);
1116 	gtk_misc_set_alignment (GTK_MISC (music_time), 0, 0.5);
1117 
1118 	img_struct->music_time_data = gtk_label_new(NULL);
1119 	gtk_box_pack_start(GTK_BOX(hbox_music_label), img_struct->music_time_data, TRUE, TRUE, 0);
1120 	gtk_misc_set_alignment (GTK_MISC (img_struct->music_time_data), 1, 0.5);
1121 
1122 	hbox_buttons = gtk_hbox_new(TRUE, 2);
1123 	gtk_box_pack_start( GTK_BOX( vbox2 ), hbox_buttons, FALSE, FALSE, 0 );
1124 
1125 	img_struct->play_audio_button = gtk_button_new();
1126 	gtk_widget_set_sensitive(img_struct->play_audio_button, FALSE);
1127 	gtk_box_pack_start(GTK_BOX(hbox_buttons), img_struct->play_audio_button, FALSE, TRUE, 0);
1128 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
1129 	gtk_container_add (GTK_CONTAINER (img_struct->play_audio_button), image_buttons);
1130 	gtk_widget_set_tooltip_text(img_struct->play_audio_button, _("Play the selected file"));
1131 	g_signal_connect ( (gpointer) img_struct->play_audio_button, "clicked", G_CALLBACK (img_play_stop_selected_file), img_struct);
1132 
1133 	img_struct->remove_audio_button = gtk_button_new();
1134 	gtk_widget_set_sensitive(img_struct->remove_audio_button, FALSE);
1135 	gtk_box_pack_start(GTK_BOX(hbox_buttons), img_struct->remove_audio_button, FALSE, TRUE, 0);
1136 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU);
1137 	gtk_container_add (GTK_CONTAINER (img_struct->remove_audio_button), image_buttons);
1138 	gtk_widget_set_tooltip_text(img_struct->remove_audio_button, _("Delete the selected file"));
1139 	g_signal_connect ( (gpointer) img_struct->remove_audio_button, "clicked", G_CALLBACK (img_remove_audio_files), img_struct);
1140 
1141 	move_up_button = gtk_button_new();
1142 	gtk_box_pack_start(GTK_BOX(hbox_buttons), move_up_button, FALSE, TRUE, 0);
1143 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU);
1144 	gtk_container_add (GTK_CONTAINER (move_up_button), image_buttons);
1145 	gtk_widget_set_tooltip_text(move_up_button, _("Move the selected file up"));
1146 	g_signal_connect( G_OBJECT( move_up_button ), "clicked", G_CALLBACK( img_move_audio_up ), img_struct );
1147 
1148 	move_down_button = gtk_button_new();
1149 	gtk_box_pack_start(GTK_BOX(hbox_buttons), move_down_button, FALSE, TRUE, 0);
1150 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU);
1151 	gtk_container_add (GTK_CONTAINER (move_down_button), image_buttons);
1152 	gtk_widget_set_tooltip_text(move_down_button, _("Move the selected file down"));
1153 	g_signal_connect( G_OBJECT( move_down_button ), "clicked", G_CALLBACK( img_move_audio_down ), img_struct );
1154 
1155 	clear_button = gtk_button_new();
1156 	gtk_box_pack_start(GTK_BOX(hbox_buttons), clear_button, FALSE, TRUE, 0);
1157 	image_buttons = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
1158 	gtk_container_add (GTK_CONTAINER (clear_button), image_buttons);
1159 	gtk_widget_set_tooltip_text(clear_button, _("Clear all files"));
1160 	g_signal_connect ( (gpointer) clear_button, "clicked", G_CALLBACK (img_clear_audio_files), img_struct);
1161     /* End of Background music frame */
1162 
1163     /* Begin of Message tab */
1164     img_struct->message_label = gtk_label_new (_("Messages"));
1165     message_scroll = gtk_scrolled_window_new(NULL, NULL);
1166     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(message_scroll),
1167                                    GTK_POLICY_AUTOMATIC,
1168                                    GTK_POLICY_AUTOMATIC);
1169     img_struct->message_page = gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1170                              message_scroll,
1171                              img_struct->message_label);
1172 
1173     message_view = gtk_text_view_new();
1174     gtk_text_view_set_editable(GTK_TEXT_VIEW(message_view), FALSE);
1175     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(message_view), GTK_WRAP_WORD);
1176     gtk_container_add(GTK_CONTAINER(message_scroll), message_view);
1177     img_struct->message_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (message_view));
1178     g_signal_connect( (gpointer) notebook, "switch_page",
1179                       G_CALLBACK (img_notebook_switch_page), img_struct);
1180     /* End of Message tab */
1181 
1182 	/* Create the model */
1183 	img_struct->thumbnail_model = gtk_list_store_new( 4,
1184                                                       GDK_TYPE_PIXBUF,  /* thumbnail */
1185                                                       G_TYPE_POINTER,   /* slide_info */
1186 													  GDK_TYPE_PIXBUF,  /* transition thumbnail */
1187 													  G_TYPE_BOOLEAN ); /* presence of a subtitle */
1188 
1189 	/* Create overview mode widgets */
1190 	/* FIXME: A lot of duplicate code here!! */
1191 	{
1192 		GtkWidget       *icon,
1193 						*swindow;
1194 		GtkCellRenderer *cell;
1195 		gchar           *path;
1196 		GdkPixbuf       *text;
1197 
1198 		swindow = gtk_scrolled_window_new( NULL, NULL );
1199 		gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( swindow ),
1200 										GTK_POLICY_AUTOMATIC,
1201 										GTK_POLICY_AUTOMATIC );
1202 		gtk_box_pack_start( GTK_BOX( modes_vbox ), swindow, TRUE, TRUE, 0 );
1203 		img_struct->over_root = swindow;
1204 
1205 		icon = gtk_icon_view_new_with_model(
1206 					GTK_TREE_MODEL( img_struct->thumbnail_model ) );
1207 		gtk_icon_view_set_selection_mode( GTK_ICON_VIEW( icon ),
1208 										  GTK_SELECTION_MULTIPLE );
1209 		gtk_icon_view_set_orientation( GTK_ICON_VIEW( icon ),
1210 									   GTK_ORIENTATION_HORIZONTAL );
1211 		gtk_icon_view_set_column_spacing( GTK_ICON_VIEW( icon ), 0 );
1212 		gtk_icon_view_set_row_spacing( GTK_ICON_VIEW( icon ), 0 );
1213 		img_struct->over_icon = icon;
1214 		img_struct->active_icon = icon;
1215 		g_signal_connect( G_OBJECT( icon ), "selection-changed",
1216 						  G_CALLBACK( img_iconview_selection_changed ),
1217 						  img_struct );
1218 		g_signal_connect( G_OBJECT( icon ), "select-all",
1219 						  G_CALLBACK( img_iconview_selection_changed ),
1220 						  img_struct );
1221 		g_signal_connect( G_OBJECT( icon ), "button-press-event",
1222 						  G_CALLBACK( img_iconview_selection_button_press ),
1223 						  img_struct );
1224 		gtk_container_add( GTK_CONTAINER( swindow ), icon );
1225 
1226 		cell = img_cell_renderer_pixbuf_new();
1227 		gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( icon ), cell, FALSE );
1228 		img_struct->over_cell = G_OBJECT( cell );
1229 
1230 #if PLUGINS_INSTALLED
1231 		path = g_strconcat( DATADIR,
1232 							"/imagination/pixmaps/imagination-text.png",
1233 							NULL );
1234 #else
1235 		path = g_strdup( "pixmaps/imagination-text.png" );
1236 #endif
1237 		text = gdk_pixbuf_new_from_file( path, NULL );
1238 		g_free( path );
1239 		g_object_set( G_OBJECT( cell ), "ypad", 2,
1240 										"text-ico", text,
1241 										NULL );
1242 		g_object_unref( G_OBJECT( text ) );
1243 		gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT( icon ), cell,
1244 										"pixbuf", 0,
1245 										"transition", 2,
1246 										"has-text", 3,
1247 										NULL );
1248 		gtk_icon_view_set_reorderable( GTK_ICON_VIEW( icon ), TRUE );
1249 	}
1250 
1251 	/* Add wrapper for DnD */
1252 	eventbox = gtk_event_box_new();
1253 	img_struct->thum_root = eventbox;
1254 	gtk_event_box_set_above_child( GTK_EVENT_BOX( eventbox ), FALSE );
1255 	gtk_event_box_set_visible_window( GTK_EVENT_BOX( eventbox ), FALSE );
1256 	gtk_drag_dest_set( GTK_WIDGET( eventbox ), GTK_DEST_DEFAULT_ALL,
1257 					   drop_targets, 1, GDK_ACTION_COPY | GDK_ACTION_MOVE |
1258 					   GDK_ACTION_LINK | GDK_ACTION_ASK);
1259 	g_signal_connect( G_OBJECT( eventbox ), "drag-data-received",
1260 					  G_CALLBACK( img_on_drag_data_received), img_struct );
1261 	gtk_box_pack_start( GTK_BOX( vbox1 ), eventbox, FALSE, TRUE, 0 );
1262 
1263 	/* Create the thumbnail viewer */
1264 	thumb_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
1265 	gtk_widget_set_size_request( thumb_scrolledwindow, -1, 115 );
1266 	g_signal_connect( G_OBJECT( thumb_scrolledwindow ), "scroll-event",
1267 					  G_CALLBACK( img_scroll_thumb ), img_struct );
1268 	gtk_container_add( GTK_CONTAINER( eventbox ), thumb_scrolledwindow );
1269 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (thumb_scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1270 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (thumb_scrolledwindow), GTK_SHADOW_IN);
1271 
1272 	img_struct->thumbnail_iconview = gtk_icon_view_new_with_model(GTK_TREE_MODEL (img_struct->thumbnail_model));
1273 	gtk_container_add( GTK_CONTAINER( thumb_scrolledwindow ), img_struct->thumbnail_iconview );
1274 
1275 	/* Create the cell layout */
1276 	pixbuf_cell = img_cell_renderer_pixbuf_new();
1277 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (img_struct->thumbnail_iconview), pixbuf_cell, FALSE);
1278 	{
1279 		gchar     *path;
1280 		GdkPixbuf *text;
1281 
1282 #if PLUGINS_INSTALLED
1283 		path = g_strconcat( DATADIR,
1284 							"/imagination/pixmaps/imagination-text.png",
1285 							NULL );
1286 #else
1287 		path = g_strdup( "pixmaps/imagination-text.png" );
1288 #endif
1289 		text = gdk_pixbuf_new_from_file( path, NULL );
1290 		g_free( path );
1291 		g_object_set( G_OBJECT( pixbuf_cell ), "width", 115,
1292 											   "ypad", 2,
1293 											   "text-ico", text,
1294 											   NULL );
1295 		g_object_unref( G_OBJECT( text ) );
1296 	}
1297 	gtk_cell_layout_set_attributes(
1298 			GTK_CELL_LAYOUT( img_struct->thumbnail_iconview ), pixbuf_cell,
1299 			"pixbuf", 0,
1300 			"transition", 2,
1301 			"has-text", 3,
1302 			NULL );
1303 
1304 	/* Set some iconview properties */
1305 	gtk_icon_view_set_text_column( GTK_ICON_VIEW( img_struct->thumbnail_iconview ), -1 );
1306 	gtk_icon_view_set_reorderable(GTK_ICON_VIEW (img_struct->thumbnail_iconview),TRUE);
1307 	gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (img_struct->thumbnail_iconview), GTK_SELECTION_MULTIPLE);
1308 	gtk_icon_view_set_orientation (GTK_ICON_VIEW (img_struct->thumbnail_iconview), GTK_ORIENTATION_HORIZONTAL);
1309 	gtk_icon_view_set_column_spacing (GTK_ICON_VIEW (img_struct->thumbnail_iconview),0);
1310 	gtk_icon_view_set_row_spacing (GTK_ICON_VIEW (img_struct->thumbnail_iconview),0);
1311 	gtk_icon_view_set_columns (GTK_ICON_VIEW (img_struct->thumbnail_iconview), G_MAXINT);
1312 	g_signal_connect (G_OBJECT (img_struct->thumbnail_iconview),"selection-changed",G_CALLBACK (img_iconview_selection_changed),img_struct);
1313 	g_signal_connect (G_OBJECT (img_struct->thumbnail_iconview),"select-all",G_CALLBACK (img_iconview_selection_changed),img_struct);
1314 	g_signal_connect (G_OBJECT (img_struct->thumbnail_iconview),"button-press-event",G_CALLBACK (img_iconview_selection_button_press),img_struct);
1315 	gtk_widget_show_all( eventbox );
1316 
1317 	/* Create the status bar */
1318 	img_struct->statusbar = gtk_statusbar_new ();
1319 	gtk_widget_show (img_struct->statusbar);
1320 	gtk_box_pack_start (GTK_BOX (vbox1), img_struct->statusbar, FALSE, TRUE, 0);
1321 	img_struct->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (img_struct->statusbar), "statusbar");
1322 
1323 	/* Create the progress bar */
1324 	img_struct->progress_bar = gtk_progress_bar_new();
1325 	gtk_widget_set_size_request (img_struct->progress_bar, -1, 15);
1326 	{
1327 		GtkWidget *vbox;
1328 
1329 		vbox = gtk_vbox_new (FALSE, 0);
1330 		gtk_box_pack_start (GTK_BOX (img_struct->statusbar), vbox, FALSE, FALSE, 0);
1331 		gtk_box_pack_start (GTK_BOX (vbox), img_struct->progress_bar, TRUE, FALSE, 0);
1332 		gtk_widget_show (vbox);
1333 	}
1334 	gtk_widget_show_all( img_struct->paned );
1335 	gtk_window_add_accel_group (GTK_WINDOW (img_struct->imagination_window), img_struct->accel_group);
1336 
1337 	/* Disable all Ken Burns controls */
1338 	img_ken_burns_update_sensitivity( img_struct, FALSE, 0 );
1339 
1340 	/* Disable all subtitle controls */
1341 	img_subtitle_update_sensitivity( img_struct, 0 );
1342 
1343 	/* Load interface settings or apply default ones */
1344 	if( ! img_load_window_settings( img_struct ) )
1345 		img_set_window_default_settings( img_struct );
1346 
1347 	/* Update preview frame rate */
1348 	{
1349 		gint index =
1350 			( img_struct->preview_fps - PREVIEW_FPS_MIN ) / PREVIEW_FPS_STEP;
1351 		gtk_check_menu_item_set_active(
1352 				GTK_CHECK_MENU_ITEM( tmp_checks[index] ), TRUE );
1353 	}
1354 
1355 	return img_struct;
1356 }
1357 
img_slide_cut(GtkMenuItem * item,img_window_struct * img)1358 static void img_slide_cut(GtkMenuItem* item, img_window_struct *img)
1359 {
1360 	img_clipboard_cut_copy_operation(img, IMG_CLIPBOARD_CUT);
1361 }
1362 
img_slide_copy(GtkMenuItem * item,img_window_struct * img)1363 static void img_slide_copy(GtkMenuItem* item, img_window_struct *img)
1364 {
1365 	img_clipboard_cut_copy_operation(img, IMG_CLIPBOARD_COPY);
1366 }
1367 
img_slide_paste(GtkMenuItem * item,img_window_struct * img)1368 static void img_slide_paste(GtkMenuItem* item, img_window_struct *img)
1369 {
1370 	GtkClipboard *clipboard;
1371 	GtkSelectionData *selection;
1372 	GList *where_to_paste = NULL, *node;
1373 	GtkTreeModel *model;
1374 	GtkTreeIter iter, position_iter;
1375 	gchar *total_slides = NULL;
1376 	GdkPixbuf *thumb, *trans;
1377 	gboolean   has_sub;
1378 	slide_struct *pasted_slide, *info_slide;
1379 	gint pos;
1380     GtkTreeRowReference  *position_rawref;
1381     GList                *rowref_list = NULL;
1382     GtkTreePath          *path, *position_path;
1383 
1384 
1385     clipboard = gtk_clipboard_get(IMG_CLIPBOARD);
1386 	selection = gtk_clipboard_wait_for_contents(clipboard, IMG_INFO_LIST);
1387 
1388 	if (selection == NULL)
1389 	{
1390 		img_message (img, FALSE, "Paste: selection is NULL\n");
1391 		return;
1392 	}
1393 
1394 	model			 =	GTK_TREE_MODEL(img->thumbnail_model);
1395 	where_to_paste	 =	gtk_icon_view_get_selected_items(GTK_ICON_VIEW(img->active_icon));
1396     if (where_to_paste == NULL)     /*no icon selected */
1397         return;
1398     position_rawref  =  gtk_tree_row_reference_new(model, where_to_paste->data);
1399 
1400     /* Build a list selected of icons to move */
1401     node = img->selected_paths;
1402     while (node)
1403     {
1404         rowref_list = g_list_append(rowref_list, gtk_tree_row_reference_new(model, node->data));
1405         node = node->next;
1406     }
1407 
1408 	if (img->clipboard_mode == IMG_CLIPBOARD_CUT)
1409 	{
1410         /* move the icons */
1411 		node = rowref_list;
1412 		while (node)
1413         {
1414             path = gtk_tree_row_reference_get_path(node->data);
1415             if (path)
1416             {
1417                 if (gtk_tree_model_get_iter(model, &iter, path))
1418                 {
1419                     position_path = gtk_tree_row_reference_get_path(position_rawref);
1420                     /* position_path can not be NULL as we only move, without delete */
1421                     assert (position_path != NULL);
1422                     gtk_tree_model_get_iter (model, &position_iter,  position_path);
1423                     gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, &position_iter);
1424                     gtk_tree_path_free(position_path);
1425                 }
1426                 gtk_tree_path_free(path);
1427             }
1428             node = node->next;
1429         }
1430 	}
1431 	else    /* clipboard copy */
1432 	{
1433         node = rowref_list;
1434         while (node)
1435 		{
1436             path = gtk_tree_row_reference_get_path(node->data);
1437             if (path)
1438             {
1439                 if (gtk_tree_model_get_iter(model, &iter, path))
1440                 {
1441                     /* Get slide and some additional data */
1442                     gtk_tree_model_get_iter(model, &iter, path);
1443                     gtk_tree_model_get(model, &iter, 0, &thumb,
1444                                                     1, &info_slide,
1445                                                     2, &trans,
1446                                                     3, &has_sub,
1447                                                     -1);
1448                     if( thumb )
1449                         g_object_unref( G_OBJECT( thumb ) );
1450                     if( trans )
1451                         g_object_unref( G_OBJECT( trans ) );
1452 
1453                     /* Create new slide that is exact copy of rpevious one */
1454                     pasted_slide = g_slice_copy( sizeof( slide_struct ), info_slide );
1455 
1456                     if (pasted_slide)
1457                     {
1458                         /* Fill fields with fresh strings, since g_slice_copy cannot do
1459                         * that for us. */
1460                         pasted_slide->o_filename = g_strdup(info_slide->o_filename);
1461                         pasted_slide->r_filename = g_strdup(info_slide->r_filename);
1462                         pasted_slide->original_filename = g_strdup(info_slide->original_filename);
1463                         pasted_slide->resolution = g_strdup(info_slide->resolution);
1464                         pasted_slide->type = g_strdup(info_slide->type);
1465                         pasted_slide->path = g_strdup(info_slide->path);
1466 
1467                         /* Stop Points also need to copied by hand. */
1468                         if (info_slide->no_points)
1469                         {
1470                             GList *dummy_pnt = info_slide->points;
1471                             ImgStopPoint *point;
1472 
1473                             pasted_slide->points = NULL;
1474                             while (dummy_pnt)
1475                             {
1476                                 point = g_slice_copy( sizeof( ImgStopPoint ),
1477                                                     dummy_pnt->data );
1478                                 pasted_slide->points = g_list_append(pasted_slide->points, point);
1479                                 dummy_pnt = dummy_pnt->next;
1480                             }
1481                         }
1482 
1483                         /* Text should be duplicated if present. Font descripštion
1484                         * should also be copied!! */
1485                         if (info_slide->subtitle)
1486                             pasted_slide->subtitle = g_strdup(info_slide->subtitle);
1487                         pasted_slide->font_desc =
1488                                 pango_font_description_copy( info_slide->font_desc );
1489 
1490                         position_path = gtk_tree_row_reference_get_path(position_rawref);
1491                         /* position_path can not be NULL as we only copy, without delete */
1492                         assert (position_path != NULL);
1493                         pos = gtk_tree_path_get_indices(position_path)[0]+1;
1494                         gtk_tree_path_free(position_path);
1495 
1496                         gtk_list_store_insert_with_values(
1497                                 GTK_LIST_STORE( model ), &iter, pos,
1498                                                         0, thumb,
1499                                                         1, pasted_slide,
1500                                                         2, trans,
1501                                                         3, has_sub,
1502                                                         -1 );
1503                     /* Let's update the total number of slides and the label in toolbar */
1504                     img->slides_nr++;
1505                     }
1506                 }
1507                 gtk_tree_path_free(path);
1508 
1509 		}
1510         node = node->next;
1511 
1512 	}
1513     }
1514 
1515     /* Free rowref_list */
1516     g_list_foreach(rowref_list, (GFunc) gtk_tree_row_reference_free, NULL);
1517     g_list_free(rowref_list);
1518     gtk_tree_row_reference_free(position_rawref);
1519 
1520 	/* Free the GList containing the paths of the selected slides */
1521 	if (img->selected_paths)
1522 	{
1523 		g_list_foreach (img->selected_paths, (GFunc)gtk_tree_path_free, NULL);
1524 		g_list_free (img->selected_paths);
1525 		img->selected_paths = NULL;
1526 	}
1527 	/* Free the GList containing the paths where to paste */
1528 	g_list_foreach (where_to_paste, (GFunc)gtk_tree_path_free, NULL);
1529 	g_list_free (where_to_paste);
1530 
1531 	/* Update display */
1532 	total_slides = g_strdup_printf("%d",img->slides_nr);
1533 	gtk_label_set_text(GTK_LABEL(img->total_slide_number_label),total_slides);
1534 	g_free(total_slides);
1535 
1536 	/* Free the GTK selection structure */
1537 	gtk_selection_data_free (selection);
1538 }
1539 
img_clear_audio_files(GtkButton * button,img_window_struct * img)1540 static void img_clear_audio_files(GtkButton *button, img_window_struct *img)
1541 {
1542 	gtk_list_store_clear(GTK_LIST_STORE(img->music_file_liststore));
1543     img_play_stop_selected_file(NULL, img);
1544 	gtk_widget_set_sensitive(img->play_audio_button, FALSE);
1545 	gtk_widget_set_sensitive(img->remove_audio_button, FALSE);
1546 	gtk_label_set_text(GTK_LABEL(img->music_time_data), "");
1547 }
1548 
img_expand_button_clicked(GtkButton * button,img_window_struct * img)1549 static void img_expand_button_clicked(GtkButton *button, img_window_struct *img)
1550 {
1551 	gint width, height;
1552 
1553 	gtk_widget_get_size_request(img->scrolled_win, &width, &height);
1554 	if (height == 18)
1555 	{
1556 		gtk_widget_set_size_request(img->scrolled_win, -1, 90);
1557 		gtk_widget_set_tooltip_text(img->expand_button, _("Click to shrink the area"));
1558 	}
1559 	else
1560 	{
1561 		gtk_widget_set_size_request(img->scrolled_win, -1, 18);
1562 		gtk_widget_set_tooltip_text(img->expand_button, _("Click to expand the area"));
1563 	}
1564 }
1565 
img_sub_textview_focus_in(GtkWidget * widget,GdkEventFocus * event,img_window_struct * img)1566 static gboolean img_sub_textview_focus_in(GtkWidget *widget, GdkEventFocus *event, img_window_struct *img)
1567 {
1568 	gtk_widget_remove_accelerator (img->remove_menu, img->accel_group, GDK_Delete, 0);
1569 	return FALSE;
1570 }
1571 
1572 
img_sub_textview_focus_out(GtkWidget * widget,GdkEventFocus * event,img_window_struct * img)1573 static gboolean img_sub_textview_focus_out(GtkWidget *widget, GdkEventFocus *event, img_window_struct *img)
1574 {
1575 	gtk_widget_add_accelerator (img->remove_menu,"activate", img->accel_group, GDK_Delete, 0, GTK_ACCEL_VISIBLE);
1576 	return FALSE;
1577 }
1578 
img_on_drag_audio_data_received(GtkWidget * widget,GdkDragContext * context,int x,int y,GtkSelectionData * data,unsigned int info,unsigned int time,img_window_struct * img)1579 static void img_on_drag_audio_data_received (GtkWidget *widget,GdkDragContext *context,int x,int y,GtkSelectionData *data,unsigned int info,unsigned int time, img_window_struct *img)
1580 {
1581 	gchar **audio = NULL;
1582 	gchar *filename,*ttime;
1583 	GtkWidget *dialog;
1584 	gint len = 0;
1585 
1586 	audio = gtk_selection_data_get_uris(data);
1587 	if (audio == NULL)
1588 	{
1589 		dialog = gtk_message_dialog_new(GTK_WINDOW(img->imagination_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Sorry, I could not perform the operation!"));
1590 		gtk_window_set_title(GTK_WINDOW(dialog),"Imagination");
1591 		gtk_dialog_run (GTK_DIALOG (dialog));
1592 		gtk_widget_destroy (GTK_WIDGET (dialog));
1593 		gtk_drag_finish(context,FALSE,FALSE,time);
1594 		return;
1595 	}
1596 	gtk_drag_finish (context,TRUE,FALSE,time);
1597 	while(audio[len])
1598 	{
1599 		filename = g_filename_from_uri (audio[len],NULL,NULL);
1600 		img_add_audio_files(filename,img);
1601 		g_free(filename);
1602 		len++;
1603 	}
1604 	ttime = img_convert_seconds_to_time(img->total_music_secs);
1605 	gtk_label_set_text(GTK_LABEL(img->music_time_data), ttime);
1606 	g_free(ttime);
1607 	g_strfreev (audio);
1608 }
1609 
img_activate_remove_button_music_liststore(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter,img_window_struct * img)1610 static void img_activate_remove_button_music_liststore(GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, img_window_struct *img)
1611 {
1612 	if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(img->music_file_liststore), iter) == TRUE)
1613 	{
1614 		gtk_widget_set_sensitive ( img->remove_audio_button, TRUE);
1615 		gtk_widget_set_sensitive ( img->play_audio_button, TRUE);
1616 	}
1617 }
1618 
img_quit_menu(GtkMenuItem * menuitem,img_window_struct * img)1619 static void img_quit_menu(GtkMenuItem *menuitem, img_window_struct *img)
1620 {
1621 	if( ! img_quit_application( NULL, NULL, img ) )
1622 		gtk_main_quit();
1623 }
1624 
img_iconview_selection_changed(GtkIconView * iconview,img_window_struct * img)1625 void img_iconview_selection_changed(GtkIconView *iconview, img_window_struct *img)
1626 {
1627 	GtkTreeModel *model;
1628 	GtkTreeIter iter;
1629 	GtkTreePath *path = NULL;
1630 	gint dummy, nr_selected = 0;
1631 	GList *selected = NULL;
1632 	gchar *slide_info_msg = NULL, *selected_slide_nr = NULL;
1633 	slide_struct *info_slide;
1634 
1635 	if (img->preview_is_running || img->export_is_running)
1636 		return;
1637 
1638 	model = gtk_icon_view_get_model(iconview);
1639 	gtk_icon_view_get_cursor(iconview,&path,NULL);
1640 
1641 	selected = gtk_icon_view_get_selected_items(iconview);
1642 	nr_selected = g_list_length(selected);
1643 	img_set_total_slideshow_duration(img);
1644 
1645 	if (selected == NULL)
1646 	{
1647 		img_set_statusbar_message(img,nr_selected);
1648 		if( img->current_image )
1649 		{
1650 			cairo_surface_destroy( img->current_image );
1651 			img->current_image = NULL;
1652 		}
1653 		img->current_slide = NULL;
1654 		gtk_widget_queue_draw( img->image_area );
1655 
1656 		/* Disable slide settings */
1657         img_disable_videotab(img);
1658 
1659 		if (img->slides_nr == 0)
1660 			gtk_label_set_text(GTK_LABEL (img->total_time_data),"");
1661 
1662 		return;
1663 	}
1664 
1665 	gtk_widget_set_sensitive(img->trans_duration,	TRUE);
1666 	gtk_widget_set_sensitive(img->duration,			TRUE);
1667 	gtk_widget_set_sensitive(img->transition_type,	TRUE);
1668 	gtk_widget_set_sensitive(img->random_button,	TRUE);
1669 
1670 	dummy = gtk_tree_path_get_indices(selected->data)[0]+1;
1671 	selected_slide_nr = g_strdup_printf("%d",dummy);
1672 	gtk_entry_set_text(GTK_ENTRY(img->slide_number_entry),selected_slide_nr);
1673 	g_free(selected_slide_nr);
1674 
1675 	gtk_tree_model_get_iter(model,&iter,selected->data);
1676 	g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
1677 	g_list_free (selected);
1678 	gtk_tree_model_get(model,&iter,1,&info_slide,-1);
1679 	img->current_slide = info_slide;
1680 
1681 	/* Set the transition type */
1682 	model = gtk_combo_box_get_model(GTK_COMBO_BOX(img->transition_type));
1683 
1684 	/* Block "changed" signal from model to avoid rewriting the same value back into current slide. */
1685 	g_signal_handlers_block_by_func((gpointer)img->transition_type, (gpointer)img_combo_box_transition_type_changed, img);
1686 	{
1687 		GtkTreeIter   iter;
1688 		GtkTreeModel *model;
1689 
1690 		model = gtk_combo_box_get_model( GTK_COMBO_BOX( img->transition_type ) );
1691 		gtk_tree_model_get_iter_from_string( model, &iter, info_slide->path );
1692 		gtk_combo_box_set_active_iter(GTK_COMBO_BOX(img->transition_type), &iter );
1693 	}
1694 	g_signal_handlers_unblock_by_func((gpointer)img->transition_type, (gpointer)img_combo_box_transition_type_changed, img);
1695 
1696 	/* Moved this piece of code below the setting the transition, since we
1697 	 * get false negatives in certain situations (eg.: if the previously
1698 	 * selected transition doesn't have transition renderer set): */
1699 	if (gtk_combo_box_get_active(GTK_COMBO_BOX(img->transition_type)) == 0)
1700 		gtk_widget_set_sensitive(img->trans_duration,FALSE);
1701 	else
1702 		gtk_widget_set_sensitive(img->trans_duration,TRUE);
1703 
1704 	/* Set the transition speed */
1705 	if (info_slide->speed == FAST)
1706 		dummy = 0;
1707 	else if (info_slide->speed == NORMAL)
1708 		dummy = 1;
1709 	else
1710 		dummy = 2;
1711 	g_signal_handlers_block_by_func((gpointer)img->duration, (gpointer)img_combo_box_speed_changed, img);
1712 	gtk_combo_box_set_active(GTK_COMBO_BOX(img->trans_duration),dummy);
1713 	g_signal_handlers_block_by_func((gpointer)img->duration, (gpointer)img_combo_box_speed_changed, img);
1714 
1715 	/* Set the transition duration */
1716 	g_signal_handlers_block_by_func((gpointer)img->duration, (gpointer)img_spinbutton_value_changed, img);
1717 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(img->duration), info_slide->duration);
1718 	g_signal_handlers_unblock_by_func((gpointer)img->duration, (gpointer)img_spinbutton_value_changed, img);
1719 
1720 	/* Update Ken Burns display */
1721 	img_update_stop_display( img, TRUE );
1722 
1723 	/* Update subtitle widgets */
1724 	img_update_subtitles_widgets( img );
1725 
1726 	img->project_is_modified = TRUE;
1727 
1728 	if (nr_selected > 1)
1729 	{
1730 		img_set_statusbar_message(img,nr_selected);
1731 		img_ken_burns_update_sensitivity( img, FALSE, 0 );
1732 		img_subtitle_update_sensitivity( img, 2 );
1733 	}
1734 	else
1735 	{
1736 		if (FALSE == info_slide->load_ok)
1737         {
1738             slide_info_msg = g_strdup_printf(_("File '%s' not found"), info_slide->original_filename);
1739             gtk_statusbar_push(GTK_STATUSBAR (img->statusbar), img->context_id, slide_info_msg);
1740             g_free (slide_info_msg);
1741             img_disable_videotab(img);
1742         }
1743         else
1744         {
1745             if (info_slide->o_filename != NULL)
1746             {
1747                 slide_info_msg = g_strdup_printf("%s    %s: %s    %s: %s",info_slide->o_filename, _("Resolution"), info_slide->resolution, _("Type"), info_slide->type);
1748                 gtk_statusbar_push(GTK_STATUSBAR (img->statusbar), img->context_id, slide_info_msg);
1749                 g_free(slide_info_msg);
1750             }
1751             img_ken_burns_update_sensitivity( img, TRUE, info_slide->no_points );
1752             img_subtitle_update_sensitivity( img, 1 );
1753         }
1754 	}
1755 
1756 	if( img->current_image )
1757 	{
1758 		cairo_surface_destroy( img->current_image );
1759 		img->current_image = NULL;
1760 	}
1761 
1762 	/* This is not needed when in overview mode, since we're not displaying any
1763 	 * large image preview. */
1764 	if( img->mode == 0 )
1765 	{
1766 		if( ! info_slide->r_filename )
1767 		{
1768 			img_scale_gradient( info_slide->gradient,
1769 								info_slide->g_start_point,
1770 								info_slide->g_stop_point,
1771 								info_slide->g_start_color,
1772 								info_slide->g_stop_color,
1773 								img->video_size[0],
1774 								img->video_size[1], NULL,
1775 								&img->current_image );
1776 		}
1777 		/* Respect quality settings */
1778 		else if( img->low_quality )
1779 			img_scale_image( info_slide->r_filename,
1780 							 (gdouble)img->video_size[0] / img->video_size[1],
1781 							 0, img->video_size[1], img->distort_images,
1782 							 img->background_color, NULL, &img->current_image );
1783 		else
1784 			img_scale_image( info_slide->r_filename,
1785 							 (gdouble)img->video_size[0] / img->video_size[1],
1786 							 0, 0, img->distort_images,
1787 							 img->background_color, NULL, &img->current_image );
1788 	}
1789 }
1790 
img_combo_box_transition_type_changed(GtkComboBox * combo,img_window_struct * img)1791 static void img_combo_box_transition_type_changed (GtkComboBox *combo, img_window_struct *img)
1792 {
1793 	GList        *selected,
1794 				 *bak;
1795 	GtkTreeIter   iter;
1796 	GtkTreeModel *model;
1797 	gpointer      address;
1798 	slide_struct *info_slide;
1799 	gint          transition_id;
1800 	GtkTreePath  *p;
1801 	gchar        *path;
1802 	GdkPixbuf    *pix;
1803 
1804 	/* Check if anything is selected and return if nothing is */
1805 	selected = gtk_icon_view_get_selected_items(
1806 					GTK_ICON_VIEW( img->active_icon ) );
1807 	if( selected == NULL )
1808 		return;
1809 
1810 	/* Get information about selected transition */
1811 	model = gtk_combo_box_get_model( combo );
1812 	gtk_combo_box_get_active_iter( combo, &iter );
1813 	gtk_tree_model_get( model, &iter, 0, &pix,
1814 									  2, &address,
1815 									  3, &transition_id,
1816 									  -1 );
1817 
1818 	/* If user applied None transition, make duration combo insensitive */
1819 	if( transition_id == -1 )
1820 		gtk_widget_set_sensitive( img->trans_duration, FALSE );
1821 	else
1822 		gtk_widget_set_sensitive( img->trans_duration, TRUE );
1823 
1824 	/* Get string representation of the path, which will be
1825 	 * saved inside slide */
1826 	p = gtk_tree_model_get_path( model, &iter );
1827 	path = gtk_tree_path_to_string( p );
1828 	gtk_tree_path_free( p );
1829 
1830 	/* Update all selected slides */
1831 	model = GTK_TREE_MODEL( img->thumbnail_model );
1832 	bak = selected;
1833 	while (selected)
1834 	{
1835 		gtk_tree_model_get_iter( model, &iter, selected->data );
1836 		gtk_tree_model_get( model, &iter, 1, &info_slide, -1 );
1837 		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, 2, pix, -1 );
1838 		info_slide->render = (ImgRender)address;
1839 		info_slide->transition_id = transition_id;
1840 		g_free( info_slide->path );
1841 		info_slide->path = g_strdup( path );
1842 
1843 		/* If this is first slide, we need to copy transition
1844 		 * to the last pseudo-slide too. */
1845 		if( gtk_tree_path_get_indices( selected->data )[0] == 0 )
1846 			img->final_transition.render = (ImgRender)address;
1847 
1848 		selected = selected->next;
1849 	}
1850 	g_free( path );
1851 	if( pix )
1852 		g_object_unref( G_OBJECT( pix ) );
1853 	img->project_is_modified = TRUE;
1854 	img_report_slides_transitions( img );
1855 	img_set_total_slideshow_duration( img );
1856 	g_list_foreach( bak, (GFunc)gtk_tree_path_free, NULL );
1857 	g_list_free( bak );
1858 }
1859 
img_random_button_clicked(GtkButton * button,img_window_struct * img)1860 static void img_random_button_clicked(GtkButton *button, img_window_struct *img)
1861 {
1862 	GList        *selected,
1863 				 *bak;
1864 	GtkTreeIter   iter;
1865 	GtkTreeModel *model;
1866 	slide_struct *info_slide;
1867 	GdkPixbuf    *pixbuf;
1868 
1869 	model = GTK_TREE_MODEL( img->thumbnail_model );
1870 	selected = gtk_icon_view_get_selected_items(GTK_ICON_VIEW (img->active_icon));
1871 	if (selected == NULL)
1872 		return;
1873 
1874 	/* Avoiding GList memory leak. */
1875 	bak = selected;
1876 	while (selected)
1877 	{
1878 		gtk_tree_model_get_iter(model, &iter,selected->data);
1879 		gtk_tree_model_get(model, &iter,1,&info_slide,-1);
1880 		pixbuf = img_set_random_transition(img, info_slide);
1881 		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, 2, pixbuf, -1 );
1882 		if( pixbuf )
1883 			g_object_unref( G_OBJECT( pixbuf ) );
1884 
1885 		/* If this is first slide, copy transition to last
1886 		 * pseudo-slide */
1887 		if( gtk_tree_path_get_indices( selected->data )[0] == 0 )
1888 			img->final_transition.render = info_slide->render;
1889 
1890 		selected = selected->next;
1891 	}
1892 	img->project_is_modified = TRUE;
1893 	g_list_foreach (bak, (GFunc)gtk_tree_path_free, NULL);
1894 	g_list_free(bak);
1895 
1896 	/* This fixes enable/disable issue */
1897 	img_iconview_selection_changed(GTK_ICON_VIEW(img->active_icon), img );
1898 }
1899 
1900 static GdkPixbuf *
img_set_random_transition(img_window_struct * img,slide_struct * info_slide)1901 img_set_random_transition( img_window_struct *img,
1902 						   slide_struct      *info_slide )
1903 {
1904 	gint          nr;
1905 	gint          r1, r2;
1906 	gpointer      address;
1907 	gint          transition_id;
1908 	GtkTreeModel *model;
1909 	GtkTreeIter   iter;
1910 	gchar         path[10];
1911 	GdkPixbuf    *pix;
1912 
1913 	/* Get tree store that holds transitions */
1914 	model = gtk_combo_box_get_model( GTK_COMBO_BOX( img->transition_type ) );
1915 
1916 	/* Get number of top-levels (categories) and select one */
1917 	nr = gtk_tree_model_iter_n_children( model, NULL );
1918 
1919 	/* Fix crash if no modules are loaded */
1920 	if( nr < 2 )
1921 		return( NULL );
1922 
1923 	r1 = g_random_int_range( 1, nr );
1924 	g_snprintf( path, sizeof( path ), "%d", r1 );
1925 	gtk_tree_model_get_iter_from_string( model, &iter, path );
1926 
1927 	/* Get number of transitions in selected category and select one */
1928 	nr = gtk_tree_model_iter_n_children( model, &iter );
1929 	r2 = g_random_int_range( 0, nr );
1930 	g_snprintf( path, sizeof( path ), "%d:%d", r1, r2 );
1931 	gtk_tree_model_get_iter_from_string( model, &iter, path );
1932 
1933 	gtk_tree_model_get( model, &iter, 0, &pix, 2, &address, 3, &transition_id, -1 );
1934 	info_slide->transition_id = transition_id;
1935 	info_slide->render = (ImgRender)address;
1936 
1937 	/* Prevent leak here */
1938 	if( info_slide->path )
1939 		g_free( info_slide->path );
1940 	info_slide->path = g_strdup( path );
1941 
1942 	/* Select proper iter in transition model */
1943 	g_signal_handlers_block_by_func((gpointer)img->transition_type, (gpointer)img_combo_box_transition_type_changed, img);
1944 	gtk_combo_box_set_active_iter(GTK_COMBO_BOX(img->transition_type), &iter);
1945 	/* Update the slide dialog report in real time */
1946 	img_report_slides_transitions(img);
1947 	g_signal_handlers_unblock_by_func((gpointer)img->transition_type, (gpointer)img_combo_box_transition_type_changed, img);
1948 
1949 	return( pix );
1950 }
1951 
img_combo_box_speed_changed(GtkComboBox * combo,img_window_struct * img)1952 static void img_combo_box_speed_changed (GtkComboBox *combo, img_window_struct *img)
1953 {
1954 	gint speed;
1955 	gdouble duration;
1956 	GList *selected, *bak;
1957 	GtkTreeIter iter;
1958 	GtkTreeModel *model;
1959 	slide_struct *info_slide;
1960 
1961 	model = GTK_TREE_MODEL( img->thumbnail_model );
1962 	selected = gtk_icon_view_get_selected_items(GTK_ICON_VIEW (img->active_icon));
1963 	if (selected == NULL)
1964 		return;
1965 
1966 	speed = gtk_combo_box_get_active(combo);
1967 
1968 	if (speed == 0)
1969 		duration = FAST;
1970 	else if (speed == 1)
1971 		duration = NORMAL;
1972 	else
1973 		duration = SLOW;
1974 
1975 	/* Avoid memory leak */
1976 	bak = selected;
1977 	while (selected)
1978 	{
1979 		gtk_tree_model_get_iter(model, &iter,selected->data);
1980 		gtk_tree_model_get(model, &iter,1,&info_slide,-1);
1981 		info_slide->speed = duration;
1982 
1983 		/* If we're modifying fisr slide, we need to modify
1984 		 * last pseudo-slide too. */
1985 		if( gtk_tree_path_get_indices( selected->data )[0] == 0 )
1986 			img->final_transition.speed = duration;
1987 
1988 		selected = selected->next;
1989 	}
1990 	img_set_total_slideshow_duration(img);
1991 
1992 	g_list_foreach (bak, (GFunc)gtk_tree_path_free, NULL);
1993 	g_list_free(bak);
1994 }
1995 
img_spinbutton_value_changed(GtkSpinButton * spinbutton,img_window_struct * img)1996 static void img_spinbutton_value_changed (GtkSpinButton *spinbutton, img_window_struct *img)
1997 {
1998 	gint duration = 0;
1999 	GList *selected, *bak;
2000 	GtkTreeIter iter;
2001 	GtkTreeModel *model;
2002 	slide_struct *info_slide;
2003 
2004 	model = GTK_TREE_MODEL( img->thumbnail_model );
2005 	selected = gtk_icon_view_get_selected_items(GTK_ICON_VIEW(img->active_icon));
2006 	if (selected == NULL)
2007 		return;
2008 
2009 	duration = gtk_spin_button_get_value_as_int(spinbutton);
2010 
2011 	bak = selected;
2012 	while (selected)
2013 	{
2014 		gtk_tree_model_get_iter(model, &iter,selected->data);
2015 		gtk_tree_model_get(model, &iter,1,&info_slide,-1);
2016 		img_set_slide_still_info( info_slide, duration, img );
2017 		selected = selected->next;
2018 	}
2019 
2020 	g_list_foreach (bak, (GFunc)gtk_tree_path_free, NULL);
2021 	g_list_free(bak);
2022 
2023 	/* Sync timings */
2024 	img_sync_timings( img->current_slide, img );
2025 }
2026 
img_select_all_thumbnails(GtkMenuItem * item,img_window_struct * img)2027 static void img_select_all_thumbnails(GtkMenuItem *item, img_window_struct *img)
2028 {
2029 	gtk_icon_view_select_all(GTK_ICON_VIEW (img->active_icon));
2030 }
2031 
img_unselect_all_thumbnails(GtkMenuItem * item,img_window_struct * img)2032 static void img_unselect_all_thumbnails(GtkMenuItem *item, img_window_struct *img)
2033 {
2034 	gtk_icon_view_unselect_all(GTK_ICON_VIEW (img->active_icon));
2035 }
2036 
img_goto_line_entry_activate(GtkWidget * entry,img_window_struct * img)2037 static void img_goto_line_entry_activate(GtkWidget *entry, img_window_struct *img)
2038 {
2039 	gint slide;
2040 	GtkTreePath *path;
2041 
2042 	slide = strtol(gtk_entry_get_text(GTK_ENTRY(img->slide_number_entry)), NULL, 10);
2043 	if (slide > 0 && slide <= img->slides_nr)
2044 	{
2045 		gtk_icon_view_unselect_all(GTK_ICON_VIEW (img->active_icon));
2046 		path = gtk_tree_path_new_from_indices(slide-1,-1);
2047 		gtk_icon_view_set_cursor (GTK_ICON_VIEW (img->active_icon), path, NULL, FALSE);
2048 		gtk_icon_view_select_path (GTK_ICON_VIEW (img->active_icon), path);
2049 		gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (img->active_icon), path, FALSE, 0, 0);
2050 		gtk_tree_path_free (path);
2051 	}
2052 }
2053 
img_sort_none_before_other(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer data)2054 static gint img_sort_none_before_other(GtkTreeModel *model,GtkTreeIter *a,GtkTreeIter *b,gpointer data)
2055 {
2056 	gchar *name1, *name2;
2057 	gint i;
2058 
2059 	gtk_tree_model_get(model, a, 1, &name1, -1);
2060 	gtk_tree_model_get(model, b, 1, &name2, -1);
2061 
2062 	if (strcmp(name1,_("None")) == 0)
2063 		i = -1;
2064 	else if (strcmp(name2,_("None")) == 0)
2065 		i = 1;
2066 	else
2067 		i = (g_strcmp0 (name1,name2));
2068 
2069 	g_free(name1);
2070 	g_free(name2);
2071 	return i;
2072 }
2073 
img_check_numeric_entry(GtkEditable * entry,gchar * text,gint lenght,gint * position,gpointer data)2074 static void img_check_numeric_entry (GtkEditable *entry, gchar *text, gint lenght, gint *position, gpointer data)
2075 {
2076 	if(*text < '0' || *text > '9')
2077 		g_signal_stop_emission_by_name( (gpointer)entry, "insert-text" );
2078 }
2079 
2080 /*
2081  * img_iconview_selection_button_press:
2082  *
2083  * This is a temporary hack that should do the job of unselecting slides if
2084  * single slide should be selected after select all.
2085  */
2086 static gboolean
img_iconview_selection_button_press(GtkWidget * widget,GdkEventButton * button,img_window_struct * img)2087 img_iconview_selection_button_press( GtkWidget         *widget,
2088 									 GdkEventButton    *button,
2089 									 img_window_struct *img )
2090 {
2091 	if( ( button->button == 1 ) &&
2092 		! ( button->state & ( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) )
2093 		gtk_icon_view_unselect_all( GTK_ICON_VIEW( widget ) );
2094 
2095 	return( FALSE );
2096 }
2097 
2098 static gboolean
img_scroll_thumb(GtkWidget * widget,GdkEventScroll * scroll,img_window_struct * img)2099 img_scroll_thumb( GtkWidget         *widget,
2100 				  GdkEventScroll    *scroll,
2101 				  img_window_struct *img )
2102 {
2103 	GtkAdjustment *adj;
2104 	gdouble        page, step, upper, value;
2105 	gint           dir = 1;
2106 
2107 	if( scroll->direction == GDK_SCROLL_UP ||
2108 		scroll->direction == GDK_SCROLL_LEFT )
2109 	{
2110 		dir = - 1;
2111 	}
2112 
2113 	adj = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW( widget ) );
2114 
2115 	page  = gtk_adjustment_get_page_size( adj );
2116 	step  = gtk_adjustment_get_step_increment( adj );
2117 	upper = gtk_adjustment_get_upper( adj );
2118 	value = gtk_adjustment_get_value( adj );
2119 
2120 	gtk_adjustment_set_value( adj, CLAMP( value + step * dir, 0, upper - page ) );
2121 	return( TRUE );
2122 }
2123 
img_show_uri(GtkMenuItem * menuitem,img_window_struct * img)2124 static void img_show_uri(GtkMenuItem *menuitem, img_window_struct *img)
2125 {
2126 	gchar *file = NULL;
2127 	gchar *lang = NULL;
2128 
2129 	lang = g_strndup(g_getenv("LANG"),2);
2130 	file = g_strconcat("file://",DATADIR,"/doc/",PACKAGE,"/html/",lang,"/index.html",NULL);
2131 	g_free(lang);
2132 	img_message (img, FALSE, "%s\n", file);
2133 
2134 	/* If help is not localized yet, show default language (english) */
2135 	if ( !gtk_show_uri(NULL,file, GDK_CURRENT_TIME, NULL))
2136 	{
2137 		g_free( file );
2138 		file = g_strconcat("file://",DATADIR,"/doc/",PACKAGE,"/html/en/index.html",NULL);
2139 		gtk_show_uri(NULL,file, GDK_CURRENT_TIME, NULL);
2140 	}
2141 	g_free(file);
2142 }
2143 
2144 void
img_queue_subtitle_update(GtkTextBuffer * buffer,img_window_struct * img)2145 img_queue_subtitle_update( GtkTextBuffer     *buffer,
2146 						   img_window_struct *img )
2147 {
2148 	/* This queue enables us to avid sensless copying and redrawing when typing
2149 	 * relatively fast (limit is cca. 3 keypresses per second) */
2150 	if( img->subtitle_update_id )
2151 		g_source_remove( img->subtitle_update_id );
2152 
2153 	img->subtitle_update_id =
2154 			g_timeout_add( 300, (GSourceFunc)img_subtitle_update, img );
2155 }
2156 
2157 static GtkWidget *
img_create_subtitle_animation_combo(void)2158 img_create_subtitle_animation_combo( void )
2159 {
2160 	GtkWidget       *combo;
2161 	GtkListStore    *store;
2162 	TextAnimation   *animations;
2163 	gint             no_anims;
2164 	register gint    i;
2165 	GtkTreeIter      iter;
2166 	GtkCellRenderer *cell;
2167 
2168 	store = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT );
2169 
2170 	no_anims = img_get_text_animation_list( &animations );
2171 	for( i = 0; i < no_anims; i++ )
2172 	{
2173 		gtk_list_store_append( store, &iter );
2174 		gtk_list_store_set( store, &iter, 0, animations[i].name,
2175 										  1, animations[i].func,
2176 										  2, animations[i].id,
2177 										  -1 );
2178 	}
2179 	img_free_text_animation_list( no_anims, animations );
2180 
2181 	combo = gtk_combo_box_new_with_model( GTK_TREE_MODEL( store ) );
2182 	g_object_unref( G_OBJECT( store ) );
2183 
2184 	cell = gtk_cell_renderer_text_new();
2185 	gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell, TRUE );
2186 	gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell, "text", 0 );
2187 
2188 	return( combo );
2189 }
2190 
2191 static gboolean
img_subtitle_update(img_window_struct * img)2192 img_subtitle_update( img_window_struct *img )
2193 {
2194 	gboolean     has_subtitle;
2195 	GtkTreeIter  iter;
2196 	GList       *list;
2197 
2198 
2199 	/* Get text from buffer and store it inside slide */
2200 	if( img->current_slide->subtitle )
2201 	{
2202 		g_free( img->current_slide->subtitle );
2203 		img->current_slide->subtitle = NULL;
2204 	}
2205 
2206 	has_subtitle =
2207 			1 < gtk_text_buffer_get_char_count( img->slide_text_buffer );
2208 	if( has_subtitle )
2209 		g_object_get( G_OBJECT( img->slide_text_buffer ), "text",
2210 					  &img->current_slide->subtitle, NULL );
2211 
2212 	list = gtk_icon_view_get_selected_items(
2213 				GTK_ICON_VIEW( img->active_icon ) );
2214 	gtk_tree_model_get_iter( GTK_TREE_MODEL( img->thumbnail_model ),
2215 							 &iter, list->data );
2216 	g_list_foreach( list, (GFunc)gtk_tree_path_free, NULL );
2217 	g_list_free( list );
2218 	gtk_list_store_set( GTK_LIST_STORE( img->thumbnail_model ), &iter,
2219 						3, has_subtitle, -1 );
2220 
2221 	/* Queue redraw */
2222 	gtk_widget_queue_draw( img->image_area );
2223 
2224 	/* Set source id to zero and remove itself from main context */
2225 	img->subtitle_update_id = 0;
2226 
2227 	return( FALSE );
2228 }
2229 
2230 void
img_text_font_set(GtkFontButton * button,img_window_struct * img)2231 img_text_font_set( GtkFontButton     *button,
2232 				   img_window_struct *img )
2233 {
2234 	const gchar *string;
2235 
2236 	string = gtk_font_button_get_font_name( button );
2237 
2238 	img_update_sub_properties( img, NULL, -1, -1, -1, -1, string, NULL, NULL );
2239 
2240 	gtk_widget_queue_draw( img->image_area );
2241 }
2242 
2243 void
img_text_anim_set(GtkComboBox * combo,img_window_struct * img)2244 img_text_anim_set( GtkComboBox       *combo,
2245 				   img_window_struct *img )
2246 {
2247 	GtkTreeModel      *model;
2248 	GtkTreeIter        iter;
2249 	TextAnimationFunc  anim;
2250 	gint               anim_id;
2251 
2252 	model = gtk_combo_box_get_model( combo );
2253 	gtk_combo_box_get_active_iter( combo, &iter );
2254 	gtk_tree_model_get( model, &iter, 1, &anim, 2, &anim_id, -1 );
2255 
2256 	img_update_sub_properties( img, anim, anim_id, -1, -1, -1, NULL, NULL, NULL);
2257 
2258 	/* Speed should be disabled when None is in effect */
2259 	gtk_widget_set_sensitive( img->sub_anim_duration,
2260 							  (gboolean)gtk_combo_box_get_active( combo ) );
2261 
2262 	gtk_widget_queue_draw( img->image_area );
2263 }
2264 
2265 void
img_font_color_changed(GtkColorButton * button,img_window_struct * img)2266 img_font_color_changed( GtkColorButton    *button,
2267 						img_window_struct *img )
2268 {
2269 	GdkColor color;
2270 	guint16  alpha;
2271 	gdouble  font_color[4];
2272 
2273 	gtk_color_button_get_color( button, &color );
2274 	alpha = gtk_color_button_get_alpha( button  );
2275 
2276 	font_color[0] = (gdouble)color.red   / 0xffff;
2277 	font_color[1] = (gdouble)color.green / 0xffff;
2278 	font_color[2] = (gdouble)color.blue  / 0xffff;
2279 	font_color[3] = (gdouble)alpha       / 0xffff;
2280 
2281 	img_update_sub_properties( img, NULL, -1, -1, -1, -1, NULL, font_color, NULL );
2282 
2283 	gtk_widget_queue_draw( img->image_area );
2284 }
2285 
2286 void
img_font_bgcolor_changed(GtkColorButton * button,img_window_struct * img)2287 img_font_bgcolor_changed( GtkColorButton    *button,
2288                           img_window_struct *img )
2289 {
2290     GdkColor color;
2291     guint16  alpha;
2292     gdouble  font_bgcolor[4];
2293 
2294     gtk_color_button_get_color( button, &color );
2295     alpha = gtk_color_button_get_alpha( button  );
2296 
2297     font_bgcolor[0] = (gdouble)color.red   / 0xffff;
2298     font_bgcolor[1] = (gdouble)color.green / 0xffff;
2299     font_bgcolor[2] = (gdouble)color.blue  / 0xffff;
2300     font_bgcolor[3] = (gdouble)alpha       / 0xffff;
2301 
2302     img_update_sub_properties( img, NULL, -1, -1, -1, -1, NULL, NULL, font_bgcolor);
2303 
2304     gtk_widget_queue_draw( img->image_area );
2305 }
2306 
2307 void
img_combo_box_anim_speed_changed(GtkSpinButton * spinbutton,img_window_struct * img)2308 img_combo_box_anim_speed_changed( GtkSpinButton       *spinbutton,
2309 								  img_window_struct *img )
2310 {
2311 	gint speed;
2312 
2313 	speed = gtk_spin_button_get_value_as_int(spinbutton);
2314 	img_update_sub_properties( img, NULL, -1, speed, -1, -1, NULL, NULL, NULL);
2315 }
2316 
2317 void
img_text_pos_changed(ImgTableButton * button,gint item,img_window_struct * img)2318 img_text_pos_changed( ImgTableButton    *button,
2319 					  gint               item,
2320 					  img_window_struct *img )
2321 {
2322 	/* NOTE: This can be done because we know how items are packed into table
2323 	 * button. For safety measures and future expandability, this should be
2324 	 * converted into switch statement. */
2325 	img_update_sub_properties( img, NULL, -1, -1, item, -1, NULL, NULL, NULL);
2326 
2327 	gtk_widget_queue_draw( img->image_area );
2328 }
2329 
2330 void
img_placing_changed(GtkComboBox * combo,img_window_struct * img)2331 img_placing_changed( GtkComboBox   *combo,
2332 					 img_window_struct *img )
2333 {
2334 	ImgRelPlacing placing;
2335 
2336 	if( gtk_combo_box_get_active(combo) == 0 )
2337 		placing = IMG_REL_PLACING_EXPORTED_VIDEO;
2338 	else
2339 		placing = IMG_REL_PLACING_ORIGINAL_IMAGE;
2340 
2341 	img_update_sub_properties( img, NULL, -1, -1, -1, placing, NULL, NULL, NULL);
2342 
2343 	gtk_widget_queue_draw( img->image_area );
2344 }
2345 
2346 void
img_disable_videotab(img_window_struct * img)2347 img_disable_videotab (img_window_struct *img)
2348 {
2349     gtk_widget_set_sensitive(img->random_button, FALSE);
2350     gtk_widget_set_sensitive(img->transition_type, FALSE);
2351     gtk_widget_set_sensitive(img->duration, FALSE);
2352     gtk_widget_set_sensitive(img->trans_duration,   FALSE);
2353 
2354     img_ken_burns_update_sensitivity (img, FALSE, 0);
2355     img_subtitle_update_sensitivity (img, 0);
2356 }
2357 
2358 
2359 void
img_ken_burns_update_sensitivity(img_window_struct * img,gboolean slide_selected,gint no_points)2360 img_ken_burns_update_sensitivity( img_window_struct *img,
2361 								  gboolean           slide_selected,
2362 								  gint               no_points )
2363 {
2364 	/* Modes of operation:
2365 	 *   3 - disable all
2366 	 *   2 - enable duration, zoom and add
2367 	 *   1 - disable only navigation
2368 	 *   0 - enable all
2369 	 */
2370 	gint mode = 3;
2371 
2372 	if( slide_selected )
2373 	{
2374 		switch( no_points )
2375 		{
2376 			case 0:
2377 				mode = 2;
2378 				break;
2379 
2380 			case 1:
2381 				mode = 1;
2382 				break;
2383 
2384 			default:
2385 				mode = 0;
2386 				break;
2387 		}
2388 	}
2389 
2390 	/* Disable all - this is starting state */
2391 	gtk_widget_set_sensitive( img->ken_left,     FALSE );
2392 	gtk_widget_set_sensitive( img->ken_entry,    FALSE );
2393 	gtk_widget_set_sensitive( img->ken_right,    FALSE );
2394 	gtk_widget_set_sensitive( img->ken_duration, FALSE );
2395 	gtk_widget_set_sensitive( img->ken_zoom,     FALSE );
2396 	gtk_widget_set_sensitive( img->ken_add,      FALSE );
2397 	gtk_widget_set_sensitive( img->ken_update,   FALSE );
2398 	gtk_widget_set_sensitive( img->ken_remove,   FALSE );
2399 
2400 	/* Enabler */
2401 	switch( mode ) /* THIS SWITCH IS IN FALL-THROUGH MODE!! */
2402 	{
2403 		case 0: /* Enable all */
2404 			gtk_widget_set_sensitive( img->ken_left,     TRUE );
2405 			gtk_widget_set_sensitive( img->ken_entry,    TRUE );
2406 			gtk_widget_set_sensitive( img->ken_right,    TRUE );
2407 
2408 		case 1: /* Disable navigation only */
2409 			gtk_widget_set_sensitive( img->ken_update,   TRUE );
2410 			gtk_widget_set_sensitive( img->ken_remove,   TRUE );
2411 
2412 		case 2: /* Only adding is enabled */
2413 			gtk_widget_set_sensitive( img->ken_add,      TRUE );
2414 			gtk_widget_set_sensitive( img->ken_zoom,     TRUE );
2415 			gtk_widget_set_sensitive( img->ken_duration, TRUE );
2416 
2417 		case 3: /* Disable all */
2418 			break;
2419 	}
2420 }
2421 
2422 void
img_subtitle_update_sensitivity(img_window_struct * img,gint mode)2423 img_subtitle_update_sensitivity( img_window_struct *img,
2424 								 gint               mode )
2425 {
2426 	/* Modes:
2427 	 *  0 - disable all
2428 	 *  1 - enable all
2429 	 *  2 - enable all but text field
2430 	 */
2431 
2432 	/* Text view is special, since it cannot handle multiple slides */
2433 	gtk_widget_set_sensitive( img->sub_textview,
2434 							  ( mode == 2 ? FALSE : (gboolean)mode ) );
2435 
2436 	/* Let's delete the textbuffer when no slide is selected */
2437 	if( mode == 0 || mode == 2 )
2438 	{
2439 		g_signal_handlers_block_by_func( (gpointer)img->slide_text_buffer,
2440 										 (gpointer)img_queue_subtitle_update,
2441 										 img );
2442 		g_object_set( G_OBJECT( img->slide_text_buffer ), "text", "", NULL );
2443 		g_signal_handlers_unblock_by_func( (gpointer)img->slide_text_buffer,
2444 										   (gpointer)img_queue_subtitle_update,
2445 										   img );
2446 	}
2447 
2448 	/* Animation duration is also special, since it shoudl be disabled when None
2449 	 * animation is selected. */
2450 	if( gtk_combo_box_get_active( GTK_COMBO_BOX( img->sub_anim ) ) && mode )
2451 		gtk_widget_set_sensitive( img->sub_anim_duration, TRUE );
2452 	else
2453 		gtk_widget_set_sensitive( img->sub_anim_duration, FALSE );
2454 
2455 	/* All other controls are simple */
2456 	gtk_widget_set_sensitive( img->sub_font,    (gboolean)mode );
2457 	gtk_widget_set_sensitive( img->sub_color,   (gboolean)mode );
2458     gtk_widget_set_sensitive( img->sub_bgcolor, (gboolean)mode );
2459 	gtk_widget_set_sensitive( img->sub_anim,    (gboolean)mode );
2460 	gtk_widget_set_sensitive( img->sub_placing, (gboolean)mode );
2461 	gtk_widget_set_sensitive( img->sub_pos,     (gboolean)mode );
2462 }
2463 
2464 void
img_update_sub_properties(img_window_struct * img,TextAnimationFunc anim,gint anim_id,gint anim_duration,ImgSubPos position,ImgRelPlacing placing,const gchar * desc,gdouble * color,gdouble * bgcolor)2465 img_update_sub_properties( img_window_struct *img,
2466 						   TextAnimationFunc  anim,
2467 						   gint               anim_id,
2468 						   gint               anim_duration,
2469 						   ImgSubPos          position,
2470 						   ImgRelPlacing      placing,
2471 						   const gchar       *desc,
2472 						   gdouble           *color,
2473 						   gdouble           *bgcolor)
2474 {
2475 	GList        *selected,
2476 				 *tmp;
2477 	GtkTreeIter   iter;
2478 	GtkTreeModel *model;
2479 
2480 	/* Get all selected slides */
2481 	selected = gtk_icon_view_get_selected_items(
2482 					GTK_ICON_VIEW( img->active_icon ) );
2483 	if( ! selected )
2484 		return;
2485 
2486 	model = GTK_TREE_MODEL( img->thumbnail_model );
2487 
2488 	for( tmp = selected; tmp; tmp = g_list_next( tmp ) )
2489 	{
2490 		slide_struct *slide;
2491 
2492 		gtk_tree_model_get_iter( model, &iter, (GtkTreePath *)tmp->data );
2493 		gtk_tree_model_get( model, &iter, 1, &slide, -1 );
2494 
2495 		img_set_slide_text_info( slide, NULL, NULL, NULL,
2496 								 anim_id, anim_duration, position,
2497 								 placing, desc, color, bgcolor, img );
2498 	}
2499 
2500 	g_list_foreach( selected, (GFunc)gtk_tree_path_free, NULL );
2501 	g_list_free( selected );
2502 }
2503 
2504 static void
img_toggle_mode(GtkCheckMenuItem * item,img_window_struct * img)2505 img_toggle_mode( GtkCheckMenuItem  *item,
2506 				 img_window_struct *img )
2507 {
2508 	gint mode;
2509 	mode = ( gtk_check_menu_item_get_active( item ) ? 0 : 1 );
2510 
2511 	img_switch_mode( img, mode );
2512 }
2513 
2514 void
img_switch_mode(img_window_struct * img,gint mode)2515 img_switch_mode( img_window_struct *img,
2516 				 gint               mode )
2517 {
2518 	GtkIconView *from,      /* Iconviews for selection synchronization */
2519 				*to;
2520 	GList       *selection, /* Selection to be copied from 'from' to 'to' */
2521 				*tmp;       /* Iterator */
2522 
2523 	if( img->mode == mode )
2524 		return;
2525 
2526 	img->mode = mode;
2527 
2528 	gtk_widget_hide( img->active_icon );
2529 	switch( mode )
2530 	{
2531 		case 0: /* Preview mode */
2532 			gtk_widget_hide( img->over_root );
2533 			gtk_widget_show( img->prev_root );
2534 			gtk_widget_show( img->thum_root );
2535 			img->active_icon = img->thumbnail_iconview;
2536 			from = GTK_ICON_VIEW( img->over_icon );
2537 			break;
2538 
2539 		case 1: /* Overview mode */
2540 			gtk_widget_hide( img->prev_root );
2541 			gtk_widget_hide( img->thum_root );
2542 			gtk_widget_show( img->over_root );
2543 			img->active_icon = img->over_icon;
2544 			from = GTK_ICON_VIEW( img->thumbnail_iconview );
2545 			break;
2546 	}
2547 	gtk_widget_show( img->active_icon );
2548 	to = GTK_ICON_VIEW( img->active_icon );
2549 
2550 	/* Synchronize selections */
2551 	selection = gtk_icon_view_get_selected_items( from );
2552 	if( ! selection )
2553 	{
2554 		gtk_icon_view_unselect_all( to );
2555 		return;
2556 	}
2557 
2558 	g_signal_handlers_block_by_func( from,
2559 									 img_iconview_selection_changed, img );
2560 	g_signal_handlers_block_by_func( to,
2561 									 img_iconview_selection_changed, img );
2562 
2563 	gtk_icon_view_unselect_all( to );
2564 	for( tmp = g_list_next( selection ); tmp; tmp = g_list_next( tmp ) )
2565 	{
2566 		GtkTreePath *path = (GtkTreePath *)tmp->data;
2567 		gtk_icon_view_select_path( to, path );
2568 		gtk_tree_path_free( path );
2569 	}
2570 
2571 	g_signal_handlers_unblock_by_func( from,
2572 									   img_iconview_selection_changed, img );
2573 	g_signal_handlers_unblock_by_func( to,
2574 									   img_iconview_selection_changed, img );
2575 
2576 	gtk_icon_view_select_path( to, (GtkTreePath *)selection->data );
2577 	gtk_icon_view_set_cursor( to, (GtkTreePath *)selection->data, NULL, FALSE );
2578 	gtk_tree_path_free( (GtkTreePath *)selection->data );
2579 
2580 	g_list_free( selection );
2581 }
2582 
img_report_slides_transitions(img_window_struct * img)2583 static void img_report_slides_transitions(img_window_struct *img)
2584 {
2585 	static GtkWidget *viewport;
2586 	GtkWidget        *label;
2587 	GHashTable       *trans_hash;
2588 	GList            *values,
2589 					 *tmp;
2590 	GtkTreeModel     *model;
2591 	GtkTreeIter       iter;
2592 	gboolean          flag;
2593 	gint              i;
2594 
2595 #define GIP( val ) GINT_TO_POINTER( ( val ) )
2596 #define GPI( val ) GPOINTER_TO_INT( ( val ) )
2597 
2598 	if (img->report_dialog == NULL)
2599 	{
2600 		GtkWidget *action,
2601 				  *vbox,
2602 				  *swindow;
2603 
2604 		img->report_dialog = gtk_dialog_new_with_buttons(
2605 					_("Slides Transitions Report Dialog"),
2606 					GTK_WINDOW( img->imagination_window ),
2607 					GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
2608 					GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
2609 					NULL );
2610 		gtk_container_set_border_width( GTK_CONTAINER( img->report_dialog ),
2611 										10 );
2612 		gtk_window_set_default_size( GTK_WINDOW( img->report_dialog ),
2613 									 480, 370 );
2614 		gtk_window_set_modal( GTK_WINDOW( img->report_dialog ), FALSE );
2615 
2616 		action = gtk_dialog_get_action_area( GTK_DIALOG( img->report_dialog ) );
2617 		gtk_button_box_set_layout( GTK_BUTTON_BOX( action ),
2618 								   GTK_BUTTONBOX_SPREAD);
2619 		g_signal_connect( G_OBJECT( img->report_dialog ), "delete-event",
2620 						  G_CALLBACK( gtk_widget_hide_on_delete ), NULL );
2621 		g_signal_connect( G_OBJECT( img->report_dialog ), "response",
2622 						  G_CALLBACK( gtk_widget_hide_on_delete ), NULL );
2623 
2624 		vbox = gtk_dialog_get_content_area( GTK_DIALOG( img->report_dialog ) );
2625 		swindow = gtk_scrolled_window_new( NULL, NULL );
2626 		gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( swindow ),
2627 										GTK_POLICY_AUTOMATIC,
2628 										GTK_POLICY_AUTOMATIC);
2629 		gtk_box_pack_start( GTK_BOX( vbox ), swindow, TRUE, TRUE, 0 );
2630 
2631 		viewport = gtk_viewport_new( NULL, NULL );
2632 		gtk_viewport_set_shadow_type( GTK_VIEWPORT( viewport ),
2633 									  GTK_SHADOW_NONE);
2634 		gtk_container_add( GTK_CONTAINER( swindow ), viewport );
2635 	}
2636 
2637 	/* Delete previous shown rows */
2638 	if( img->vbox_slide_report_rows )
2639 	{
2640 		gtk_widget_destroy( img->vbox_slide_report_rows );
2641 		img->vbox_slide_report_rows = NULL;
2642 	}
2643 
2644 	model = GTK_TREE_MODEL(img->thumbnail_model);
2645 	if( gtk_tree_model_get_iter_first( model, &iter ) == 0)
2646 		return;
2647 
2648 	/* Hash table is used only for quick way of accessing transition info.
2649 	 * Information is stored inside array of 3 gpointers */
2650 	trans_hash = g_hash_table_new( g_direct_hash, NULL );
2651 
2652 	for( flag = TRUE, i = 0;
2653 		 flag;
2654 		 flag = gtk_tree_model_iter_next( model, &iter ), i++ )
2655 	{
2656 		slide_struct *slide;
2657 		gpointer     *info;
2658 
2659 		gtk_tree_model_get( model, &iter, 1, &slide, -1 );
2660 		if( slide->transition_id < 1 )
2661 			continue;
2662 
2663 		info = g_hash_table_lookup( trans_hash, GIP( slide->transition_id ) );
2664 		if( ! info )
2665 		{
2666 			/* Create new info element */
2667 			info = g_slice_alloc0( sizeof( gpointer ) * 3 );
2668 			info[0] = GIP( slide->transition_id );
2669 			g_hash_table_insert( trans_hash, GIP( slide->transition_id ),
2670 											 info );
2671 		}
2672 
2673 		/* Increment counter */
2674 		info[1] = GIP( GPI( info[1] ) + 1 );
2675 
2676 		/* Append another element to glist */
2677 		info[2] = g_list_append( (GList *)info[2], GIP( i ) );
2678 	}
2679 
2680 	/* Set the vertical box container that was previously
2681 	 * destroyed so to allow update in real time */
2682 	img->vbox_slide_report_rows = gtk_vbox_new( FALSE, 15 );
2683 	gtk_container_add( GTK_CONTAINER( viewport ), img->vbox_slide_report_rows );
2684 
2685 	label = gtk_label_new( _("\n<span weight='bold'>Note:</span>\n\n"
2686 							 "Slides whose transition is applied only once are "
2687 							 "not shown here.\n"
2688 							 "Click on the slide to have Imagination "
2689 							 "automatically select it." ) );
2690 	gtk_misc_set_alignment( GTK_MISC( label ), 0.0, 0.5 );
2691 	gtk_label_set_use_markup( GTK_LABEL( label ), TRUE );
2692 	gtk_box_pack_start( GTK_BOX( img->vbox_slide_report_rows ), label,
2693 						FALSE, FALSE, 0);
2694 
2695 	/* Get information and free hash table */
2696 	values = g_hash_table_get_values( trans_hash );
2697 	g_hash_table_destroy( trans_hash );
2698 
2699 	/* Sort values list here */
2700 	values = g_list_sort( values, img_sort_report_transitions );
2701 
2702 	/* Display results */
2703 	for( tmp = values; tmp; tmp = g_list_next( tmp ) )
2704 	{
2705 		gpointer *info = tmp->data;
2706 
2707 		if( GPI( info[1] ) > 1 )
2708 		{
2709 			GList     *tmp1;
2710 			GtkWidget *hbox_rows,
2711 					  *frame,
2712 					  *image,
2713 					  *nr_label;
2714 			gchar     *filename,
2715 					  *nr;
2716 
2717 			hbox_rows = gtk_hbox_new( FALSE, 15 );
2718 			gtk_box_pack_start( GTK_BOX( img->vbox_slide_report_rows ),
2719 								hbox_rows, FALSE, FALSE, 0 );
2720 
2721 			frame = gtk_frame_new( NULL );
2722 			gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_NONE );
2723 			gtk_box_pack_start( GTK_BOX( hbox_rows ), frame, FALSE, FALSE, 0 );
2724 
2725 #if PLUGINS_INSTALLED
2726 			filename =
2727 				g_strdup_printf( "%s/imagination/pixmaps/imagination-%d.png",
2728 								 DATADIR, GPI( info[0] ) );
2729 #else /* PLUGINS_INSTALLED */
2730 			filename =
2731 				g_strdup_printf( "./pixmaps/imagination-%d.png",
2732 								 GPI( info[0] ) );
2733 #endif
2734 			image = gtk_image_new_from_file( filename );
2735 			g_free( filename );
2736 			gtk_container_add( GTK_CONTAINER( frame ), image );
2737 
2738 			nr = g_strdup_printf( "(%d)", GPI( info[1] ) );
2739 			nr_label = gtk_label_new( nr );
2740 			gtk_box_pack_start( GTK_BOX( hbox_rows ), nr_label,
2741 								FALSE, FALSE, 0 );
2742 			g_free( nr );
2743 
2744 			for( tmp1 = (GList *)info[2]; tmp1; tmp1 = g_list_next( tmp1 ) )
2745 			{
2746 				GtkWidget   *button,
2747 							*image;
2748 				GdkPixbuf   *pixbuf;
2749 				GtkTreePath *path;
2750 				GtkTreeIter  iter;
2751 
2752 				path = gtk_tree_path_new_from_indices( GPI( tmp1->data ), -1 );
2753 				gtk_tree_model_get_iter( model, &iter, path );
2754 				gtk_tree_path_free( path );
2755 
2756 				gtk_tree_model_get( model, &iter, 0, &pixbuf, -1 );
2757 
2758 				button = gtk_button_new();
2759 				g_object_set_data( G_OBJECT( button ), "index", tmp1->data );
2760 				g_signal_connect( G_OBJECT( button ), "clicked",
2761 								  G_CALLBACK( img_select_slide_from_slide_report_dialog ), img );
2762 				gtk_box_pack_start( GTK_BOX( hbox_rows ), button,
2763 									FALSE, FALSE, 0 );
2764 
2765 				image = gtk_image_new_from_pixbuf( pixbuf );
2766 				g_object_unref( G_OBJECT( pixbuf ) );
2767 				gtk_container_add( GTK_CONTAINER( button ), image );
2768 			}
2769 		}
2770 		g_list_free( (GList *)info[2] );
2771 		g_slice_free1( sizeof( gpointer ) * 3, info );
2772 	}
2773 
2774 	if( GTK_WIDGET_VISIBLE( img->report_dialog ) )
2775 		gtk_widget_show_all( img->report_dialog );
2776 
2777 #undef GIP
2778 #undef GPI
2779 }
2780 
img_select_slide_from_slide_report_dialog(GtkButton * button,img_window_struct * img)2781 static void img_select_slide_from_slide_report_dialog(GtkButton *button, img_window_struct *img)
2782 {
2783 	GtkTreePath *path;
2784 	gint slide = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "index"));
2785 
2786 	gtk_icon_view_unselect_all(GTK_ICON_VIEW (img->active_icon));
2787 	path = gtk_tree_path_new_from_indices(slide, -1);
2788 	gtk_icon_view_set_cursor (GTK_ICON_VIEW (img->active_icon), path, NULL, FALSE);
2789 	gtk_icon_view_select_path (GTK_ICON_VIEW (img->active_icon), path);
2790 	gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (img->active_icon), path, FALSE, 0, 0);
2791 	gtk_tree_path_free (path);
2792 }
2793 
img_show_slides_report_dialog(GtkMenuItem * item,img_window_struct * img)2794 static void img_show_slides_report_dialog(GtkMenuItem *item, img_window_struct *img)
2795 {
2796 	img_report_slides_transitions(img);
2797 	gtk_widget_show_all(img->report_dialog);
2798 }
2799 
2800 static gint
img_sort_report_transitions(gconstpointer a,gconstpointer b)2801 img_sort_report_transitions( gconstpointer a,
2802 							 gconstpointer b )
2803 {
2804 	gint val_a = GPOINTER_TO_INT( ( (gpointer *)a )[1] ),
2805 		 val_b = GPOINTER_TO_INT( ( (gpointer *)b )[1] );
2806 
2807 	return( val_a - val_b );
2808 }
2809 
2810 static void
img_toggle_frame_rate(GtkCheckMenuItem * item,img_window_struct * img)2811 img_toggle_frame_rate( GtkCheckMenuItem  *item,
2812 					   img_window_struct *img )
2813 {
2814 	gpointer tmp;
2815 
2816 	if( ! gtk_check_menu_item_get_active( item ) )
2817 		return;
2818 
2819 	tmp = g_object_get_data( G_OBJECT( item ), "index" );
2820 	img->preview_fps = GPOINTER_TO_INT( tmp );
2821 }
2822