static void expose_zoomable (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; float zoom, zoom_x, zoom_y; int32_t mouse_over_id, pan, track, center; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); zoom = dt_conf_get_int("plugins/lighttable/images_in_row"); zoom_x = lib->zoom_x; zoom_y = lib->zoom_y; pan = lib->pan; center = lib->center; track = lib->track; lib->image_over = DT_VIEW_DESERT; cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); const float wd = width/zoom; const float ht = width/zoom; static int oldpan = 0; static float oldzoom = -1; if(oldzoom < 0) oldzoom = zoom; // TODO: exaggerate mouse gestures to pan when zoom == 1 if(pan)// && mouse_over_id >= 0) { zoom_x = lib->select_offset_x - /* (zoom == 1 ? 2. : 1.)*/pointerx; zoom_y = lib->select_offset_y - /* (zoom == 1 ? 2. : 1.)*/pointery; } if(!lib->statements.main_query) return; if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > DT_LIBRARY_MAX_ZOOM) { // double speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > 1.5*DT_LIBRARY_MAX_ZOOM) { // quad speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; } } if(oldzoom != zoom) { float oldx = (pointerx + zoom_x)*oldzoom/width; float oldy = (pointery + zoom_y)*oldzoom/width; if(zoom == 1) { zoom_x = (int)oldx*wd; zoom_y = (int)oldy*ht; lib->offset = 0x7fffffff; } else { zoom_x = oldx*wd - pointerx; zoom_y = oldy*ht - pointery; } } oldzoom = zoom; // TODO: replace this with center on top of selected/developed image if(center) { if(mouse_over_id >= 0) { zoom_x = wd*((int)(zoom_x)/(int)wd); zoom_y = ht*((int)(zoom_y)/(int)ht); } else zoom_x = zoom_y = 0.0; center = 0; } // mouse left the area, but we leave mouse over as it was, especially during panning // if(!pan && pointerx > 0 && pointerx < width && pointery > 0 && pointery < height) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); if(!pan && zoom != 1) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); // set scrollbar positions, clamp zoom positions if(lib->collection_count == 0) { zoom_x = zoom_y = 0.0f; } else if(zoom < 1.01) { if(zoom_x < 0) zoom_x = 0; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < 0) zoom_y = 0; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } else { if(zoom_x < -wd*DT_LIBRARY_MAX_ZOOM/2) zoom_x = -wd*DT_LIBRARY_MAX_ZOOM/2; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < -height+ht) zoom_y = -height+ht; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } int offset_i = (int)(zoom_x/wd); int offset_j = (int)(zoom_y/ht); if(lib->first_visible_filemanager >= 0) { offset_i = lib->first_visible_filemanager % DT_LIBRARY_MAX_ZOOM; offset_j = lib->first_visible_filemanager / DT_LIBRARY_MAX_ZOOM; } lib->first_visible_filemanager = -1; lib->first_visible_zoomable = offset_i + DT_LIBRARY_MAX_ZOOM*offset_j; // arbitrary 1000 to avoid bug due to round towards zero using (int) int seli = zoom == 1 ? 0 : ((int)(1000 + (pointerx + zoom_x)/wd) - MAX(offset_i, 0) - 1000); int selj = zoom == 1 ? 0 : ((int)(1000 + (pointery + zoom_y)/ht) - offset_j - 1000); float offset_x = (zoom == 1) ? 0.0 : (zoom_x/wd - (int)(zoom_x/wd)); float offset_y = (zoom == 1) ? 0.0 : (zoom_y/ht - (int)(zoom_y/ht)); const int max_rows = (zoom == 1) ? 1 : (2 + (int)((height)/ht + .5)); const int max_cols = (zoom == 1) ? 1 : (MIN(DT_LIBRARY_MAX_ZOOM - MAX(0, offset_i), 1 + (int)(zoom+.5))); int offset = MAX(0, offset_i) + DT_LIBRARY_MAX_ZOOM*offset_j; int img_pointerx = zoom == 1 ? pointerx : fmodf(pointerx + zoom_x, wd); int img_pointery = zoom == 1 ? pointery : fmodf(pointery + zoom_y, ht); // assure 1:1 is not switching images on resize/tab events: if(!track && lib->offset != 0x7fffffff && zoom == 1) { offset = lib->offset; zoom_x = wd*(offset % DT_LIBRARY_MAX_ZOOM); zoom_y = ht*(offset / DT_LIBRARY_MAX_ZOOM); } else lib->offset = offset; int id, clicked1, last_seli = 1<<30, last_selj = 1<<30; clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); dt_view_set_scrollbar(self, MAX(0, offset_i), DT_LIBRARY_MAX_ZOOM, zoom, DT_LIBRARY_MAX_ZOOM*offset_j, lib->collection_count, DT_LIBRARY_MAX_ZOOM*max_cols); cairo_translate(cr, -offset_x*wd, -offset_y*ht); cairo_translate(cr, -MIN(offset_i*wd, 0.0), 0.0); for(int row = 0; row < max_rows; row++) { if(offset < 0) { cairo_translate(cr, 0, ht); offset += DT_LIBRARY_MAX_ZOOM; continue; } /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_cols); for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { id = sqlite3_column_int(lib->statements.main_query, 0); // set mouse over id if((zoom == 1 && mouse_over_id < 0) || ((!pan || track) && seli == col && selj == row)) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } // add clicked image to selected table if(clicked1) { if((lib->modifiers & GDK_SHIFT_MASK) == 0 && (lib->modifiers & GDK_CONTROL_MASK) == 0 && seli == col && selj == row) { /* clear selection except id */ /* clear and resest statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.delete_except_arg); DT_DEBUG_SQLITE3_RESET(lib->statements.delete_except_arg); /* reuse statment */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.delete_except_arg, 1, id); sqlite3_step(lib->statements.delete_except_arg); } // FIXME: whatever comes first assumtion is broken! // if((lib->modifiers & GDK_SHIFT_MASK) && (last_seli == (1<<30)) && // (image->id == lib->last_selected_id || image->id == mouse_over_id)) { last_seli = col; last_selj = row; } // if(last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= MIN(last_seli,seli) && row >= MIN(last_selj,selj) && // col <= MAX(last_seli,seli) && row <= MAX(last_selj,selj)) && (col != last_seli || row != last_selj)) || if((lib->modifiers & GDK_SHIFT_MASK) && id == lib->last_selected_idx) { last_seli = col; last_selj = row; } if((last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= last_seli && row >= last_selj && col <= seli && row <= selj) && (col != last_seli || row != last_selj))) || (seli == col && selj == row)) { // insert all in range if shift, or only the one the mouse is over for ctrl or plain click. dt_view_toggle_selection(id); lib->last_selected_idx = id; } } cairo_save(cr); // if(zoom == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, zoom == 1 ? height : ht, zoom, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); offset += DT_LIBRARY_MAX_ZOOM; } failure: oldpan = pan; lib->zoom_x = zoom_x; lib->zoom_y = zoom_y; lib->track = 0; lib->center = center; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); }
static gboolean _lib_filmstrip_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int32_t width = allocation.width; int32_t height = allocation.height; gdouble pointerx = strip->pointerx; gdouble pointery = strip->pointery; if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip++; strip->image_over = DT_VIEW_DESERT; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); /* create cairo surface */ cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); int offset = strip->offset; const float wd = height; const float ht = height; int max_cols = (int)(width/(float)wd) + 2; if (max_cols%2 == 0) max_cols += 1; const int col_start = max_cols/2 - strip->offset; const int empty_edge = (width - (max_cols * wd))/2; int step_res = SQLITE_ROW; sqlite3_stmt *stmt = NULL; /* mouse over image position in filmstrip */ pointerx -= empty_edge; const int seli = (pointery > 0 && pointery <= ht) ? pointerx / (float)wd : -1; const int img_pointerx = (int)fmodf(pointerx, wd); const int img_pointery = (int)pointery; /* get the count of current collection */ strip->collection_count = dt_collection_get_count (darktable.collection); /* get the collection query */ const gchar *query=dt_collection_get_query (darktable.collection); if(!query) return FALSE; if(offset < 0) strip->offset = offset = 0; if(offset > strip->collection_count-1) strip->offset = offset = strip->collection_count-1; // dt_view_set_scrollbar(self, offset, count, max_cols, 0, 1, 1); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset - max_cols/2); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_cols); cairo_save(cr); cairo_translate(cr, empty_edge, 0.0f); for(int col = 0; col < max_cols; col++) { if(col < col_start) { cairo_translate(cr, wd, 0.0f); continue; } if(step_res != SQLITE_DONE) { step_res = sqlite3_step(stmt); } if(step_res == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); // set mouse over id if(seli == col) { strip->mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->mouse_over_id); } cairo_save(cr); // FIXME find out where the y translation is done, how big the value is and use it directly instead of getting it from the matrix ... cairo_matrix_t m; cairo_get_matrix(cr, &m); dt_view_image_expose(&(strip->image_over), id, cr, wd, ht, max_cols, img_pointerx, img_pointery, FALSE); cairo_restore(cr); } else if (step_res == SQLITE_DONE) { /* do nothing, just add some empty thumb frames */ } else goto failure; cairo_translate(cr, wd, 0.0f); } failure: cairo_restore(cr); sqlite3_finalize(stmt); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(strip->mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", "", (char *)NULL); } #ifdef _DEBUG if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); #endif /* cleanup */ cairo_destroy(cr); return TRUE; }
static void expose_filemanager (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; gboolean offset_changed = FALSE; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip = 2; /* get grid stride */ const int iir = dt_conf_get_int("plugins/lighttable/images_in_row"); /* get image over id */ lib->image_over = DT_VIEW_DESERT; int32_t mouse_over_id, mouse_over_group = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); if(lib->first_visible_zoomable >= 0) { lib->offset = lib->first_visible_zoomable; } lib->first_visible_zoomable = -1; /* check if offset has been changed */ if(lib->track > 2) lib->offset += iir; if(lib->track < -2) lib->offset -= iir; lib->track = 0; if(lib->center) lib->offset = 0; lib->center = 0; int offset = lib->offset; /* if offset differs then flag as changed */ if (offset != lib->first_visible_filemanager) offset_changed = TRUE; lib->first_visible_filemanager = offset; static int oldpan = 0; const int pan = lib->pan; const float wd = width/(float)iir; const float ht = width/(float)iir; int pi = pointerx / (float)wd; int pj = pointery / (float)ht; if(pointerx < 0 || pointery < 0) pi = pj = -1; //const int pidx = grid_to_index(pj, pi, iir, offset); const int img_pointerx = iir == 1 ? pointerx : fmodf(pointerx, wd); const int img_pointery = iir == 1 ? pointery : fmodf(pointery, ht); const int max_rows = 1 + (int)((height)/ht + .5); const int max_cols = iir; int id; int clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); /* get the count of current collection */ if(lib->collection_count == 0) { const float fs = 15.0f; const float ls = 1.5f*fs; const float offy = height*0.2f; const float offx = 60; const float at = 0.3f; cairo_set_font_size(cr, fs); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_move_to(cr, offx, offy); cairo_show_text(cr, _("there are no images in this collection")); cairo_move_to(cr, offx, offy + 2*ls); cairo_show_text(cr, _("if you have not imported any images yet")); cairo_move_to(cr, offx, offy + 3*ls); cairo_show_text(cr, _("you can do so in the import module")); cairo_move_to(cr, offx - 10.0f, offy + 3*ls - ls*.25f); cairo_line_to(cr, 0.0f, 10.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 5*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("try to relax the filter settings in the top panel")); cairo_rel_move_to(cr, 10.0f, -ls*.25f); cairo_line_to(cr, width*0.5f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 6*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("or add images in the collection module in the left panel")); cairo_move_to(cr, offx - 10.0f, offy + 6*ls - ls*0.25f); cairo_rel_line_to(cr, - offx + 10.0f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); return; } /* do we have a main query collection statement */ if(!lib->statements.main_query) return; if(offset < 0) lib->offset = offset = 0; while(offset >= lib->collection_count) lib->offset = (offset -= iir); /* update scroll borders */ dt_view_set_scrollbar(self, 0, 1, 1, offset, lib->collection_count, max_rows*iir); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offset and row for the main query */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_rows*iir); if(mouse_over_id != -1) { const dt_image_t *mouse_over_image = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); mouse_over_group = mouse_over_image->group_id; dt_image_cache_read_release(darktable.image_cache, mouse_over_image); DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.is_grouped); DT_DEBUG_SQLITE3_RESET(lib->statements.is_grouped); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 1, mouse_over_group); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 2, mouse_over_id); if(sqlite3_step(lib->statements.is_grouped) != SQLITE_ROW) mouse_over_group = -1; } // prefetch the ids so that we can peek into the future to see if there are adjacent images in the same group. int *query_ids = g_malloc0(max_rows*max_cols*sizeof(int)); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) query_ids[row*iir+col] = sqlite3_column_int(lib->statements.main_query, 0); else goto end_query_cache; } } end_query_cache: cairo_save(cr); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { //curidx = grid_to_index(row, col, iir, offset); id = query_ids[row*iir+col]; if(id > 0) { if (iir == 1 && row) continue; /* set mouse over id if pointer is in current row / col */ if(pi == col && pj == row) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } /* handle mouse click on current row / col this could easily and preferable be moved to button_pressed() */ if (clicked1 && (pi == col && pj == row)) { if ((lib->modifiers & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == 0) dt_selection_select_single(darktable.selection, id); else if ((lib->modifiers & (GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) dt_selection_toggle(darktable.selection, id); else if ((lib->modifiers & (GDK_SHIFT_MASK)) == GDK_SHIFT_MASK) dt_selection_select_range(darktable.selection, id); } cairo_save(cr); // if(iir == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, iir == 1 ? height : ht, iir, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } cairo_restore(cr); // and now the group borders for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { id = query_ids[row*iir+col]; if(id > 0) { const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, id); int group_id = -1; if(image) group_id = image->group_id; dt_image_cache_read_release(darktable.image_cache, image); if (iir == 1 && row) continue; cairo_save(cr); gboolean paint_border = FALSE; // regular highlight border if(group_id != -1) { if(mouse_over_group == group_id && iir > 1 && ((!darktable.gui->grouping && dt_conf_get_bool("plugins/lighttable/draw_group_borders")) || group_id == darktable.gui->expanded_group_id)) { cairo_set_source_rgb(cr, 1, 0.8, 0); paint_border = TRUE; } // border of expanded group else if(darktable.gui->grouping && group_id == darktable.gui->expanded_group_id && iir > 1) { cairo_set_source_rgb(cr, 0, 0, 1); paint_border = TRUE; } } if(paint_border) { int neighbour_group = -1; // top border if(row > 0) { int _id = query_ids[(row-1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, wd, 0); } // left border neighbour_group = -1; if(col > 0) { int _id = query_ids[row*iir+(col-1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, 0, ht); } // bottom border neighbour_group = -1; if(row < max_rows-1) { int _id = query_ids[(row+1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, ht); cairo_line_to(cr, wd, ht); } // right border neighbour_group = -1; if(col < max_cols-1) { int _id = query_ids[row*iir+(col+1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, wd, 0); cairo_line_to(cr, wd, ht); } cairo_set_line_width(cr, 0.01*wd); cairo_stroke(cr); } cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } /* check if offset was changed and we need to prefetch thumbs */ if (offset_changed) { int32_t imgids_num = 0; const int prefetchrows = .5*max_rows+1; int32_t imgids[prefetchrows*iir]; /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offest and row for prefetch */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset + max_rows*iir); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, prefetchrows*iir); // prefetch jobs in inverse order: supersede previous jobs: most important last while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW && imgids_num < prefetchrows*iir) imgids[imgids_num++] = sqlite3_column_int(lib->statements.main_query, 0); float imgwd = iir == 1 ? 0.97 : 0.8; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size( darktable.mipmap_cache, imgwd*wd, imgwd*(iir==1?height:ht)); while(imgids_num > 0) { imgids_num --; dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get( darktable.mipmap_cache, &buf, imgids[imgids_num], mip, DT_MIPMAP_PREFETCH); } } failure: g_free(query_ids); oldpan = pan; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", "", (char *)NULL); } }