44
55#include "vipsdisp.h"
66
7- /* We have a number of active imageui (open images) and look them up via a
8- * filename. Use this to flip back to an open image.
7+ /* We have a number of active imageui (open images) and look them up via the
8+ * tile_source filename or image pointer.
9+ *
10+ * Use these to flip back to an already open image.
911 */
1012typedef struct _Active {
1113 ImageWindow * win ;
12- const char * filename ;
14+
15+ /* This is a ref ... we can't just use the ref in the widget hierarchy or
16+ * it'll be freed during gtk_stack_remove() and cause chaos.
17+ *
18+ * Fetch active
19+ */
1320 Imageui * imageui ;
1421
1522 /* A timestamp we update on every action -- we throw away the oldest views
@@ -60,7 +67,7 @@ struct _ImageWindow {
6067 /* The set of active images in the stack right now. These are not
6168 * references.
6269 */
63- GHashTable * active_hash ;
70+ GSList * active ;
6471
6572 GSettings * settings ;
6673};
@@ -138,80 +145,80 @@ image_window_error_hide(ImageWindow *win)
138145 */
139146
140147static Active *
141- image_window_active_lookup (ImageWindow * win , const char * filename )
142- {
143- return g_hash_table_lookup (win -> active_hash , (gpointer ) filename );
144- }
145-
146- static void
147- image_window_active_touch (ImageWindow * win , const char * filename )
148+ image_window_active_lookup_by_filename (ImageWindow * win , const char * filename )
148149{
149- static int serial = 0 ;
150+ for (GSList * p = win -> active ; p ; p = p -> next ) {
151+ Active * active = (Active * ) p -> data ;
152+ TileSource * tile_source = imageui_get_tile_source (active -> imageui );
150153
151- Active * active = image_window_active_lookup (win , filename );
154+ if (tile_source -> filename &&
155+ g_str_equal (tile_source -> filename , filename ))
156+ return active ;
157+ }
152158
153- active -> timestamp = serial ++ ;
159+ return NULL ;
154160}
155161
156162static void
157- active_imageui_active_oldest ( gpointer key , gpointer value , gpointer user_data )
163+ image_window_active_touch ( ImageWindow * win , Active * active )
158164{
159- Active * this = (Active * ) value ;
160- const char * * oldest = (const char * * ) user_data ;
161- Active * prev = (* oldest ) ?
162- image_window_active_lookup (this -> win , * oldest ) : NULL ;
165+ static int serial = 0 ;
163166
164- if (!prev ||
165- this -> timestamp < prev -> timestamp )
166- * oldest = this -> filename ;
167+ active -> timestamp = serial ++ ;
167168}
168169
169170static void
170- image_window_active_remove (ImageWindow * win , const char * filename )
171+ image_window_active_remove (ImageWindow * win , Active * active )
171172{
172- Active * active = image_window_active_lookup ( win , filename );
173+ gtk_stack_remove ( GTK_STACK ( win -> stack ), GTK_WIDGET ( active -> imageui ) );
173174
174175 if (active -> imageui == win -> imageui )
175176 win -> imageui = NULL ;
176177
177- // many version of gtk hate removing a widget which has focus
178- gtk_widget_grab_focus (win -> gears );
178+ VIPS_UNREF (active -> imageui );
179179
180- gtk_stack_remove (GTK_STACK (win -> stack ), GTK_WIDGET (active -> imageui ));
181- g_hash_table_remove (win -> active_hash , filename );
180+ win -> active = g_slist_remove (win -> active , active );
181+
182+ g_free (active );
182183}
183184
184185static void
185186image_window_active_remove_all (ImageWindow * win )
186187{
187- g_autofree const char * * filenames =
188- ( const char * * ) g_hash_table_get_keys_as_array ( win -> active_hash , NULL ) ;
188+ while ( win -> active ) {
189+ Active * active = ( Active * ) win -> active -> data ;
189190
190- for ( const char * * p = filenames ; * p ; p ++ )
191- image_window_active_remove ( win , * p );
191+ image_window_active_remove ( win , active );
192+ }
192193}
193194
194195static void
195- image_window_active_add (ImageWindow * win ,
196- const char * filename , Imageui * imageui )
196+ image_window_active_add (ImageWindow * win , Imageui * imageui )
197197{
198- g_assert (!image_window_active_lookup (win , filename ));
199-
200198 Active * active = VIPS_NEW (NULL , Active );
201199 active -> win = win ;
202- active -> filename = filename ;
203200 active -> imageui = imageui ;
204- g_hash_table_insert (win -> active_hash , (gpointer ) filename , active );
205- image_window_active_touch (win , filename );
206201
207- if (g_hash_table_size (win -> active_hash ) > 3 ) {
208- const char * oldest = NULL ;
202+ // we hold a true reference
203+ g_object_ref (imageui );
204+
205+ win -> active = g_slist_prepend (win -> active , active );
209206
210- g_hash_table_foreach (win -> active_hash ,
211- active_imageui_active_oldest , & oldest );
207+ image_window_active_touch (win , active );
208+
209+ while (g_slist_length (win -> active ) > 3 ) {
210+ Active * oldest ;
211+
212+ oldest = NULL ;
213+ for (GSList * p = win -> active ; p ; p = p -> next ) {
214+ Active * active = (Active * ) p -> data ;
215+
216+ if (!oldest ||
217+ active -> timestamp < oldest -> timestamp )
218+ oldest = active ;
219+ }
212220
213- if (oldest )
214- image_window_active_remove (win , oldest );
221+ image_window_active_remove (win , oldest );
215222 }
216223}
217224
@@ -544,7 +551,7 @@ image_window_imageui_changed(Imageui *imageui, ImageWindow *win)
544551/* Add an imageui to the stack.
545552 */
546553static void
547- image_window_imageui_add (ImageWindow * win , Imageui * imageui )
554+ image_window_imageui_add (ImageWindow * win , Imageui * imageui )
548555{
549556 TileSource * tile_source = imageui_get_tile_source (imageui );
550557
@@ -563,6 +570,8 @@ image_window_imageui_add(ImageWindow *win, Imageui *imageui)
563570
564571 gtk_stack_add_child (GTK_STACK (win -> stack ), GTK_WIDGET (imageui ));
565572
573+ image_window_active_add (win , imageui );
574+
566575 // now it's in the UI, trigger a load
567576 tile_source_background_load (tile_source );
568577}
@@ -580,9 +589,10 @@ image_window_imageui_set_visible(ImageWindow *win,
580589 VipsImage * image ;
581590 char * title ;
582591
583- g_object_set (old_tile_source ,
584- "visible" , FALSE,
585- NULL );
592+ if (old_tile_source )
593+ g_object_set (old_tile_source ,
594+ "visible" , FALSE,
595+ NULL );
586596
587597 g_object_set (win -> properties ,
588598 "tile-source" , new_tile_source ,
@@ -657,8 +667,8 @@ image_window_open_current_file(ImageWindow *win,
657667 image_window_imageui_set_visible (win , NULL , transition );
658668 else {
659669 char * filename = win -> files [win -> current_file ];
660- g_autoptr (Imageui ) imageui = NULL ;
661670
671+ Imageui * imageui ;
662672 Active * active ;
663673
664674#ifdef DEBUG
@@ -667,10 +677,9 @@ image_window_open_current_file(ImageWindow *win,
667677
668678 /* An old image selected again?
669679 */
670- if ((active = image_window_active_lookup (win , filename ))) {
680+ imageui = NULL ;
681+ if ((active = image_window_active_lookup_by_filename (win , filename )))
671682 imageui = active -> imageui ;
672- g_object_ref (imageui );
673- }
674683 else {
675684 /* FIXME ... we only want to revalidate if eg. the timestamp has
676685 * changed, or perhaps on F5?
@@ -696,8 +705,6 @@ image_window_open_current_file(ImageWindow *win,
696705 }
697706
698707 image_window_imageui_add (win , imageui );
699-
700- image_window_active_add (win , filename , imageui );
701708 }
702709
703710 image_window_imageui_set_visible (win , imageui , transition );
@@ -713,11 +720,12 @@ image_window_dispose(GObject *object)
713720 printf ("image_window_dispose:\n" );
714721#endif /*DEBUG*/
715722
723+ image_window_files_free (win );
724+
716725 VIPS_UNREF (win -> save_folder );
717726 VIPS_UNREF (win -> load_folder );
718727 VIPS_FREEF (gtk_widget_unparent , win -> right_click_menu );
719728 VIPS_FREEF (g_timer_destroy , win -> progress_timer );
720- image_window_files_free (win );
721729
722730 G_OBJECT_CLASS (image_window_parent_class )-> dispose (object );
723731}
@@ -1508,8 +1516,6 @@ image_window_init(ImageWindow *win)
15081516 win -> save_folder = g_file_new_for_path (cwd );
15091517 win -> load_folder = g_file_new_for_path (cwd );
15101518 g_free (cwd );
1511- win -> active_hash = g_hash_table_new_full (g_str_hash , g_str_equal ,
1512- NULL , g_free );
15131519
15141520 gtk_widget_init_template (GTK_WIDGET (win ));
15151521
@@ -1714,7 +1720,7 @@ image_window_open_image(ImageWindow *win, VipsImage *image)
17141720 return ;
17151721 }
17161722
1717- g_autoptr ( Imageui ) imageui = imageui_new (tile_source );
1723+ Imageui * imageui = imageui_new (tile_source );
17181724 if (!imageui ) {
17191725 image_window_error (win );
17201726 return ;
0 commit comments