void dt_selection_select_range(dt_selection_t *selection, uint32_t imgid) { gchar *fullq = NULL; sqlite3_stmt *stmt; if (!selection->collection || selection->last_single_id == -1) return; /* get start and end rows for range selection */ int rc=0; uint32_t sr=-1,er=-1; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), dt_collection_get_query(selection->collection), -1, &stmt, NULL); while(sqlite3_step(stmt)==SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); if (id == selection->last_single_id) sr = rc; if (id == imgid) er = rc; if (sr != -1 && er != -1 ) break; rc++; } sqlite3_finalize(stmt); /* selece the images in range from start to end */ uint32_t old_flags = dt_collection_get_query_flags(selection->collection); /* use the limit to select range of images */ dt_collection_set_query_flags(selection->collection, (old_flags |COLLECTION_QUERY_USE_LIMIT)); dt_collection_update(selection->collection); fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images "); fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection)); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), fullq, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, MIN(sr,er)); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, (MAX(sr,er)-MIN(sr,er))+1); sqlite3_step(stmt); /* reset filter */ dt_collection_set_query_flags(selection->collection, old_flags); dt_collection_update(selection->collection); selection->last_single_id = -1; }
void dt_selection_invert(dt_selection_t *selection) { gchar *fullq = NULL; if (!selection->collection) return; fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images "); fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection)); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "insert into memory.tmp_selection select imgid from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq, NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images where imgid in (select imgid from memory.tmp_selection)", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from memory.tmp_selection", NULL, NULL, NULL); g_free(fullq); /* update hint message */ dt_collection_hint_message(darktable.collection); }
void dt_selection_select_unaltered(dt_selection_t *selection) { char *fullq = NULL; if (!selection->collection) return; /* set unaltered collection filter and update query */ uint32_t old_filter_flags = dt_collection_get_filter_flags(selection->collection); dt_collection_set_filter_flags (selection->collection, (dt_collection_get_filter_flags(selection->collection) | COLLECTION_FILTER_UNALTERED)); dt_collection_update(selection->collection); fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images "); fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection)); /* clean current selection and select unaltered images */ DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq, NULL, NULL, NULL); /* restore collection filter and update query */ dt_collection_set_filter_flags(selection->collection, old_filter_flags); dt_collection_update(selection->collection); g_free(fullq); selection->last_single_id = -1; }
int dt_collection_image_offset(int imgid) { const gchar *qin = dt_collection_get_query (darktable.collection); int offset = 0; sqlite3_stmt *stmt; if(qin) { DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), qin, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); gboolean found = FALSE; while (sqlite3_step (stmt) == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); if (imgid == id) { found = TRUE; break; } offset++; } if (!found) offset = 0; sqlite3_finalize(stmt); } return offset; }
static gboolean _lib_filmstrip_imgid_in_collection(const dt_collection_t *collection, const int imgid) { sqlite3_stmt *stmt = NULL; uint32_t count=1; const gchar *query = dt_collection_get_query(collection); gchar *count_query = NULL; //gchar *fq = g_strstr_len(query, strlen(query), "from"); gchar *fw = g_strstr_len(query, strlen(query), "where") + 6; gchar *qq = NULL; qq = dt_util_dstrcat(qq, "id=?3 and %s", fw); if ((collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT)) count_query = dt_util_dstrcat(NULL, "select count(images.id) from images %s and id=?3", collection->where_ext); else count_query = dt_util_dstrcat(count_query, "select count(id) from images where %s", qq); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), count_query, -1, &stmt, NULL); if ((collection->params.query_flags&COLLECTION_QUERY_USE_LIMIT) && !(collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT)) { DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); } DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) count = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); g_free(count_query); return count; }
static uint32_t _dt_collection_compute_count(const dt_collection_t *collection) { sqlite3_stmt *stmt = NULL; uint32_t count=1; const gchar *query = dt_collection_get_query(collection); gchar *count_query = NULL; gchar *fq = g_strstr_len(query, strlen(query), "from"); if ((collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT)) count_query = dt_util_dstrcat(NULL, "select count(images.id) from images %s", collection->where_ext); else count_query = dt_util_dstrcat(count_query, "select count(id) %s", fq); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), count_query, -1, &stmt, NULL); if ((collection->params.query_flags&COLLECTION_QUERY_USE_LIMIT) && !(collection->params.query_flags&COLLECTION_QUERY_USE_ONLY_WHERE_EXT)) { DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); } if(sqlite3_step(stmt) == SQLITE_ROW) count = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); g_free(count_query); return count; }
void _view_map_collection_changed(gpointer instance, gpointer user_data) { dt_view_t *self = (dt_view_t *)user_data; dt_map_t *lib = (dt_map_t *)self->data; /* check if we can get a query from collection */ const gchar *query = dt_collection_get_query (darktable.collection); if(!query) return; /* if we have a statment lets clean it */ if(lib->statements.main_query) sqlite3_finalize(lib->statements.main_query); /* build the new query string */ char *geo_query = g_strdup("select id from images where \ longitude >= ?1 and longitude <= ?2 and latitude <= ?3 and latitude >= ?4\ and longitude not NULL and latitude not NULL limit 0, 100"); /* prepare a new main query statement for collection */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), geo_query, -1, &lib->statements.main_query, NULL); dt_control_queue_redraw_widget(GTK_WIDGET(lib->map)); g_free(geo_query); }
void dt_selection_invert(dt_selection_t *selection) { gchar *fullq = NULL; if(!selection->collection) return; fullq = dt_util_dstrcat(fullq, "%s", "INSERT OR IGNORE INTO main.selected_images "); fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection)); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "INSERT INTO memory.tmp_selection SELECT imgid FROM main.selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM main.selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq, NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM main.selected_images WHERE imgid IN (SELECT imgid FROM memory.tmp_selection)", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM memory.tmp_selection", NULL, NULL, NULL); g_free(fullq); dt_control_signal_raise(darktable.signals, DT_SIGNAL_SELECTION_CHANGED); /* update hint message */ dt_collection_hint_message(darktable.collection); }
static void _view_lighttable_collection_listener_callback(gpointer instance, gpointer user_data) { dt_view_t *self = (dt_view_t *)user_data; dt_library_t *lib = (dt_library_t *)self->data; /* check if we can get a query from collection */ const gchar *query=dt_collection_get_query (darktable.collection); if(!query) return; /* if we have a statment lets clean it */ if(lib->statements.main_query) sqlite3_finalize(lib->statements.main_query); /* prepare a new main query statement for collection */ DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &lib->statements.main_query, NULL); dt_control_queue_redraw_center(); }
void dt_selection_select_all(dt_selection_t *selection) { gchar *fullq = NULL; if (!selection->collection) return; fullq = dt_util_dstrcat(fullq, "%s", "insert or ignore into selected_images "); fullq = dt_util_dstrcat(fullq, "%s", dt_collection_get_query(selection->collection)); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), fullq, NULL, NULL, NULL); selection->last_single_id = -1; g_free(fullq); /* update hint message */ dt_collection_hint_message(darktable.collection); }
static void dt_dev_jump_image(dt_develop_t *dev, int diff) { const gchar *qin = dt_collection_get_query (darktable.collection); int offset = 0; if(qin) { int orig_imgid = -1, imgid = -1; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) orig_imgid = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); offset = dt_collection_image_offset (orig_imgid); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), qin, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset + diff); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, 1); if(sqlite3_step(stmt) == SQLITE_ROW) { imgid = sqlite3_column_int(stmt, 0); if (orig_imgid == imgid) { //nothing to do sqlite3_finalize(stmt); return; } if (!dev->image_loading) { dt_view_filmstrip_scroll_to_image(darktable.view_manager, imgid, FALSE); } dt_dev_change_image(dev, imgid); } sqlite3_finalize(stmt); } }
int dt_collection_get_nth(const dt_collection_t *collection, int nth) { if(nth < 0 || nth >= dt_collection_get_count(collection)) return -1; const gchar *query = dt_collection_get_query(collection); sqlite3_stmt *stmt = NULL; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, nth); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, 1); int result = -1; if(sqlite3_step(stmt) == SQLITE_ROW) { result = sqlite3_column_int(stmt, 0); } sqlite3_finalize(stmt); return result; }
void dt_view_filmstrip_prefetch() { const gchar *qin = dt_collection_get_query (darktable.collection); if(!qin) return; char query[1024]; int offset = 0; if(qin) { int imgid = -1; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) imgid = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); snprintf(query, 1024, "select rowid from (%s) where id=?3", qin); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) offset = sqlite3_column_int(stmt, 0) - 1; sqlite3_finalize(stmt); } sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), qin, -1, &stmt, NULL); // only get one more image: DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset+1); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offset+2); if(sqlite3_step(stmt) == SQLITE_ROW) { const uint32_t prefetchid = sqlite3_column_int(stmt, 0); // dt_control_log("prefetching image %u", prefetchid); dt_mipmap_cache_read_get(darktable.mipmap_cache, NULL, prefetchid, DT_MIPMAP_FULL, DT_MIPMAP_PREFETCH); } sqlite3_finalize(stmt); }
static void _lib_filmstrip_scroll_to_image(dt_lib_module_t *self, gint imgid, gboolean activate) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; /* if no imgid just bail out */ if(imgid <= 0) return; strip->activated_image = imgid; char query[1024]; const gchar *qin = dt_collection_get_query (darktable.collection); if(qin) { snprintf(query, 1024, "select rowid from (%s) where id=?3", qin); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) { strip->offset = sqlite3_column_int(stmt, 0) - 1; } sqlite3_finalize(stmt); } /* activate the image if requested */ if (activate) { strip->activated_image = imgid; dt_control_signal_raise(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE); } /* redraw filmstrip */ gboolean owns_lock = dt_control_gdk_lock(); gtk_widget_queue_draw(self->widget); if(owns_lock) dt_control_gdk_unlock(); }
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; }
void dt_collection_update_query(const dt_collection_t *collection) { char query[1024], confname[200]; gchar *complete_query = NULL; const int _n_r = dt_conf_get_int("plugins/lighttable/collect/num_rules"); const int num_rules = CLAMP(_n_r, 1, 10); char *conj[] = {"and", "or", "and not"}; complete_query = dt_util_dstrcat(complete_query, "("); for(int i=0; i<num_rules; i++) { snprintf(confname, sizeof(confname), "plugins/lighttable/collect/item%1d", i); const int property = dt_conf_get_int(confname); snprintf(confname, sizeof(confname), "plugins/lighttable/collect/string%1d", i); gchar *text = dt_conf_get_string(confname); if(!text) break; snprintf(confname, sizeof(confname), "plugins/lighttable/collect/mode%1d", i); const int mode = dt_conf_get_int(confname); gchar *escaped_text = dt_util_str_replace(text, "'", "''"); get_query_string(property, escaped_text, query, sizeof(query)); if(i > 0) complete_query = dt_util_dstrcat(complete_query, " %s %s", conj[mode], query); else complete_query = dt_util_dstrcat(complete_query, "%s", query); g_free(escaped_text); g_free(text); } complete_query = dt_util_dstrcat(complete_query, ")"); // printf("complete query: `%s'\n", complete_query); /* set the extended where and the use of it in the query */ dt_collection_set_extended_where (collection, complete_query); dt_collection_set_query_flags (collection, (dt_collection_get_query_flags (collection) | COLLECTION_QUERY_USE_WHERE_EXT)); /* remove film id from default filter */ dt_collection_set_filter_flags (collection, (dt_collection_get_filter_flags (collection) & ~COLLECTION_FILTER_FILM_ID)); /* update query and at last the visual */ dt_collection_update (collection); /* free string */ g_free(complete_query); // remove from selected images where not in this query. sqlite3_stmt *stmt = NULL; const gchar *cquery = dt_collection_get_query(collection); complete_query = NULL; if(cquery && cquery[0] != '\0') { complete_query = dt_util_dstrcat(complete_query, "delete from selected_images where imgid not in (%s)", cquery); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), complete_query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); sqlite3_step(stmt); sqlite3_finalize(stmt); /* free allocated strings */ g_free(complete_query); } /* raise signal of collection change, only if this is an original */ if (!collection->clone) dt_control_signal_raise(darktable.signals, DT_SIGNAL_COLLECTION_CHANGED); }