Exemplo n.º 1
0
int32_t dt_image_duplicate(const int32_t imgid)
{
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "insert into images "
                              "(id, group_id, film_id, width, height, filename, maker, model, lens, exposure, "
                              "aperture, iso, focal_length, focus_distance, datetime_taken, flags, "
                              "output_width, output_height, crop, raw_parameters, raw_denoise_threshold, "
                              "raw_auto_bright_threshold, raw_black, raw_maximum, "
                              "caption, description, license, sha1sum, orientation, histogram, lightmap, "
                              "longitude, latitude, color_matrix, colorspace) "
                              "select null, group_id, film_id, width, height, filename, maker, model, lens, "
                              "exposure, aperture, iso, focal_length, focus_distance, datetime_taken, "
                              "flags, width, height, crop, raw_parameters, raw_denoise_threshold, "
                              "raw_auto_bright_threshold, raw_black, raw_maximum, "
                              "caption, description, license, sha1sum, orientation, histogram, lightmap, "
                              "longitude, latitude, color_matrix, colorspace "
                              "from images where id = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select a.id from images as a join images as b where "
                              "a.film_id = b.film_id and a.filename = b.filename and "
                              "b.id = ?1 order by a.id desc", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
  int32_t newid = -1;
  if(sqlite3_step(stmt) == SQLITE_ROW)
    newid = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);
  if(newid != -1)
  {
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "insert into color_labels (imgid, color) select ?1, color from "
                                "color_labels where imgid = ?2", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "insert into meta_data (id, key, value) select ?1, key, value "
                                "from meta_data where id = ?2", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "insert into tagged_images (imgid, tagid) select ?1, tagid from "
                                "tagged_images where imgid = ?2", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "update tagxtag set count = count + 1 where "
                                "(id1 in (select tagid from tagged_images where imgid = ?1)) or "
                                "(id2 in (select tagid from tagged_images where imgid = ?1))",
                                -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    if(darktable.gui && darktable.gui->grouping)
    {
      const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, newid);
      darktable.gui->expanded_group_id = img->group_id;
      dt_image_cache_read_release(darktable.image_cache, img);
      dt_collection_update_query(darktable.collection);
    }
  }
  return newid;
}
Exemplo n.º 2
0
/* do the real migration steps, returns the version the db was converted to */
static int _upgrade_schema_step(dt_database_t *db, int version)
{
  sqlite3_stmt *stmt;
  int new_version = version;
  if(version == CURRENT_DATABASE_VERSION)
    return version;
  else if(version == 0)
  {
    // this can't happen, we started with 1, but it's a good example how this function works
    // <do some magic to the db>
    new_version = 1; // the version we transformed the db to. this way it might be possible to roll back or add fast paths
  }
  else if(version == 1)
  {
    // 1 -> 2 added write_timestamp
    sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);
    if(sqlite3_exec(db->handle, "ALTER TABLE images ADD COLUMN write_timestamp INTEGER", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't add `write_timestamp' column to database\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    if(sqlite3_exec(db->handle, "UPDATE images SET write_timestamp = STRFTIME('%s', 'now') WHERE write_timestamp IS NULL", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't initialize `write_timestamp' with current point in time\n"); // let alone space
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
    new_version = 2;
  }
  else if(version == 2)
  {
    // 2 -> 3 reset raw_black and raw_maximum. in theory we should change the columns from REAL to INTEGER, but sqlite doesn't care about types so whatever
    sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);
    if(sqlite3_exec(db->handle, "UPDATE images SET raw_black = 0, raw_maximum = 16384", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't reset raw_black and raw_maximum\n"); // let alone space
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
    new_version = 3;
  }
  else if(version == 3)
  {
    sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);

    if (sqlite3_exec(db->handle,
                     "CREATE TRIGGER insert_tag AFTER INSERT ON tags"
                     " BEGIN"
                     "   INSERT INTO tagxtag SELECT id, new.id, 0 FROM TAGS;"
                     "   UPDATE tagxtag SET count = 1000000 WHERE id1=new.id AND id2=new.id;"
                     " END",
                     NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create insert_tag trigger\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    if (sqlite3_exec(db->handle,
                        "CREATE TRIGGER delete_tag BEFORE DELETE on tags"
                        " BEGIN"
                        "   DELETE FROM tagxtag WHERE id1=old.id OR id2=old.id;"
                        "   DELETE FROM tagged_images WHERE tagid=old.id;"
                        " END",
                        NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create delete_tag trigger\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    if (sqlite3_exec(db->handle,
                        "CREATE TRIGGER attach_tag AFTER INSERT ON tagged_images"
                        " BEGIN"
                        "   UPDATE tagxtag"
                        "     SET count = count + 1"
                        "     WHERE (id1=new.tagid AND id2 IN (SELECT tagid FROM tagged_images WHERE imgid=new.imgid))"
                        "        OR (id2=new.tagid AND id1 IN (SELECT tagid FROM tagged_images WHERE imgid=new.imgid));"
                        " END",
                        NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create attach_tag trigger\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }
    if (sqlite3_exec(db->handle,
                        "CREATE TRIGGER detach_tag BEFORE DELETE ON tagged_images"
                        " BEGIN"
                        "   UPDATE tagxtag"
                        "     SET count = count - 1"
                        "     WHERE (id1=old.tagid AND id2 IN (SELECT tagid FROM tagged_images WHERE imgid=old.imgid))"
                        "        OR (id2=old.tagid AND id1 IN (SELECT tagid FROM tagged_images WHERE imgid=old.imgid));"
                        " END",
                        NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create detach_tag trigger\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
    new_version = 4;
  }
  else if(version == 4)
  {
    sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);

    if (sqlite3_exec(db->handle,
                     "ALTER TABLE presets RENAME TO tmp_presets", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't rename table presets\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    if (sqlite3_exec(db->handle,
                     "CREATE TABLE presets (name VARCHAR, description VARCHAR, operation VARCHAR, op_params BLOB,"
                     "enabled INTEGER, blendop_params BLOB, model VARCHAR, maker VARCHAR, lens VARCHAR,"
                     "iso_min REAL, iso_max REAL, exposure_min REAL, exposure_max REAL, aperture_min REAL,"
                     "aperture_max REAL, focal_length_min REAL, focal_length_max REAL, writeprotect INTEGER,"
                     "autoapply INTEGER, filter INTEGER, def INTEGER, format INTEGER, op_version INTEGER,"
                     "blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256))",
                     NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create new presets table\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    if (sqlite3_exec(db->handle,
                     "INSERT INTO presets (name, description, operation, op_params, enabled, blendop_params, model, maker, lens,"
                     "                     iso_min, iso_max, exposure_min, exposure_max, aperture_min, aperture_max,"
                     "                     focal_length_min, focal_length_max, writeprotect, autoapply, filter, def, format,"
                     "                     op_version, blendop_version, multi_priority, multi_name)"
                     "              SELECT name, description, operation, op_params, enabled, blendop_params, model, maker, lens,"
                     "                     iso_min, iso_max, exposure_min, exposure_max, aperture_min, aperture_max,"
                     "                     focal_length_min, focal_length_max, writeprotect, autoapply, filter, def, isldr,"
                     "                     op_version, blendop_version, multi_priority, multi_name"
                     "              FROM   tmp_presets",
                     NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't populate presets table from tmp_presets\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    if (sqlite3_exec(db->handle,
                     "DROP TABLE tmp_presets", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't delete table tmp_presets\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
    new_version = 5;
  }
  else if(version == 5)
  {
    sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);

    if(sqlite3_exec(db->handle,
                      "CREATE INDEX images_filename_index ON images (filename)", NULL, NULL, NULL) != SQLITE_OK)
    {
      fprintf(stderr, "[init] can't create index on image filename\n");
      fprintf(stderr, "[init]   %s\n", sqlite3_errmsg(db->handle));
      sqlite3_exec(db->handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
      return version;
    }

    sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
    new_version = 6;
  }// maybe in the future, see commented out code elsewhere
//   else if(version == XXX)
//   {
//     sqlite3_exec(db->handle, "ALTER TABLE film_rolls ADD COLUMN external_drive VARCHAR(1024)", NULL, NULL, NULL);
//   }
  else
    new_version = version; // should be the fallback so that calling code sees that we are in an infinite loop

  // write the new version to db
  DT_DEBUG_SQLITE3_PREPARE_V2(db->handle, "INSERT OR REPLACE INTO db_info (key, value) VALUES ('version', ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, new_version);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  return new_version;
}
Exemplo n.º 3
0
int dt_film_import(const char *dirname)
{
  int rc;
  sqlite3_stmt *stmt;

  /* initialize a film object*/
  dt_film_t *film = (dt_film_t *)malloc(sizeof(dt_film_t));
  dt_film_init(film);
  film->id = -1;

  /* lookup if film exists and reuse id */
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from film_rolls where folder = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, strlen(dirname),
                             SQLITE_STATIC);
  if(sqlite3_step(stmt) == SQLITE_ROW)
    film->id = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);

  /* if we didn't find a id, lets instansiate a new filmroll */
  if(film->id <= 0)
  {
    char datetime[20];
    dt_gettime(datetime);
    /* insert a new film roll into database */
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "insert into film_rolls (id, datetime_accessed, folder) values "
                                "(null, ?1, ?2)", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, datetime, strlen(datetime),
                               SQLITE_STATIC);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dirname, strlen(dirname),
                               SQLITE_STATIC);

    rc = sqlite3_step(stmt);
    if(rc != SQLITE_DONE)
      fprintf(stderr, "[film_import] failed to insert film roll! %s\n",
              sqlite3_errmsg(dt_database_get(darktable.db)));
    sqlite3_finalize(stmt);

    /* requery for filmroll and fetch new id */
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "select id from film_rolls where folder=?1", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, dirname, strlen(dirname),
                               SQLITE_STATIC);
    if(sqlite3_step(stmt) == SQLITE_ROW)
      film->id = sqlite3_column_int(stmt, 0);
    sqlite3_finalize(stmt);
  }

  /* bail out if we got troubles */
  if(film->id <= 0)
  {
    // if the film is empty => remove it again.
    if(dt_film_is_empty(film->id))
    {
      dt_film_remove(film->id);
    }
    dt_film_cleanup(film);
    free(film);
    return 0;
  }

  /* at last put import film job on queue */
  dt_job_t j;
  film->last_loaded = 0;
  g_strlcpy(film->dirname, dirname, sizeof(film->dirname));
  film->dir = g_dir_open(film->dirname, 0, NULL);
  dt_film_import1_init(&j, film);
  dt_control_add_job(darktable.control, &j);

  return film->id;
}
Exemplo n.º 4
0
void
dt_styles_update (const char *name, const char *newname, const char *newdescription, GList *filter)
{
  sqlite3_stmt *stmt;
  int id=0;
  gchar *desc = NULL;
  
  id = dt_styles_get_id_by_name(name);
  if(id == 0) return;
  
  desc = dt_styles_get_description (name);
  
  if ((g_strcmp0(name, newname)) || (g_strcmp0(desc, newdescription)))
  {
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update styles set name=?1, description=?2 where rowid=?3", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, newname, strlen (newname), SQLITE_STATIC);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, newdescription, strlen (newdescription), SQLITE_STATIC);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
  }
  
  if (filter)
  {
    GList *list=filter;
    char tmp[64];
    char include[2048] = {0};
    g_strlcat(include,"num not in (", 2048);
    do
    {
      if(list!=g_list_first(list))
        g_strlcat(include, ",", 2048);
      sprintf(tmp, "%ld", (long int)list->data);
      g_strlcat(include, tmp, 2048);
    }
    while ((list=g_list_next(list)));
    g_strlcat(include,")", 2048);
    
    char query[4096]= {0};
    sprintf(query,"delete from style_items where styleid=?1 and %s", include);
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
  }
  
  /* backup style to disk */
  char stylesdir[1024];
  dt_loc_get_user_config_dir(stylesdir, 1024);
  g_strlcat(stylesdir,"/styles",1024);
  g_mkdir_with_parents(stylesdir,00755);
  
  dt_styles_save_to_file(newname,stylesdir,TRUE);
  
  /* delete old accelerator and create a new one */
  //TODO: sould better use dt_accel_rename_global() to keep the old accel_key untouched, but it seems to be buggy
  if (g_strcmp0(name, newname))
  {
    char tmp_accel[1024];
    snprintf(tmp_accel, 1024, "styles/Apply %s", name);
    dt_accel_deregister_global(tmp_accel);
  
    gchar* tmp_name = g_strdup(newname); // freed by _destro_style_shortcut_callback
    snprintf(tmp_accel, 1024, "styles/Apply %s", newname);
    dt_accel_register_global( tmp_accel, 0, 0);
    GClosure *closure;
    closure = g_cclosure_new(
        G_CALLBACK(_apply_style_shortcut_callback),
        tmp_name, _destroy_style_shortcut_callback);
    dt_accel_connect_global(tmp_accel, closure);
  }
  
  g_free(desc);
}
Exemplo n.º 5
0
void
dt_styles_apply_to_image(const char *name,gboolean duplicate, int32_t imgid)
{
  int id=0;
  sqlite3_stmt *stmt;

  if ((id=dt_styles_get_id_by_name(name)) != 0)
  {
    /* check if we should make a duplicate before applying style */
    if (duplicate)
      imgid = dt_image_duplicate (imgid);

    /* if merge onto history stack, lets find history offest in destination image */
    int32_t offs = 0;
#if 1
    {
      /* apply on top of history stack */
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(num) from history where imgid = ?1", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
      if (sqlite3_step (stmt) == SQLITE_ROW) offs = sqlite3_column_int (stmt, 0);
    }
#else
    {
      /* replace history stack */
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
      sqlite3_step (stmt);
    }
#endif
    sqlite3_finalize (stmt);

    /* copy history items from styles onto image */
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history (imgid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num+?2,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid=?3", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, offs);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id);
    sqlite3_step (stmt);
    sqlite3_finalize (stmt);

    /* add tag */
    guint tagid=0;
    gchar ntag[512]= {0};
    g_snprintf(ntag,512,"darktable|style|%s",name);
    if (dt_tag_new(ntag,&tagid))
      dt_tag_attach(tagid,imgid);

    /* if current image in develop reload history */
    if (dt_dev_is_current_image(darktable.develop, imgid))
    {
      dt_dev_reload_history_items (darktable.develop);
      dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop));
    }

    /* update xmp file */
    dt_image_synch_xmp(imgid);

    /* remove old obsolete thumbnails */
    dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);

    /* redraw center view to update visible mipmaps */
    dt_control_queue_redraw_center();
  }
}
Exemplo n.º 6
0
void init(dt_view_t *self)
{
  self->data = malloc(sizeof(dt_map_t));
  memset(self->data,0,sizeof(dt_map_t));

  dt_map_t *lib = (dt_map_t *)self->data;

  OsmGpsMapSource_t map_source = OSM_GPS_MAP_SOURCE_OPENSTREETMAP;
  const gchar *old_map_source = dt_conf_get_string("plugins/map/map_source");
  if(old_map_source && old_map_source[0] != '\0')
  {
    // find the number of the stored map_source
    for(int i=0; i<=OSM_GPS_MAP_SOURCE_LAST; i++)
    {
      const gchar *new_map_source = osm_gps_map_source_get_friendly_name(i);
      if(!g_strcmp0(old_map_source, new_map_source))
      {
        if(osm_gps_map_source_is_valid(i))
          map_source = i;
        break;
      }
    }
  }
  else // open street map should be a nice default ...
    dt_conf_set_string("plugins/map/map_source", osm_gps_map_source_get_friendly_name(OSM_GPS_MAP_SOURCE_OPENSTREETMAP));

  lib->map = g_object_new (OSM_TYPE_GPS_MAP,
                           "map-source", map_source,
                           "proxy-uri",g_getenv("http_proxy"),
                           NULL);

  GtkWidget *parent = gtk_widget_get_parent(dt_ui_center(darktable.gui->ui));
  gtk_box_pack_start(GTK_BOX(parent), GTK_WIDGET(lib->map) ,TRUE, TRUE, 0);

  lib->osd = g_object_new (OSM_TYPE_GPS_MAP_OSD,
                                        "show-scale",TRUE, "show-coordinates",TRUE, "show-dpad",TRUE, "show-zoom",TRUE, NULL);

  if(dt_conf_get_bool("plugins/map/show_map_osd"))
  {
    osm_gps_map_layer_add(OSM_GPS_MAP(lib->map), lib->osd);
  }

  /* build the query string */
  int max_images_drawn = dt_conf_get_int("plugins/map/max_images_drawn");
  if(max_images_drawn == 0)
    max_images_drawn = 100;
  char *geo_query = g_strdup_printf("select * from (select id from images where \
                              longitude >= ?1 and longitude <= ?2 and latitude <= ?3 and latitude >= ?4 \
                              and longitude not NULL and latitude not NULL order by abs(latitude - ?5), abs(longitude - ?6) \
                              limit 0, %d) order by id", max_images_drawn);

  /* prepare the main query statement */
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), geo_query, -1, &lib->statements.main_query, NULL);

  g_free(geo_query);

  /* allow drag&drop of images from filmstrip */
  gtk_drag_dest_set(GTK_WIDGET(lib->map), GTK_DEST_DEFAULT_ALL, target_list_internal, n_targets_internal, GDK_ACTION_COPY);
  g_signal_connect(GTK_WIDGET(lib->map), "drag-data-received", G_CALLBACK(drag_and_drop_received), self);
  g_signal_connect(GTK_WIDGET(lib->map), "changed", G_CALLBACK(_view_map_changed_callback), self);
  g_signal_connect(G_OBJECT(lib->map), "button-press-event", G_CALLBACK(_view_map_button_press_callback), self);
  g_signal_connect (G_OBJECT(lib->map), "motion-notify-event", G_CALLBACK(_view_map_motion_notify_callback), self);

  /* allow drag&drop of images from the map, too */
  g_signal_connect(GTK_WIDGET(lib->map), "drag-data-get", G_CALLBACK(_view_map_dnd_get_callback), self);
  g_signal_connect(GTK_WIDGET(lib->map), "drag-failed", G_CALLBACK(_view_map_dnd_failed_callback), self);
}
Exemplo n.º 7
0
int32_t dt_control_indexer_job_run(dt_job_t *job)
{
  // if no indexing was requested, bail out:
  if(!dt_conf_get_bool("run_similarity_indexer")) return 0;

  /*
   * First pass run thru ALL images and collect the ones who needs to update
   *  \TODO in the future lets have a indexer table with ids filed with images
   *  thats need some kind of reindexing.. all mark dirty functions adds image
   *  to this table--
   */
  // temp memory for uncompressed images:
  uint8_t *scratchmem = dt_mipmap_cache_alloc_scratchmem(darktable.mipmap_cache);

  GList *images=NULL;
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select images.id,film_rolls.folder||'/'||images.filename,images.histogram,images.lightmap from images,film_rolls where film_rolls.id = images.film_id", -1, &stmt, NULL);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    _control_indexer_img_t *idximg=g_malloc(sizeof( _control_indexer_img_t));
    memset(idximg,0,sizeof(_control_indexer_img_t));
    idximg->id = sqlite3_column_int(stmt,0);

    /* first check if image file exists on disk */
    const char *filename = (const char *)sqlite3_column_text(stmt, 1);
    if (filename && !g_file_test(filename, G_FILE_TEST_IS_REGULAR))
      idximg->flags |= _INDEXER_IMAGE_FILE_REMOVED;


    /* check if histogram should be updated */
    if (sqlite3_column_bytes(stmt, 2) != sizeof(dt_similarity_histogram_t))
      idximg->flags |= _INDEXER_UPDATE_HISTOGRAM;

    /* check if lightmap should be updated */
    if (sqlite3_column_bytes(stmt, 3) != sizeof(dt_similarity_lightmap_t))
      idximg->flags |= _INDEXER_UPDATE_LIGHTMAP;


    /* if image is flagged add to collection */
    if (idximg->flags != 0)
      images = g_list_append(images, idximg);
    else
      g_free(idximg);
  }
  sqlite3_finalize(stmt);


  /*
   * Second pass, run thru collected images thats
   *  need reindexing...
   */
  GList *imgitem = g_list_first(images);
  if(imgitem)
  {
    char message[512]= {0};
    double fraction=0;
    int total = g_list_length(images);

    guint *jid = NULL;

    /* background job plate only if more then one image is reindexed */
    if (total > 1)
    {
      snprintf(message, 512, ngettext ("re-indexing %d image", "re-indexing %d images", total), total );
      jid = (guint *)dt_control_backgroundjobs_create(darktable.control, 0, message);
    }

    do
    {
      // bail out if we're shutting down:
      if(!dt_control_running()) break;
      // if indexer was switched off during runtime, respect that as soon as we can:
      if(!dt_conf_get_bool("run_similarity_indexer")) break;

      /* get the _control_indexer_img_t pointer */
      _control_indexer_img_t *idximg = imgitem->data;

      /*
       * Check if image has been delete from disk
       */
      if ((idximg->flags&_INDEXER_IMAGE_FILE_REMOVED))
      {
        /* file does not exist on disk lets delete image reference from database */
        //char query[512]={0};

        // \TODO dont delete move to an temp table and let user to revalidate

        /*sprintf(query,"delete from history where imgid=%d",idximg->id);
          DT_DEBUG_SQLITE3_EXEC(darktable.db, query, NULL, NULL, NULL);
          sprintf(query,"delete from tagged_images where imgid=%d",idximg->id);
          DT_DEBUG_SQLITE3_EXEC(darktable.db, query, NULL, NULL, NULL);
          sprintf(query,"delete from images where id=%d",idximg->id);
          DT_DEBUG_SQLITE3_EXEC(darktable.db, query, NULL, NULL, NULL);*/

        /* no need to additional work */
        continue;
      }


      /*
       *  Check if image histogram or lightmap should be updated.
       *   those indexing that involves a image pipe should fall into this
       */
      if ( (idximg->flags&_INDEXER_UPDATE_HISTOGRAM) ||  (idximg->flags&_INDEXER_UPDATE_LIGHTMAP) )
      {
        /* get a mipmap of image to analyse */
        dt_mipmap_buffer_t buf;
        dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, idximg->id, DT_MIPMAP_2, DT_MIPMAP_BLOCKING);
        // pointer owned by the cache or == scratchmem, no need to free this one:
        uint8_t *buf_decompressed = dt_mipmap_cache_decompress(&buf, scratchmem);

        if (!(buf.width * buf.height))
          continue;

        /*
         * Generate similarity histogram data if requested
         */
        if ( (idximg->flags&_INDEXER_UPDATE_HISTOGRAM) )
        {
          dt_similarity_histogram_t histogram;
          float bucketscale = (float)DT_SIMILARITY_HISTOGRAM_BUCKETS/(float)0xff;
          for(int j=0; j<(4*buf.width*buf.height); j+=4)
          {
            /* swap rgb and scale to bucket index */
            uint8_t rgb[3];

            for(int k=0; k<3; k++)
              rgb[k] = (int)((buf_decompressed[j+2-k]/(float)0xff) * bucketscale);

            /* distribute rgb into buckets */
            for(int k=0; k<3; k++)
              histogram.rgbl[rgb[k]][k]++;

            /* distribute lum into buckets */
            uint8_t lum = MAX(MAX(rgb[0], rgb[1]), rgb[2]);
            histogram.rgbl[lum][3]++;
          }

          for(int k=0; k<DT_SIMILARITY_HISTOGRAM_BUCKETS; k++)
            for (int j=0; j<4; j++)
              histogram.rgbl[k][j] /= (buf.width*buf.height);

          /* store the histogram data */
          dt_similarity_histogram_store(idximg->id, &histogram);

        }

        /*
         * Generate scaledowned similarity lightness map if requested
         */
        if ( (idximg->flags&_INDEXER_UPDATE_LIGHTMAP) )
        {
          dt_similarity_lightmap_t lightmap;
          memset(&lightmap,0,sizeof(dt_similarity_lightmap_t));

          /*
           * create a pixbuf out of the image for downscaling
           */

          /* first of setup a standard rgb buffer, swap bgr in same routine */
          uint8_t *rgbbuf = g_malloc(buf.width*buf.height*3);
          for(int j=0; j<(buf.width*buf.height); j++)
            for(int k=0; k<3; k++)
              rgbbuf[3*j+k] = buf_decompressed[4*j+2-k];


          /* then create pixbuf and scale down to lightmap size */
          GdkPixbuf *source = gdk_pixbuf_new_from_data(rgbbuf,GDK_COLORSPACE_RGB,FALSE,8,buf.width,buf.height,(buf.width*3),NULL,NULL);
          GdkPixbuf *scaled = gdk_pixbuf_scale_simple(source,DT_SIMILARITY_LIGHTMAP_SIZE,DT_SIMILARITY_LIGHTMAP_SIZE,GDK_INTERP_HYPER);

          /* copy scaled data into lightmap */
          uint8_t min=0xff,max=0;
          uint8_t *spixels = gdk_pixbuf_get_pixels(scaled);

          for(int j=0; j<(DT_SIMILARITY_LIGHTMAP_SIZE*DT_SIMILARITY_LIGHTMAP_SIZE); j++)
          {
            /* copy rgb */
            for(int k=0; k<3; k++)
              lightmap.pixels[4*j+k] = spixels[3*j+k];

            /* average intensity into 4th channel */
            lightmap.pixels[4*j+3] =  (lightmap.pixels[4*j+0]+ lightmap.pixels[4*j+1]+ lightmap.pixels[4*j+2])/3.0;
            min = MIN(min, lightmap.pixels[4*j+3]);
            max = MAX(max, lightmap.pixels[4*j+3]);
          }

          /* contrast stretch each channel in lightmap
           *  TODO: do we want this...
           */
          float scale=0;
          int range = max-min;
          if(range==0)
            scale = 1.0;
          else
            scale = 0xff/range;
          for(int j=0; j<(DT_SIMILARITY_LIGHTMAP_SIZE*DT_SIMILARITY_LIGHTMAP_SIZE); j++)
          {
            for(int k=0; k<4; k++)
              lightmap.pixels[4*j+k] = (lightmap.pixels[4*j+k]-min)*scale;
          }

          /* free some resources */
          g_object_unref(scaled);
          g_object_unref(source);

          g_free(rgbbuf);

          /* store the lightmap */
          dt_similarity_lightmap_store(idximg->id, &lightmap);
        }


        /* no use for buffer anymore release the mipmap */
        dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf);

      }

      /* update background progress */
      if (jid)
      {
        fraction+=1.0/total;
        dt_control_backgroundjobs_progress(darktable.control, jid, fraction);
      }

    }
    while ((imgitem=g_list_next(imgitem)) && dt_control_job_get_state(job) != DT_JOB_STATE_CANCELLED);


    /* cleanup */
    if (jid)
      dt_control_backgroundjobs_destroy(darktable.control, jid);
  }

  free(scratchmem);

  /*
   * Indexing opertions finished, lets reschedule the indexer
   * unless control is shutting down...
   */
  if(dt_control_running())
    dt_control_start_indexer();

  return 0;
}
Exemplo n.º 8
0
static void
edit_preset (const char *name_in, dt_lib_module_info_t *minfo)
{
  gchar *name = NULL;
  if(name_in == NULL)
  {
    name = get_active_preset_name(minfo);
    if(name == NULL) return;
  }
  else name = g_strdup(name_in);

  GtkWidget *dialog;
  /* Create the widgets */
  char title[1024];
  GtkWidget *window = dt_ui_main_window(darktable.gui->ui);
  snprintf(title, 1024, _("edit `%s'"), name);
  dialog = gtk_dialog_new_with_buttons (title,
                                        GTK_WINDOW(window),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
                                        NULL);
  GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
  GtkWidget *alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 5, 5, 5);
  gtk_container_add (content_area, alignment);
  GtkBox *box = GTK_BOX(gtk_vbox_new(FALSE, 5));
  gtk_container_add (GTK_CONTAINER(alignment), GTK_WIDGET(box));

  dt_lib_presets_edit_dialog_t *g = (dt_lib_presets_edit_dialog_t *)g_malloc0(sizeof(dt_lib_presets_edit_dialog_t));
  g->old_id = -1;
  g_strlcpy(g->plugin_name, minfo->plugin_name, 128);
  g->version = minfo->version;
  g->params_size = minfo->params_size;
  g->params = minfo->params;
  g->name = GTK_ENTRY(gtk_entry_new());
  g->module = minfo->module;
  g->original_name = name;
  gtk_entry_set_text(g->name, name);
  gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0);
  g_object_set(G_OBJECT(g->name), "tooltip-text", _("name of the preset"), (char *)NULL);

  g->description = GTK_ENTRY(gtk_entry_new());
  gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0);
  g_object_set(G_OBJECT(g->description), "tooltip-text", _("description or further information"), (char *)NULL);

  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select rowid, description from presets where name = ?1 and operation = ?2 and op_version = ?3", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, strlen(name), SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, minfo->plugin_name, strlen(minfo->plugin_name), SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, minfo->version);
  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    g->old_id = sqlite3_column_int(stmt, 0);
    gtk_entry_set_text(g->description, (const char *)sqlite3_column_text(stmt, 1));
  }
  sqlite3_finalize(stmt);

  g_signal_connect (dialog, "response", G_CALLBACK (edit_preset_response), g);
  gtk_widget_show_all (dialog);
}
Exemplo n.º 9
0
static void
dt_lib_presets_popup_menu_show(dt_lib_module_info_t *minfo)
{
  GtkMenu *menu = darktable.gui->presets_popup_menu;
  if(menu)
    gtk_widget_destroy(GTK_WIDGET(menu));
  darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new());
  menu = darktable.gui->presets_popup_menu;

  GtkWidget *mi;
  int active_preset = -1, cnt = 0, writeprotect = 0;
  sqlite3_stmt *stmt;
  // order: get shipped defaults first
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, description from presets where operation=?1 and op_version=?2 order by writeprotect desc, rowid", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, minfo->plugin_name, strlen(minfo->plugin_name), SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, minfo->version);

  // collect all presets for op from db
  int found = 0;
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    void *op_params = (void *)sqlite3_column_blob(stmt, 1);
    int32_t op_params_size = sqlite3_column_bytes(stmt, 1);
    const char *name = (char *)sqlite3_column_text(stmt, 0);

    if (darktable.gui->last_preset
        && strcmp(darktable.gui->last_preset, name)==0)
      found = 1;

    // selected in bold:
    // printf("comparing %d bytes to %d\n", op_params_size, minfo->params_size);
    // for(int k=0;k<op_params_size && !memcmp(minfo->params, op_params, k);k++) printf("compare [%c %c] %d: %d\n",
    // ((const char*)(minfo->params))[k],
    // ((const char*)(op_params))[k],
    // k, memcmp(minfo->params, op_params, k));
    if(op_params_size == minfo->params_size && !memcmp(minfo->params, op_params, op_params_size))
    {
      active_preset = cnt;
      writeprotect = sqlite3_column_int(stmt, 2);
      char *markup;
      mi = gtk_menu_item_new_with_label("");
      markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>", name);
      gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child(GTK_BIN(mi))), markup);
      g_free (markup);
    }
    else
    {
      mi = gtk_menu_item_new_with_label((const char *)name);
    }
    g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), minfo);
    g_object_set(G_OBJECT(mi), "tooltip-text", sqlite3_column_text(stmt, 3), (char *)NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
    cnt ++;
  }
  sqlite3_finalize(stmt);

  if(cnt > 0)
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());

  // FIXME: this doesn't seem to work.
  if(active_preset >= 0)
  {
    if(!writeprotect)
    {
      mi = gtk_menu_item_new_with_label(_("edit this preset.."));
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_edit_preset), minfo);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);

      mi = gtk_menu_item_new_with_label(_("delete this preset"));
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_delete_preset), minfo);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
    }
  }
  else
  {
    mi = gtk_menu_item_new_with_label(_("store new preset.."));
    g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_new_preset), minfo);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);

    if (darktable.gui->last_preset && found)
    {
      char label[60];
      strcpy (label, _("update preset"));
      strcat (label, " <span weight=\"bold\">%s</span>");
      char *markup = g_markup_printf_escaped (label, darktable.gui->last_preset);
      mi = gtk_menu_item_new_with_label("");
      gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child(GTK_BIN(mi))), markup);
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_update_preset), minfo);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
      g_free (markup);
    }
  }
}
Exemplo n.º 10
0
void dt_image_cache_allocate(void *data, dt_cache_entry_t *entry)
{
  entry->cost = sizeof(dt_image_t);

  dt_image_t *img = (dt_image_t *)g_malloc(sizeof(dt_image_t));
  dt_image_init(img);
  entry->data = img;
  // load stuff from db and store in cache:
  char *str;
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(
      dt_database_get(darktable.db),
      "SELECT id, group_id, film_id, width, height, filename, maker, model, lens, exposure, "
      "aperture, iso, focal_length, datetime_taken, flags, crop, orientation, focus_distance, "
      "raw_parameters, longitude, latitude, color_matrix, colorspace, version, raw_black, raw_maximum FROM "
      "images WHERE id = ?1",
      -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, entry->key);
  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    img->id = sqlite3_column_int(stmt, 0);
    img->group_id = sqlite3_column_int(stmt, 1);
    img->film_id = sqlite3_column_int(stmt, 2);
    img->width = sqlite3_column_int(stmt, 3);
    img->height = sqlite3_column_int(stmt, 4);
    img->crop_x = img->crop_y = img->crop_width = img->crop_height = 0;
    img->filename[0] = img->exif_maker[0] = img->exif_model[0] = img->exif_lens[0]
        = img->exif_datetime_taken[0] = '\0';
    str = (char *)sqlite3_column_text(stmt, 5);
    if(str) g_strlcpy(img->filename, str, sizeof(img->filename));
    str = (char *)sqlite3_column_text(stmt, 6);
    if(str) g_strlcpy(img->exif_maker, str, sizeof(img->exif_maker));
    str = (char *)sqlite3_column_text(stmt, 7);
    if(str) g_strlcpy(img->exif_model, str, sizeof(img->exif_model));
    str = (char *)sqlite3_column_text(stmt, 8);
    if(str) g_strlcpy(img->exif_lens, str, sizeof(img->exif_lens));
    img->exif_exposure = sqlite3_column_double(stmt, 9);
    img->exif_aperture = sqlite3_column_double(stmt, 10);
    img->exif_iso = sqlite3_column_double(stmt, 11);
    img->exif_focal_length = sqlite3_column_double(stmt, 12);
    str = (char *)sqlite3_column_text(stmt, 13);
    if(str) g_strlcpy(img->exif_datetime_taken, str, sizeof(img->exif_datetime_taken));
    img->flags = sqlite3_column_int(stmt, 14);
    img->exif_crop = sqlite3_column_double(stmt, 15);
    img->orientation = sqlite3_column_int(stmt, 16);
    img->exif_focus_distance = sqlite3_column_double(stmt, 17);
    if(img->exif_focus_distance >= 0 && img->orientation >= 0) img->exif_inited = 1;
    uint32_t tmp = sqlite3_column_int(stmt, 18);
    memcpy(&img->legacy_flip, &tmp, sizeof(dt_image_raw_parameters_t));
    if(sqlite3_column_type(stmt, 19) == SQLITE_FLOAT)
      img->longitude = sqlite3_column_double(stmt, 19);
    else
      img->longitude = NAN;
    if(sqlite3_column_type(stmt, 20) == SQLITE_FLOAT)
      img->latitude = sqlite3_column_double(stmt, 20);
    else
      img->latitude = NAN;
    const void *color_matrix = sqlite3_column_blob(stmt, 21);
    if(color_matrix)
      memcpy(img->d65_color_matrix, color_matrix, sizeof(img->d65_color_matrix));
    else
      img->d65_color_matrix[0] = NAN;
    g_free(img->profile);
    img->profile = NULL;
    img->profile_size = 0;
    img->colorspace = sqlite3_column_int(stmt, 22);
    img->version = sqlite3_column_int(stmt, 23);
    img->raw_black_level = sqlite3_column_int(stmt, 24);
    for(uint8_t i = 0; i < 4; i++) img->raw_black_level_separate[i] = 0;
    img->raw_white_point = sqlite3_column_int(stmt, 25);

    // buffer size?
    if(img->flags & DT_IMAGE_LDR)
      img->bpp = 4 * sizeof(float);
    else if(img->flags & DT_IMAGE_HDR)
    {
      if(img->flags & DT_IMAGE_RAW)
        img->bpp = sizeof(float);
      else
        img->bpp = 4 * sizeof(float);
    }
    else // raw
      img->bpp = sizeof(uint16_t);
  }
  else
  {
    img->id = -1;
    fprintf(stderr, "[image_cache_allocate] failed to open image %d from database: %s\n", entry->key,
            sqlite3_errmsg(dt_database_get(darktable.db)));
  }
  sqlite3_finalize(stmt);
  img->cache_entry = entry; // init backref
  // could downgrade lock write->read on entry->lock if we were using concurrencykit..
}
Exemplo n.º 11
0
static void
edit_preset_response(GtkDialog *dialog, gint response_id, dt_lib_presets_edit_dialog_t *g)
{
  gint dlg_ret;
  gint is_new = 0;

  if(response_id == GTK_RESPONSE_ACCEPT)
  {
    sqlite3_stmt *stmt;

    // now delete preset, so we can re-insert the new values:
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, g->original_name, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if ( ((g->old_id >= 0) && (strcmp(g->original_name, gtk_entry_get_text(g->name)) != 0)) || (g->old_id < 0) )
    {

      // editing existing preset with different name or store new preset -> check for a preset with the same name:

      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name from presets where name = ?1 and operation=?2 and op_version=?3", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT);
      DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version);

      if(sqlite3_step(stmt) == SQLITE_ROW)
      {
        sqlite3_finalize(stmt);

        GtkWidget *window = dt_ui_main_window(darktable.gui->ui);
        GtkWidget *dlg_overwrite = gtk_message_dialog_new (GTK_WINDOW(window),
                                   GTK_DIALOG_DESTROY_WITH_PARENT,
                                   GTK_MESSAGE_WARNING,
                                   GTK_BUTTONS_YES_NO,
                                   _("preset `%s' already exists.\ndo you want to overwrite?"),
                                   gtk_entry_get_text(g->name)
                                                          );
        gtk_window_set_title(GTK_WINDOW (dlg_overwrite), _("overwrite preset?"));
        dlg_ret = gtk_dialog_run (GTK_DIALOG (dlg_overwrite));
        gtk_widget_destroy (dlg_overwrite);

        // if result is BUTTON_NO exit without destroy dialog, to permit other name
        if (dlg_ret == GTK_RESPONSE_NO) return;
      }
      else
      {
        is_new = 1;
        sqlite3_finalize(stmt);
      }

    }

    if (is_new == 0)
    {
      // delete preset, so we can re-insert the new values:
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from presets where name=?1 and operation=?2 and op_version=?3", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT);
      DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->version);
      sqlite3_step(stmt);
      sqlite3_finalize(stmt);
    }


    // commit all the user input fields
    char path[1024];
    snprintf(path,1024,"preset/%s",g->original_name);
    dt_accel_rename_preset_lib(g->module,path,gtk_entry_get_text(g->name));
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into presets (name, description, operation, op_version, op_params, blendop_params, blendop_version, enabled, model, maker, lens, "
                                "iso_min, iso_max, exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, focal_length_max, writeprotect, "
                                "autoapply, filter, def, isldr) values (?1, ?2, ?3, ?4, ?5, null, 0, 1, '%', '%', '%', 0, 51200, 0, 100000000, 0, 100000000, 0, 1000, 0, 0, 0, 0, 0)", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, gtk_entry_get_text(g->name), strlen(gtk_entry_get_text(g->name)), SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, gtk_entry_get_text(g->description), strlen(gtk_entry_get_text(g->description)), SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, g->plugin_name, strlen(g->plugin_name), SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, g->version);
    DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 5, g->params, g->params_size, SQLITE_TRANSIENT);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    dt_gui_store_last_preset (gtk_entry_get_text(g->name));
  }
  gtk_widget_destroy(GTK_WIDGET(dialog));
  g_free(g->original_name);
  free(g);
}
Exemplo n.º 12
0
int32_t dt_image_copy(const int32_t imgid, const int32_t filmid)
{
  int32_t newid = -1;
  sqlite3_stmt *stmt;
  gchar srcpath[DT_MAX_PATH_LEN] = {0};
  gchar *newdir = NULL;

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select folder from film_rolls where id = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid);
  if(sqlite3_step(stmt) == SQLITE_ROW)
    newdir = g_strdup((gchar *) sqlite3_column_text(stmt, 0));
  sqlite3_finalize(stmt);

  if(newdir)
  {
    dt_image_full_path(imgid, srcpath, DT_MAX_PATH_LEN);
    gchar *imgbname = g_path_get_basename(srcpath);
    gchar *destpath = g_build_filename(newdir, imgbname, NULL);
    GFile *src = g_file_new_for_path(srcpath);
    GFile *dest = g_file_new_for_path(destpath);
    g_free(imgbname);
    imgbname = NULL;
    g_free(newdir);
    newdir = NULL;
    g_free(destpath);
    destpath = NULL;

    // copy image to new folder
    // if image file already exists, continue
    GError *gerror = NULL;
    g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &gerror);

    if((gerror == NULL) || (gerror != NULL && gerror->code == G_IO_ERROR_EXISTS))
    {
      // update database
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                  "insert into images "
                                  "(id, group_id, film_id, width, height, filename, maker, model, lens, exposure, "
                                  "aperture, iso, focal_length, focus_distance, datetime_taken, flags, "
                                  "output_width, output_height, crop, raw_parameters, raw_denoise_threshold, "
                                  "raw_auto_bright_threshold, raw_black, raw_maximum, "
                                  "caption, description, license, sha1sum, orientation, histogram, lightmap, "
                                  "longitude, latitude, color_matrix, colorspace) "
                                  "select null, group_id, ?1 as film_id, width, height, filename, maker, model, lens, "
                                  "exposure, aperture, iso, focal_length, focus_distance, datetime_taken, "
                                  "flags, width, height, crop, raw_parameters, raw_denoise_threshold, "
                                  "raw_auto_bright_threshold, raw_black, raw_maximum, "
                                  "caption, description, license, sha1sum, orientation, histogram, lightmap, "
                                  "longitude, latitude, color_matrix, colorspace "
                                  "from images where id = ?2", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
      sqlite3_step(stmt);
      sqlite3_finalize(stmt);
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                  "select a.id from images as a join images as b where "
                                  "a.film_id = ?1 and a.filename = b.filename and "
                                  "b.id = ?2 order by a.id desc", -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);

      if(sqlite3_step(stmt) == SQLITE_ROW)
        newid = sqlite3_column_int(stmt, 0);
      sqlite3_finalize(stmt);

      if(newid != -1)
      {
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                    "insert into color_labels (imgid, color) select ?1, color from "
                                    "color_labels where imgid = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                    "insert into meta_data (id, key, value) select ?1, key, value "
                                    "from meta_data where id = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                    "insert into tagged_images (imgid, tagid) select ?1, tagid from "
                                    "tagged_images where imgid = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                    "update tagxtag set count = count + 1 where "
                                    "(id1 in (select tagid from tagged_images where imgid = ?1)) or "
                                    "(id2 in (select tagid from tagged_images where imgid = ?1))",
                                    -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);

        // write xmp file
        dt_image_write_sidecar_file(newid);
      }
    }
    else
    {
      fprintf(stderr, "Failed to copy image %s: %s\n", srcpath, gerror->message);
    }
    g_object_unref(dest);
    g_object_unref(src);
    g_clear_error(&gerror);
  }

  return newid;
}
Exemplo n.º 13
0
int32_t dt_image_move(const int32_t imgid, const int32_t filmid)
{
  //TODO: several places where string truncation could occur unnoticed
  int32_t result = -1;
  gchar oldimg[DT_MAX_PATH_LEN] = {0};
  gchar newimg[DT_MAX_PATH_LEN] = {0};
  dt_image_full_path(imgid, oldimg, DT_MAX_PATH_LEN);
  gchar *newdir = NULL;

  sqlite3_stmt *film_stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select folder from film_rolls where id = ?1", -1, &film_stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(film_stmt, 1, filmid);
  if(sqlite3_step(film_stmt) == SQLITE_ROW)
    newdir = g_strdup((gchar *) sqlite3_column_text(film_stmt, 0));
  sqlite3_finalize(film_stmt);

  if(newdir)
  {
    gchar *imgbname = g_path_get_basename(oldimg);
    g_snprintf(newimg, DT_MAX_PATH_LEN, "%s%c%s", newdir, G_DIR_SEPARATOR, imgbname);
    g_free(imgbname);
    g_free(newdir);

    // statement for getting ids of the image to be moved and it's duplicates
    sqlite3_stmt *duplicates_stmt;
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "select id from images where filename in (select filename from images "
                                "where id = ?1) and film_id in (select film_id from images where id = ?1)",
                                -1, &duplicates_stmt, NULL);

    // move image
    // TODO: Use gio's' g_file_move instead of g_rename?
    if (!g_file_test(newimg, G_FILE_TEST_EXISTS)
        && (g_rename(oldimg, newimg) == 0))
    {
      // first move xmp files of image and duplicates
      GList *dup_list = NULL;
      DT_DEBUG_SQLITE3_BIND_INT(duplicates_stmt, 1, imgid);
      while (sqlite3_step(duplicates_stmt) == SQLITE_ROW)
      {
        int32_t id = sqlite3_column_int(duplicates_stmt, 0);
        dup_list = g_list_append(dup_list, GINT_TO_POINTER(id));
        gchar oldxmp[512], newxmp[512];
        g_strlcpy(oldxmp, oldimg, 512);
        g_strlcpy(newxmp, newimg, 512);
        dt_image_path_append_version(id, oldxmp, 512);
        dt_image_path_append_version(id, newxmp, 512);
        g_strlcat(oldxmp, ".xmp", 512);
        g_strlcat(newxmp, ".xmp", 512);
        if (g_file_test(oldxmp, G_FILE_TEST_EXISTS))
          (void)g_rename(oldxmp, newxmp);
      }
      sqlite3_reset(duplicates_stmt);
      sqlite3_clear_bindings(duplicates_stmt);

      // then update database and cache
      // if update was performed in above loop, dt_image_path_append_version()
      // would return wrong version!
      while (dup_list)
      {
        long int id = GPOINTER_TO_INT(dup_list->data);
        const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id);
        dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
        img->film_id = filmid;
        // write through to db, but not to xmp
        dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
        dt_image_cache_read_release(darktable.image_cache, img);
        dup_list = g_list_delete_link(dup_list, dup_list);
      }
      g_list_free(dup_list);
      result = 0;
    }
  }

  return result;
}
Exemplo n.º 14
0
uint32_t dt_image_import(const int32_t film_id, const char *filename, gboolean override_ignore_jpegs)
{
  if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
    return 0;
  const char *cc = filename + strlen(filename);
  for(; *cc!='.'&&cc>filename; cc--);
  if(!strcmp(cc, ".dt")) return 0;
  if(!strcmp(cc, ".dttags")) return 0;
  if(!strcmp(cc, ".xmp")) return 0;
  char *ext = g_ascii_strdown(cc+1, -1);
  if(override_ignore_jpegs == FALSE && (!strcmp(ext, "jpg") ||
                                        !strcmp(ext, "jpeg")) && dt_conf_get_bool("ui_last/import_ignore_jpegs"))
    return 0;
  int supported = 0;
  char **extensions = g_strsplit(dt_supported_extensions, ",", 100);
  for(char **i=extensions; *i!=NULL; i++)
    if(!strcmp(ext, *i))
    {
      supported = 1;
      break;
    }
  g_strfreev(extensions);
  if(!supported)
  {
    g_free(ext);
    return 0;
  }
  int rc;
  uint32_t id = 0;
  // select from images; if found => return
  gchar *imgfname;
  imgfname = g_path_get_basename((const gchar*)filename);
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from images where film_id = ?1 and filename = ?2",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC);
  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    id = sqlite3_column_int(stmt, 0);
    g_free(imgfname);
    sqlite3_finalize(stmt);
    g_free(ext);
    const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id);
    dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
    img->flags &= ~DT_IMAGE_REMOVE;
    dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
    dt_image_cache_read_release(darktable.image_cache, img);
    return id;
  }
  sqlite3_finalize(stmt);

  // also need to set the no-legacy bit, to make sure we get the right presets (new ones)
  uint32_t flags = dt_conf_get_int("ui_last/import_initial_rating");
  if(flags > 5)
  {
    flags = 1;
    dt_conf_set_int("ui_last/import_initial_rating", 1);
  }
  flags |= DT_IMAGE_NO_LEGACY_PRESETS;
  // insert dummy image entry in database
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "insert into images (id, film_id, filename, caption, description, "
                              "license, sha1sum, flags) values (null, ?1, ?2, '', '', '', '', ?3)",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname),
                             SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, flags);
  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) fprintf(stderr, "sqlite3 error %d\n", rc);
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from images where film_id = ?1 and filename = ?2",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname),
                             SQLITE_STATIC);
  if(sqlite3_step(stmt) == SQLITE_ROW) id = sqlite3_column_int(stmt, 0);
  sqlite3_finalize(stmt);

  // Try to find out if this should be grouped already.
  gchar *basename = g_strdup(imgfname);
  gchar *cc2 = basename + strlen(basename);
  for(; *cc2!='.'&&cc2>basename; cc2--);
  *cc2='\0';
  gchar *sql_pattern = g_strconcat(basename, ".%", NULL);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select group_id from images where film_id = ?1 and filename like ?2 and id != ?3", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, sql_pattern, -1, SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id);
  int group_id;
  if(sqlite3_step(stmt) == SQLITE_ROW) group_id = sqlite3_column_int(stmt, 0);
  else                                 group_id = id;
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update images set group_id = ?1 where id = ?2", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, group_id);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  // printf("[image_import] importing `%s' to img id %d\n", imgfname, id);

  // lock as shortly as possible:
  const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id);
  dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
  img->group_id = group_id;

  // read dttags and exif for database queries!
  (void) dt_exif_read(img, filename);
  char dtfilename[DT_MAX_PATH_LEN];
  g_strlcpy(dtfilename, filename, DT_MAX_PATH_LEN);
  dt_image_path_append_version(id, dtfilename, DT_MAX_PATH_LEN);
  char *c = dtfilename + strlen(dtfilename);
  sprintf(c, ".xmp");
  (void)dt_exif_xmp_read(img, dtfilename, 0);

  // write through to db, but not to xmp.
  dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
  dt_image_cache_read_release(darktable.image_cache, img);

  // add a tag with the file extension
  guint tagid = 0;
  char tagname[512];
  snprintf(tagname, 512, "darktable|format|%s", ext);
  g_free(ext);
  dt_tag_new(tagname, &tagid);
  dt_tag_attach(tagid,id);

  // Search for sidecar files and import them if found.
  glob_t *globbuf = g_malloc(sizeof(glob_t));

  // Add version wildcard
  gchar *fname = g_strdup(filename);
  gchar pattern[DT_MAX_PATH_LEN];
  g_snprintf(pattern, DT_MAX_PATH_LEN, "%s", filename);
  char *c1 = pattern + strlen(pattern);
  while(*c1 != '.' && c1 > pattern) c1--;
  snprintf(c1, pattern + DT_MAX_PATH_LEN - c1, "_*");
  char *c2 = fname + strlen(fname);
  while(*c2 != '.' && c2 > fname) c2--;
  snprintf(c1+2, pattern + DT_MAX_PATH_LEN - c1 - 2, "%s.xmp", c2);

  if (!glob(pattern, 0, NULL, globbuf))
  {
    for (int i=0; i < globbuf->gl_pathc; i++)
    {
      int newid = -1;
      newid = dt_image_duplicate(id);

      const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, newid);
      dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg);
      (void)dt_exif_xmp_read(img, globbuf->gl_pathv[i], 0);
      dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED);
      dt_image_cache_read_release(darktable.image_cache, img);
    }
    globfree(globbuf);
  }

  g_free(imgfname);
  g_free(fname);
  g_free(basename);
  g_free(sql_pattern);
  g_free(globbuf);

  dt_control_signal_raise(darktable.signals,DT_SIGNAL_IMAGE_IMPORT,id);
  return id;
}
Exemplo n.º 15
0
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, 200, "plugins/lighttable/collect/item%1d", i);
    const int property = dt_conf_get_int(confname);
    snprintf(confname, 200, "plugins/lighttable/collect/string%1d", i);
    gchar *text = dt_conf_get_string(confname);
    if(!text) break;
    snprintf(confname, 200, "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);

    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);

}
Exemplo n.º 16
0
// FIXME: we can't rely on darktable to avoid file overwriting -- it doesn't know the filename (extension).
int write_image(dt_imageio_module_data_t *ppm, const char *filename, const void *in, void *exif, int exif_len,
                int imgid, int num, int total)
{
  int status = 1;
  char *sourcefile = NULL;
  char *targetfile = NULL;
  char *xmpfile = NULL;
  char *content = NULL;
  FILE *fin = NULL;
  FILE *fout = NULL;
  sqlite3_stmt *stmt;

  DT_DEBUG_SQLITE3_PREPARE_V2(
      dt_database_get(darktable.db),
      "select folder, filename from images, film_rolls where images.id = ?1 and film_id = film_rolls.id;", -1,
      &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);

  if(sqlite3_step(stmt) != SQLITE_ROW) goto END;

  const char *sfolder = (char *)sqlite3_column_text(stmt, 0);
  const char *sfilename = (char *)sqlite3_column_text(stmt, 1);
  sourcefile = g_build_filename(sfolder, sfilename, NULL);
  char *extension = g_strrstr(sourcefile, ".");
  if(extension == NULL) goto END;
  targetfile = g_strconcat(filename, ++extension, NULL);

  if(!strcmp(sourcefile, targetfile)) goto END;

  fin = fopen(sourcefile, "rb");
  fout = fopen(targetfile, "wb");
  if(fin == NULL || fout == NULL) goto END;

  fseek(fin, 0, SEEK_END);
  size_t end = ftell(fin);
  rewind(fin);

  content = (char *)g_malloc_n(end, sizeof(char));
  if(content == NULL) goto END;
  if(fread(content, sizeof(char), end, fin) != end) goto END;
  if(fwrite(content, sizeof(char), end, fout) != end) goto END;

  // we got a copy of the file, now write the xmp data
  xmpfile = g_strconcat(targetfile, ".xmp", NULL);
  if(dt_exif_xmp_write(imgid, xmpfile) != 0)
  {
    // something went wrong, unlink the copied image.
    g_unlink(targetfile);
    goto END;
  }

  status = 0;
END:
  sqlite3_finalize(stmt);
  g_free(sourcefile);
  g_free(targetfile);
  g_free(xmpfile);
  g_free(content);
  if(fin) fclose(fin);
  if(fout) fclose(fout);
  return status;
}
Exemplo n.º 17
0
int32_t dt_control_remove_images_job_run(dt_job_t *job)
{
  long int imgid = -1;
  dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param;
  GList *t = t1->index;
  int total = g_list_length(t);
  char message[512]= {0};
  double fraction=0;
  snprintf(message, 512, ngettext ("removing %d image", "removing %d images", total), total );
  const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message);
  sqlite3_stmt *stmt = NULL;

  // check that we can safely remove the image
  char query[1024];
  gboolean remove_ok = TRUE;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT id FROM images WHERE id IN (SELECT imgid FROM selected_images) AND flags&?1=?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, DT_IMAGE_LOCAL_COPY);

  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    int imgid = sqlite3_column_int(stmt, 0);
    if (!dt_image_safe_remove(imgid))
    {
      remove_ok = FALSE;
      break;
    }
  }
  sqlite3_finalize(stmt);

  if (!remove_ok)
  {
    dt_control_log(_("cannot remove local copy when the original file is not accessible."));
    dt_control_backgroundjobs_destroy(darktable.control, jid);
    return 0;
  }

  // update remove status
  sprintf(query, "update images set flags = (flags | %d) where id in (select imgid from selected_images)",DT_IMAGE_REMOVE);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), query, NULL, NULL, NULL);

  dt_collection_update(darktable.collection);

  // We need a list of files to regenerate .xmp files if there are duplicates
  GList *list = NULL;

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select distinct folder || '/' || filename from images, film_rolls where images.film_id = film_rolls.id and images.id in (select imgid from selected_images)", -1, &stmt, NULL);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    list = g_list_append(list, g_strdup((const gchar *)sqlite3_column_text(stmt, 0)));
  }
  sqlite3_finalize(stmt);

  while(t)
  {
    imgid = (long int)t->data;
    dt_image_remove(imgid);
    t = g_list_delete_link(t, t);
    fraction=1.0/total;
    dt_control_backgroundjobs_progress(darktable.control, jid, fraction);
  }

  char *imgname;
  while(list)
  {
    imgname = (char *)list->data;
    dt_image_synch_all_xmp(imgname);
    list = g_list_delete_link(list, list);
  }
  dt_control_backgroundjobs_destroy(darktable.control, jid);
  dt_film_remove_empty();
  dt_control_queue_redraw_center();
  return 0;
}
Exemplo n.º 18
0
void dt_collection_get_makermodel(const gchar *filter, GList **sanitized, GList **exif)
{
  sqlite3_stmt *stmt;
  gchar *needle = NULL;

  GHashTable *names = NULL;
  if (sanitized)
    names = g_hash_table_new(g_str_hash, g_str_equal);

  if (filter && filter[0] != '\0')
    needle = g_utf8_strdown(filter, -1);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select maker, model from images group by maker, model",
                              -1, &stmt, NULL);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    char *exif_maker = (char *)sqlite3_column_text(stmt, 0);
    char *exif_model = (char *)sqlite3_column_text(stmt, 1);

    char maker[64];
    char model[64];
    char alias[64];
    maker[0] = model[0] = alias[0] = '\0';
    dt_rawspeed_lookup_makermodel(exif_maker, exif_model,
                                  maker, sizeof(maker),
                                  model, sizeof(model),
                                  alias, sizeof(alias));

    // Create the makermodel by concatenation
    char makermodel[128];
    g_strlcpy(makermodel, maker, sizeof(makermodel));
    int maker_len = strlen(maker);
    makermodel[maker_len] = ' ';
    g_strlcpy(makermodel+maker_len+1, model, sizeof(makermodel)-maker_len-1);

    gchar *haystack = g_utf8_strdown(makermodel, -1);
    if (!needle || g_strrstr(haystack, needle) != NULL)
    {
      if (exif)
      {
        // Append a two element list with maker and model
        GList *inner_list = NULL;
        inner_list = g_list_append(inner_list, g_strdup(exif_maker));
        inner_list = g_list_append(inner_list, g_strdup(exif_model));
        *exif = g_list_append(*exif, inner_list);
      }

      if (sanitized)
      {
        gchar *key = g_strdup(makermodel);
        g_hash_table_add(names, key);
      }
    }
    g_free(haystack);
  }
  sqlite3_finalize(stmt);
  if(needle)
    g_free(needle);

  if(sanitized)
  {
    *sanitized = g_list_sort(g_hash_table_get_keys(names), (GCompareFunc) strcmp);
    g_hash_table_destroy(names);
  }
}
Exemplo n.º 19
0
int32_t dt_control_delete_images_job_run(dt_job_t *job)
{
  long int imgid = -1;
  dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param;
  GList *t = t1->index;
  int total = g_list_length(t);
  char message[512]= {0};
  double fraction=0;
  snprintf(message, 512, ngettext ("deleting %d image", "deleting %d images", total), total );
  const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message);

  sqlite3_stmt *stmt;

  char query[1024];
  sprintf(query, "update images set flags = (flags | %d) where id in (select imgid from selected_images)",DT_IMAGE_REMOVE);
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), query, NULL, NULL, NULL);

  dt_collection_update(darktable.collection);

  // We need a list of files to regenerate .xmp files if there are duplicates
  GList *list = NULL;

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select distinct folder || '/' || filename from images, film_rolls where images.film_id = film_rolls.id and images.id in (select imgid from selected_images)", -1, &stmt, NULL);

  if(sqlite3_step(stmt) == SQLITE_ROW)
  {
    list = g_list_append(list, g_strdup((const gchar *)sqlite3_column_text(stmt, 0)));
  }
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(id) from images where filename in (select filename from images where id = ?1) and film_id in (select film_id from images where id = ?1)", -1, &stmt, NULL);
  while(t)
  {
    imgid = (long int)t->data;
    char filename[DT_MAX_PATH_LEN];
    dt_image_full_path(imgid, filename, DT_MAX_PATH_LEN);

    int duplicates = 0;
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
    if(sqlite3_step(stmt) == SQLITE_ROW)
      duplicates = sqlite3_column_int(stmt, 0);
    sqlite3_reset(stmt);
    sqlite3_clear_bindings(stmt);

    // remove from disk:
    if(duplicates == 1) // don't remove the actual data if there are (other) duplicates using it
      (void)g_unlink(filename);
    dt_image_path_append_version(imgid, filename, DT_MAX_PATH_LEN);
    char *c = filename + strlen(filename);
    sprintf(c, ".xmp");
    (void)g_unlink(filename);

    dt_image_remove(imgid);

    t = g_list_delete_link(t, t);
    fraction=1.0/total;
    dt_control_backgroundjobs_progress(darktable.control, jid, fraction);
  }
  sqlite3_finalize(stmt);

  char *imgname;
  while(list)
  {
    imgname = (char *)list->data;
    dt_image_synch_all_xmp(imgname);
    list = g_list_delete_link(list, list);
  }
  g_list_free(list);
  dt_control_backgroundjobs_destroy(darktable.control, jid);
  dt_film_remove_empty();
  return 0;
}
Exemplo n.º 20
0
static void delete_button_clicked(GtkButton *button, gpointer user_data)
{
  dt_lib_module_t *self = (dt_lib_module_t *)user_data;
  dt_lib_tagging_t *d = (dt_lib_tagging_t *)self->data;

  int res = GTK_RESPONSE_YES;

  guint tagid;
  GtkTreeIter iter;
  GtkTreeModel *model = NULL;
  GtkTreeView *view = d->related;
  GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
  if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return;
  gtk_tree_model_get(model, &iter, DT_LIB_TAGGING_COL_ID, &tagid, -1);

  // First check how many images are affected by the remove
  int count = dt_tag_remove(tagid, FALSE);
  if(count > 0 && dt_conf_get_bool("plugins/lighttable/tagging/ask_before_delete_tag"))
  {
    GtkWidget *dialog;
    GtkWidget *win = dt_ui_main_window(darktable.gui->ui);
    gchar *tagname = dt_tag_get_name(tagid);
    dialog = gtk_message_dialog_new(
        GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
        ngettext("do you really want to delete the tag `%s'?\n%d image is assigned this tag!",
                 "do you really want to delete the tag `%s'?\n%d images are assigned this tag!", count),
        tagname, count);
    gtk_window_set_title(GTK_WINDOW(dialog), _("delete tag?"));
    res = gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
    free(tagname);
  }
  if(res != GTK_RESPONSE_YES) return;

  GList *tagged_images = NULL;
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT imgid FROM main.tagged_images WHERE tagid=?1",
                              -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, tagid);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    tagged_images = g_list_append(tagged_images, GINT_TO_POINTER(sqlite3_column_int(stmt, 0)));
  }
  sqlite3_finalize(stmt);

  dt_tag_remove(tagid, TRUE);

  GList *list_iter;
  if((list_iter = g_list_first(tagged_images)) != NULL)
  {
    do
    {
      dt_image_synch_xmp(GPOINTER_TO_INT(list_iter->data));
    } while((list_iter = g_list_next(list_iter)) != NULL);
  }
  g_list_free(g_list_first(tagged_images));

  update(self, 0);
  update(self, 1);

  dt_control_signal_raise(darktable.signals, DT_SIGNAL_TAG_CHANGED);
}
Exemplo n.º 21
0
static GtkWidget* _lib_import_get_extra_widget(dt_lib_import_metadata_t *data, gboolean import_folder)
{
  // add extra lines to 'extra'. don't forget to destroy the widgets later.
  GtkWidget *expander = gtk_expander_new(_("import options"));
  gtk_expander_set_expanded(GTK_EXPANDER(expander), dt_conf_get_bool("ui_last/import_options_expanded"));

  GtkWidget *frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_IN);
  GtkWidget *alignment = gtk_alignment_new(1.0, 1.0, 1.0, 1.0);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 8, 8, 8, 8);
  GtkWidget *event_box = gtk_event_box_new();
  gtk_container_add(GTK_CONTAINER(frame), event_box);
  gtk_container_add(GTK_CONTAINER(event_box), alignment);
  gtk_container_add(GTK_CONTAINER(alignment), expander);

  GtkWidget *extra;
  extra = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(expander), extra);

  GtkWidget *recursive = NULL, *ignore_jpeg = NULL;
  if(import_folder == TRUE)
  {
    // recursive opening.
    recursive = gtk_check_button_new_with_label (_("import directories recursively"));
    g_object_set(recursive, "tooltip-text", _("recursively import subdirectories. each directory goes into a new film roll."), NULL);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (recursive), dt_conf_get_bool("ui_last/import_recursive"));
    gtk_box_pack_start(GTK_BOX (extra), recursive, FALSE, FALSE, 0);

    // ignoring of jpegs. hack while we don't handle raw+jpeg in the same directories.
    ignore_jpeg = gtk_check_button_new_with_label (_("ignore jpeg files"));
    g_object_set(ignore_jpeg, "tooltip-text", _("do not load files with an extension of .jpg or .jpeg. this can be useful when there are raw+jpeg in a directory."), NULL);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (ignore_jpeg), dt_conf_get_bool("ui_last/import_ignore_jpegs"));
    gtk_box_pack_start(GTK_BOX (extra), ignore_jpeg, FALSE, FALSE, 0);
  }

  // default metadata
  GtkWidget *apply_metadata;
  GtkWidget *table, *label, *creator, *publisher, *rights, *tags;
  apply_metadata = gtk_check_button_new_with_label (_("apply metadata on import"));
  g_object_set(apply_metadata, "tooltip-text", _("apply some metadata to all newly imported images."), NULL);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (apply_metadata), dt_conf_get_bool("ui_last/import_apply_metadata"));
  gtk_box_pack_start(GTK_BOX (extra), apply_metadata, FALSE, FALSE, 0);

  GValue value = {0, };
  g_value_init(&value, G_TYPE_INT);
  gtk_widget_style_get_property(apply_metadata, "indicator-size", &value);
  gint indicator_size = g_value_get_int(&value);
//   gtk_widget_style_get_property(apply_metadata, "indicator-spacing", &value);
//   gint indicator_spacing = g_value_get_int(&value);

  table = gtk_table_new(6, 3, FALSE);
  gtk_table_set_row_spacings(GTK_TABLE(table), 5);
  gtk_table_set_col_spacings(GTK_TABLE(table), 5);
  alignment = gtk_alignment_new(0, 0, 1, 1);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 2*indicator_size, 0);
  gtk_container_add(GTK_CONTAINER(alignment), table);
  gtk_box_pack_start(GTK_BOX (extra), alignment, FALSE, FALSE, 0);

  creator = gtk_entry_new();
  gtk_widget_set_size_request(creator, 300, -1);
  gtk_entry_set_text(GTK_ENTRY(creator), dt_conf_get_string("ui_last/import_last_creator"));
  publisher = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(publisher), dt_conf_get_string("ui_last/import_last_publisher"));
  rights = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(rights), dt_conf_get_string("ui_last/import_last_rights"));
  tags = gtk_entry_new();
  g_object_set(tags, "tooltip-text", _("comma separated list of tags"), NULL);
  gtk_entry_set_text(GTK_ENTRY(tags), dt_conf_get_string("ui_last/import_last_tags"));

  // presets from the metadata plugin
  GtkCellRenderer *renderer;
  GtkTreeIter iter;
  GtkListStore *model = gtk_list_store_new(N_COLUMNS,
                        G_TYPE_STRING /*name*/,
                        G_TYPE_STRING /*creator*/,
                        G_TYPE_STRING /*publisher*/,
                        G_TYPE_STRING /*rights*/);

  GtkWidget *presets = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
  renderer = gtk_cell_renderer_text_new();
  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(presets), renderer, FALSE);
  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(presets), renderer, "text", NAME_COLUMN, NULL);

  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params from presets where operation = \"metadata\"", -1, &stmt, NULL);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    void *op_params = (void *)sqlite3_column_blob(stmt, 1);
    int32_t op_params_size = sqlite3_column_bytes(stmt, 1);

    char *buf         = (char* )op_params;
    char *title       = buf;
    buf += strlen(title) + 1;
    char *description = buf;
    buf += strlen(description) + 1;
    char *rights     = buf;
    buf += strlen(rights) + 1;
    char *creator     = buf;
    buf += strlen(creator) + 1;
    char *publisher   = buf;

    if(op_params_size == strlen(title) + strlen(description) + strlen(rights) + strlen(creator) + strlen(publisher) + 5)
    {
      gtk_list_store_append(model, &iter);
      gtk_list_store_set (model, &iter,
                          NAME_COLUMN, (char *)sqlite3_column_text(stmt, 0),
                          CREATOR_COLUMN, creator,
                          PUBLISHER_COLUMN, publisher,
                          RIGHTS_COLUMN, rights,
                          -1);
    }
  }
  sqlite3_finalize(stmt);

  g_object_unref(model);

  int line = 0;

  label = gtk_label_new(_("preset"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(table), label, 0, 1, line, line+1, GTK_FILL, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(table), presets, 1, 2, line, line+1, GTK_FILL, 0, 0, 0);
  line++;

  label = gtk_label_new(_("creator"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(table), label, 0, 1, line, line+1, GTK_FILL, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(table), creator, 1, 2, line, line+1, GTK_FILL, 0, 0, 0);
  line++;

  label = gtk_label_new(_("publisher"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(table), label, 0, 1, line, line+1, GTK_FILL, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(table), publisher, 1, 2, line, line+1, GTK_FILL, 0, 0, 0);
  line++;

  label = gtk_label_new(_("rights"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(table), label, 0, 1, line, line+1, GTK_FILL, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(table), rights, 1, 2, line, line+1, GTK_FILL, 0, 0, 0);
  line++;

  label = gtk_label_new(_("tags"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(table), label, 0, 1, line, line+1, GTK_FILL, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(table), tags, 1, 2, line, line+1, GTK_FILL, 0, 0, 0);

  gtk_widget_show_all(frame);

  if(data != NULL)
  {
    data->frame = frame;
    data->recursive = recursive;
    data->ignore_jpeg = ignore_jpeg;
    data->expander = expander;
    data->apply_metadata = apply_metadata;
    data->presets = presets;
    data->creator = creator;
    data->publisher = publisher;
    data->rights = rights;
    data->tags = tags;
  }

  g_signal_connect(apply_metadata, "toggled", G_CALLBACK (_lib_import_apply_metadata_toggled), table);
  _lib_import_apply_metadata_toggled(apply_metadata, table); // needed since the apply_metadata starts being turned off,
  // and setting it to off doesn't emit the 'toggled' signal ...

  g_signal_connect(presets, "changed", G_CALLBACK(_lib_import_presets_changed), data);
  g_signal_connect(GTK_ENTRY(creator), "changed", G_CALLBACK (_lib_import_metadata_changed), presets);
  g_signal_connect(GTK_ENTRY(publisher), "changed", G_CALLBACK (_lib_import_metadata_changed), presets);
  g_signal_connect(GTK_ENTRY(rights), "changed", G_CALLBACK (_lib_import_metadata_changed), presets);

  return frame;
}
Exemplo n.º 22
0
static int image_index(lua_State *L)
{
  const char* membername = lua_tostring(L, -1);
  const dt_image_t * my_image=checkreadimage(L,-2);
  if(luaA_struct_has_member_name(L,dt_image_t,membername))
  {
    const int result = luaA_struct_push_member_name(L, dt_image_t, my_image, membername);
    releasereadimage(L,my_image);
    return result;
  }
  switch(luaL_checkoption(L,-1,NULL,image_fields_name))
  {
    case PATH:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
            "select folder from images, film_rolls where "
            "images.film_id = film_rolls.id and images.id = ?1", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        if(sqlite3_step(stmt) == SQLITE_ROW)
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        else
        {
          sqlite3_finalize(stmt);
          releasereadimage(L,my_image);
          return luaL_error(L,"should never happen");
        }
        sqlite3_finalize(stmt);
        break;
      }
    case DUP_INDEX:
      {
        // get duplicate suffix
        int version = 0;
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
            "select count(id) from images where filename in "
            "(select filename from images where id = ?1) and film_id in "
            "(select film_id from images where id = ?1) and id < ?1",
            -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        if(sqlite3_step(stmt) == SQLITE_ROW)
          version = sqlite3_column_int(stmt, 0);
        sqlite3_finalize(stmt);
        lua_pushinteger(L,version);
        break;
      }
    case IS_LDR:
      lua_pushboolean(L,dt_image_is_ldr(my_image));
      break;
    case IS_HDR:
      lua_pushboolean(L,dt_image_is_hdr(my_image));
      break;
    case IS_RAW:
      lua_pushboolean(L,dt_image_is_raw(my_image));
      break;
    case RATING:
      {
        int score = my_image->flags & 0x7;
        if(score >6) score=5;
        if(score ==6) score=-1;

        lua_pushinteger(L,score);
        break;
      }
    case ID:
      lua_pushinteger(L,my_image->id);
      break;
    case CREATOR:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_CREATOR);
        if(sqlite3_step(stmt) != SQLITE_ROW)
        {
          lua_pushstring(L,"");
        }
        else
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        sqlite3_finalize(stmt);
        break;

      }
    case PUBLISHER:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_PUBLISHER);
        if(sqlite3_step(stmt) != SQLITE_ROW)
        {
          lua_pushstring(L,"");
        }
        else
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        sqlite3_finalize(stmt);
        break;

      }
    case TITLE:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_TITLE);
        if(sqlite3_step(stmt) != SQLITE_ROW)
        {
          lua_pushstring(L,"");
        }
        else
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        sqlite3_finalize(stmt);
        break;

      }
    case DESCRIPTION:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_DESCRIPTION);
        if(sqlite3_step(stmt) != SQLITE_ROW)
        {
          lua_pushstring(L,"");
        }
        else
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        sqlite3_finalize(stmt);
        break;

      }
    case RIGHTS:
      {
        sqlite3_stmt *stmt;
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_RIGHTS);
        if(sqlite3_step(stmt) != SQLITE_ROW)
        {
          lua_pushstring(L,"");
        }
        else
        {
          lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0));
        }
        sqlite3_finalize(stmt);
        break;

      }
    case GROUP_LEADER:
      {
        luaA_push(L,dt_lua_image_t,&(my_image->group_id));
        break;
      }
    default:
      releasereadimage(L,my_image);
      return luaL_error(L,"should never happen %s",lua_tostring(L,-1));

  }
  releasereadimage(L,my_image);
  return 1;
}
Exemplo n.º 23
0
void
dt_styles_create_from_style (const char *name, const char *newname, const char *description, GList *filter)
{
  sqlite3_stmt *stmt;
  int id=0;
  int oldid=0;
  
  oldid = dt_styles_get_id_by_name(name);
  if(oldid == 0) return;

  /* create the style header */
  if (!dt_styles_create_style_header(newname, description)) return;
  
  if ((id=dt_styles_get_id_by_name(newname)) != 0)
  {
    if (filter)
    {
      GList *list=filter;
      char tmp[64];
      char include[2048]= {0};
      g_strlcat(include,"num in (", 2048);
      do
      {
        if(list!=g_list_first(list))
          g_strlcat(include,",", 2048);
        sprintf(tmp,"%ld",(long int)list->data);
        g_strlcat(include,tmp, 2048);
      }
      while ((list=g_list_next(list)));
      g_strlcat(include,")", 2048);
      char query[4096]= {0};

      sprintf(query,"insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid=?2 and %s",include);
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
    }
    else
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where style_id=?2", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, oldid);
    sqlite3_step (stmt);
    sqlite3_finalize (stmt);

    /* backup style to disk */
    char stylesdir[1024];
    dt_loc_get_user_config_dir(stylesdir, 1024);
    g_strlcat(stylesdir,"/styles",1024);
    g_mkdir_with_parents(stylesdir,00755);

    dt_styles_save_to_file(newname,stylesdir,FALSE);

      char tmp_accel[1024];
      gchar* tmp_name = g_strdup(newname); // freed by _destro_style_shortcut_callback
      snprintf(tmp_accel,1024,"styles/Apply %s",newname);
      dt_accel_register_global( tmp_accel, 0, 0);
      GClosure *closure;
      closure = g_cclosure_new(
          G_CALLBACK(_apply_style_shortcut_callback),
          tmp_name, _destroy_style_shortcut_callback);
      dt_accel_connect_global(tmp_accel, closure);
    dt_control_log(_("style named '%s' successfully created"),newname);
  }
}
Exemplo n.º 24
0
static void
auto_apply_presets(dt_develop_t *dev)
{
  const int imgid = dev->image_storage.id;

  if(imgid <= 0) return;
  int run = 0;
  const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid);
  if(!(cimg->flags & DT_IMAGE_AUTO_PRESETS_APPLIED))
    run = 1;

  // flag was already set? only apply presets once in the lifetime of a history stack.
  // (the flag will be cleared when removing it)
  if(!run || cimg->id <= 0)
  {
    dt_image_cache_read_release(darktable.image_cache, cimg);
    return;
  }

  // keep locked, we want to be alone messing with the history of the poor fellow:
  dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg);
  // be extra sure that we don't mess up history in separate threads:
  dt_pthread_mutex_lock(&darktable.db_insert);

  // cleanup
  DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db),
      "delete from memory.history",
      NULL, NULL, NULL);
  const char *preset_table[2] = {"presets", "legacy_presets"};
  const int legacy = (image->flags & DT_IMAGE_NO_LEGACY_PRESETS) ? 0 : 1;
  char query[1024];
  snprintf(query, 1024,
      "insert into memory.history select ?1, 0, op_version, operation, op_params, enabled, blendop_params, blendop_version, multi_priority, multi_name "
      "from %s where autoapply=1 and "
                              "?2 like model and ?3 like maker and ?4 like lens and "
                              "?5 between iso_min and iso_max and "
                              "?6 between exposure_min and exposure_max and "
                              "?7 between aperture_min and aperture_max and "
                              "?8 between focal_length_min and focal_length_max and "
                              "(isldr = 0 or isldr=?9) order by writeprotect desc, "
                              "length(model), length(maker), length(lens)", preset_table[legacy]);
  // query for all modules at once:
  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, cimg->exif_model, strlen(cimg->exif_model), SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, cimg->exif_maker, strlen(cimg->exif_maker), SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, cimg->exif_lens,  strlen(cimg->exif_lens),  SQLITE_TRANSIENT);
  DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 5, fmaxf(0.0f, fminf(1000000, cimg->exif_iso)));
  DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, fmaxf(0.0f, fminf(1000000, cimg->exif_exposure)));
  DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, fmaxf(0.0f, fminf(1000000, cimg->exif_aperture)));
  DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmaxf(0.0f, fminf(1000000, cimg->exif_focal_length)));
  // 0: dontcare, 1: ldr, 2: raw
  DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, 2-dt_image_is_ldr(cimg));

  if(sqlite3_step(stmt) == SQLITE_DONE)
  {
    sqlite3_finalize(stmt);
    int cnt = 0;
    // count what we found:
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
        "select count(*) from memory.history",
        -1, &stmt, NULL);
    if(sqlite3_step(stmt) == SQLITE_ROW)
    {
      // if there is anything..
      cnt = sqlite3_column_int(stmt, 0);
      sqlite3_finalize(stmt);
      // fprintf(stderr, "[auto_apply_presets] imageid %d found %d matching presets (legacy %d)\n", imgid, cnt, legacy);
      // advance the current history by that amount:
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
          "update history set num=num+?1 where imgid=?2",
          -1, &stmt, NULL);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, cnt);
      DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);

      if(sqlite3_step(stmt) == SQLITE_DONE)
      {
        // and finally prepend the rest with increasing numbers (starting at 0)
        sqlite3_finalize(stmt);
        DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
            "insert into history select imgid, rowid-1, module, operation, op_params, enabled, "
            "blendop_params, blendop_version, multi_priority, multi_name from memory.history",
          -1, &stmt, NULL);
        sqlite3_step(stmt);
      }
    }
  }
  sqlite3_finalize(stmt);

  //  first time we are loading the image, try to import lightroom .xmp if any
  if (dev->image_loading)
    dt_lightroom_import(dev->image_storage.id, dev, TRUE);

  image->flags |= DT_IMAGE_AUTO_PRESETS_APPLIED | DT_IMAGE_NO_LEGACY_PRESETS;
  dt_pthread_mutex_unlock(&darktable.db_insert);

  // make sure these end up in the image_cache + xmp (sync through here if we set the flag)
  dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE);
  dt_image_cache_read_release(darktable.image_cache, cimg);
}
Exemplo n.º 25
0
void
dt_styles_save_to_file(const char *style_name,const char *filedir,gboolean overwrite)
{
  int rc = 0;
  char stylename[520];
  sqlite3_stmt *stmt;

  snprintf(stylename,512,"%s/%s.dtstyle",filedir,style_name);

  // check if file exists
  if( g_file_test(stylename, G_FILE_TEST_EXISTS) == TRUE )
  {
    if(overwrite)
    {
      if(unlink(stylename))
      {
        dt_control_log(_("failed to overwrite style file for %s"),style_name);
        return;
      }
    }
    else
    {
      dt_control_log(_("style file for %s exists"),style_name);
      return;
    }
  }

  if ( !dt_styles_exists (style_name) ) return;

  xmlTextWriterPtr writer = xmlNewTextWriterFilename(stylename, 0);
  if (writer == NULL)
  {
    fprintf(stderr,"[dt_styles_save_to_file] Error creating the xml writer\n, path: %s", stylename);
    return;
  }
  rc = xmlTextWriterStartDocument(writer, NULL, "ISO-8859-1", NULL);
  if (rc < 0)
  {
    fprintf(stderr,"[dt_styles_save_to_file]: Error on encoding setting");
    return;
  }
  xmlTextWriterStartElement(writer, BAD_CAST "darktable_style");
  xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST "1.0");

  xmlTextWriterStartElement(writer, BAD_CAST "info");
  xmlTextWriterWriteFormatElement(writer, BAD_CAST "name", "%s", style_name);
  xmlTextWriterWriteFormatElement(writer, BAD_CAST "description", "%s", dt_styles_get_description(style_name));
  xmlTextWriterEndElement(writer);

  xmlTextWriterStartElement(writer, BAD_CAST "style");
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from style_items where styleid =?1",-1, &stmt,NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt,1,dt_styles_get_id_by_name(style_name));
  while (sqlite3_step (stmt) == SQLITE_ROW)
  {
    xmlTextWriterStartElement(writer, BAD_CAST "plugin");
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "num", "%d", sqlite3_column_int(stmt,0));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "module", "%d", sqlite3_column_int(stmt,1));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "operation", "%s", sqlite3_column_text(stmt,2));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "op_params", "%s", dt_style_encode(stmt,3));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "enabled", "%d", sqlite3_column_int(stmt,4));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "blendop_params", "%s", dt_style_encode(stmt,5));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "blendop_version", "%d", sqlite3_column_int(stmt,6));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "multi_priority", "%d", sqlite3_column_int(stmt,7));
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "multi_name", "%s", sqlite3_column_text(stmt,8));
    xmlTextWriterEndElement(writer);
  }
  sqlite3_finalize(stmt);
  xmlTextWriterEndDocument(writer);
  xmlFreeTextWriter(writer);
  dt_control_log(_("style %s was successfully saved"),style_name);
}
Exemplo n.º 26
0
void dt_dev_read_history(dt_develop_t *dev)
{
  if(dev->image_storage.id <= 0) return;
  if(!dev->iop) return;

  // maybe prepend auto-presets to history before loading it:
  auto_apply_presets(dev);

  sqlite3_stmt *stmt;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
      "select imgid, num, module, operation, op_params, enabled, blendop_params, blendop_version, multi_priority, multi_name from history where imgid = ?1 order by num", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, dev->image_storage.id);
  dev->history_end = 0;
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    // db record:
    // 0-img, 1-num, 2-module_instance, 3-operation char, 4-params blob, 5-enabled, 6-blend_params, 7-blendop_version, 8 multi_priority, 9 multi_name
    dt_dev_history_item_t *hist = (dt_dev_history_item_t *)malloc(sizeof(dt_dev_history_item_t));
    hist->enabled = sqlite3_column_int(stmt, 5);

    GList *modules = dev->iop;
    const char *opname = (const char *)sqlite3_column_text(stmt, 3);
    int multi_priority = sqlite3_column_int(stmt, 8);
    const char *multi_name = (const char *)sqlite3_column_text(stmt, 9);
    if(!opname)
    {
      fprintf(stderr, "[dev_read_history] database history for image `%s' seems to be corrupted!\n", dev->image_storage.filename);
      free(hist);
      continue;
    }

    hist->module = NULL;
    dt_iop_module_t *find_op = NULL;
    while(opname && modules)
    {
      dt_iop_module_t *module = (dt_iop_module_t *)modules->data;
      if(!strcmp(module->op, opname))
      {
        if (module->multi_priority == multi_priority)
        {
          hist->module = module;
          break;
        }
        else if (multi_priority > 0)
        {
          //we just say that we find the name, so we just have to add new instance of this module
          find_op = module;
        }
      }
      modules = g_list_next(modules);
    }
    if (!hist->module && find_op)
    {
      //we have to add a new instance of this module and set index to modindex
      dt_iop_module_t *new_module    = (dt_iop_module_t *)malloc(sizeof(dt_iop_module_t));
      if (!dt_iop_load_module(new_module, find_op->so, dev))
      {
        new_module->multi_priority = multi_priority;

        snprintf(new_module->multi_name,128,"%s",multi_name);

        dev->iop = g_list_insert_sorted(dev->iop, new_module, sort_plugins);

        new_module->instance = find_op->instance;
        hist->module = new_module;
      }
    }

    if(!hist->module && opname)
    {
      fprintf(stderr, "[dev_read_history] the module `%s' requested by image `%s' is not installed on this computer!\n", opname, dev->image_storage.filename);
      free(hist);
      continue;
    }
    int modversion = sqlite3_column_int(stmt, 2);
    assert(strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op) == 0);
    hist->params = malloc(hist->module->params_size);
    hist->blend_params = malloc(sizeof(dt_develop_blend_params_t));
    snprintf(hist->multi_name,128,"%s",multi_name);
    hist->multi_priority = multi_priority;

    if(hist->module->version() != modversion || hist->module->params_size != sqlite3_column_bytes(stmt, 4) ||
        strcmp((char *)sqlite3_column_text(stmt, 3), hist->module->op))
    {
      if(!hist->module->legacy_params ||
          hist->module->legacy_params(hist->module, sqlite3_column_blob(stmt, 4), labs(modversion), hist->params, labs(hist->module->version())))
      {
        free(hist->params);
        free(hist->blend_params);
        fprintf(stderr, "[dev_read_history] module `%s' version mismatch: history is %d, dt %d.\n", hist->module->op, modversion, hist->module->version());
        const char *fname = dev->image_storage.filename + strlen(dev->image_storage.filename);
        while(fname > dev->image_storage.filename && *fname != '/') fname --;
        if(fname > dev->image_storage.filename) fname++;
        dt_control_log(_("%s: module `%s' version mismatch: %d != %d"), fname, hist->module->op, hist->module->version(), modversion);
        free(hist);
        continue;
      }
    }
    else
    {
      memcpy(hist->params, sqlite3_column_blob(stmt, 4), hist->module->params_size);
    }

    const void *blendop_params = sqlite3_column_blob(stmt, 6);
    int bl_length = sqlite3_column_bytes(stmt, 6);
    int blendop_version = sqlite3_column_int(stmt, 7);

    if (blendop_params && (blendop_version == dt_develop_blend_version()) && (bl_length == sizeof(dt_develop_blend_params_t)))
    {
      memcpy(hist->blend_params, blendop_params, sizeof(dt_develop_blend_params_t));
    }
    else if (blendop_params && dt_develop_blend_legacy_params(hist->module, blendop_params, blendop_version, hist->blend_params, dt_develop_blend_version(), bl_length) == 0)
    {
      // do nothing
    }
    else
    {
      memcpy(hist->blend_params, hist->module->default_blendop_params, sizeof(dt_develop_blend_params_t));
    }

    // memcpy(hist->module->params, hist->params, hist->module->params_size);
    // hist->module->enabled = hist->enabled;
    // printf("[dev read history] img %d number %d for operation %d - %s params %f %f\n", sqlite3_column_int(stmt, 0), sqlite3_column_int(stmt, 1), instance, hist->module->op, *(float *)hist->params, *(((float*)hist->params)+1));
    dev->history = g_list_append(dev->history, hist);
    dev->history_end ++;
  }

  if(dev->gui_attached)
  {
    dev->pipe->changed |= DT_DEV_PIPE_SYNCH;
    dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; // again, fixed topology for now.
    dt_dev_invalidate_all(dev);

    /* signal history changed */
    dt_control_signal_raise(darktable.signals,DT_SIGNAL_DEVELOP_HISTORY_CHANGE);
  }
  sqlite3_finalize (stmt);
}
Exemplo n.º 27
0
/* create the current database schema and set the version in db_info accordingly */
static void _create_schema(dt_database_t *db)
{
  sqlite3_stmt *stmt;
  ////////////////////////////// db_info
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE db_info (key VARCHAR PRIMARY KEY, value VARCHAR)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_PREPARE_V2(db->handle, "INSERT OR REPLACE INTO db_info (key, value) VALUES ('version', ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, CURRENT_DATABASE_VERSION);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  ////////////////////////////// film_rolls
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE film_rolls "
                        "(id INTEGER PRIMARY KEY, datetime_accessed CHAR(20), "
//                        "folder VARCHAR(1024), external_drive VARCHAR(1024))", // FIXME: make sure to bump CURRENT_DATABASE_VERSION and add a case to _upgrade_schema_step when adding this!
                        "folder VARCHAR(1024))",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX film_rolls_folder_index ON film_rolls (folder)", NULL, NULL, NULL);
  ////////////////////////////// images
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE images (id INTEGER PRIMARY KEY AUTOINCREMENT, group_id INTEGER, film_id INTEGER, "
                        "width INTEGER, height INTEGER, filename VARCHAR, maker VARCHAR, model VARCHAR, "
                        "lens VARCHAR, exposure REAL, aperture REAL, iso REAL, focal_length REAL, "
                        "focus_distance REAL, datetime_taken CHAR(20), flags INTEGER, "
                        "output_width INTEGER, output_height INTEGER, crop REAL, "
                        "raw_parameters INTEGER, raw_denoise_threshold REAL, "
                        "raw_auto_bright_threshold REAL, raw_black INTEGER, raw_maximum INTEGER, "
                        "caption VARCHAR, description VARCHAR, license VARCHAR, sha1sum CHAR(40), "
                        "orientation INTEGER, histogram BLOB, lightmap BLOB, longitude REAL, "
                        "latitude REAL, color_matrix BLOB, colorspace INTEGER, version INTEGER, max_version INTEGER, write_timestamp INTEGER)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX images_group_id_index ON images (group_id)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX images_film_id_index ON images (film_id)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX images_filename_index ON images (filename)", NULL, NULL, NULL);
  ////////////////////////////// selected_images
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE selected_images (imgid INTEGER PRIMARY KEY)", NULL, NULL, NULL);
  ////////////////////////////// history
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE history (imgid INTEGER, num INTEGER, module INTEGER, "
                        "operation VARCHAR(256), op_params BLOB, enabled INTEGER, "
                        "blendop_params BLOB, blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256))", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX history_imgid_index ON history (imgid)", NULL, NULL, NULL);
  ////////////////////////////// mask
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE mask (imgid INTEGER, formid INTEGER, form INTEGER, name VARCHAR(256), "
                        "version INTEGER, points BLOB, points_count INTEGER, source BLOB)", NULL, NULL, NULL);
  ////////////////////////////// tags
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE tags (id INTEGER PRIMARY KEY, name VARCHAR, icon BLOB, "
                        "description VARCHAR, flags INTEGER)", NULL, NULL, NULL);
  ////////////////////////////// tagged_images
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE tagged_images (imgid INTEGER, tagid INTEGER, "
                        "PRIMARY KEY (imgid, tagid))", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX tagged_images_tagid_index ON tagged_images (tagid)", NULL, NULL, NULL);
  ////////////////////////////// tagxtag
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE tagxtag (id1 INTEGER, id2 INTEGER, count INTEGER, "
                        "PRIMARY KEY (id1, id2))", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TRIGGER insert_tag AFTER INSERT ON tags"
                        " BEGIN"
                        "   INSERT INTO tagxtag SELECT id, new.id, 0 FROM TAGS;"
                        "   UPDATE tagxtag SET count = 1000000 WHERE id1=new.id AND id2=new.id;"
                        " END",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TRIGGER delete_tag BEFORE DELETE on tags"
                        " BEGIN"
                        "   DELETE FROM tagxtag WHERE id1=old.id OR id2=old.id;"
                        "   DELETE FROM tagged_images WHERE tagid=old.id;"
                        " END",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TRIGGER attach_tag AFTER INSERT ON tagged_images"
                        " BEGIN"
                        "   UPDATE tagxtag"
                        "     SET count = count + 1"
                        "     WHERE (id1=new.tagid AND id2 IN (SELECT tagid FROM tagged_images WHERE imgid=new.imgid))"
                        "        OR (id2=new.tagid AND id1 IN (SELECT tagid FROM tagged_images WHERE imgid=new.imgid));"
                        " END",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TRIGGER detach_tag BEFORE DELETE ON tagged_images"
                        " BEGIN"
                        "   UPDATE tagxtag"
                        "     SET count = count - 1"
                        "     WHERE (id1=old.tagid AND id2 IN (SELECT tagid FROM tagged_images WHERE imgid=old.imgid))"
                        "        OR (id2=old.tagid AND id1 IN (SELECT tagid FROM tagged_images WHERE imgid=old.imgid));"
                        " END",
                        NULL, NULL, NULL);
  ////////////////////////////// styles
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE styles (id INTEGER, name VARCHAR, description VARCHAR)", NULL, NULL, NULL);
  ////////////////////////////// style_items
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE style_items (styleid INTEGER, num INTEGER, module INTEGER, "
                        "operation VARCHAR(256), op_params BLOB, enabled INTEGER, "
                        "blendop_params BLOB, blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256))", NULL, NULL, NULL);
  ////////////////////////////// color_labels
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE color_labels (imgid INTEGER, color INTEGER)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE UNIQUE INDEX color_labels_idx ON color_labels (imgid, color)", NULL, NULL, NULL);
  ////////////////////////////// meta_data
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE meta_data (id INTEGER, key INTEGER, value VARCHAR)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE INDEX metadata_index ON meta_data (id, key)", NULL, NULL, NULL);
  ////////////////////////////// presets
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE presets (name VARCHAR, description VARCHAR, operation VARCHAR, op_version INTEGER, op_params BLOB, "
                        "enabled INTEGER, blendop_params BLOB, blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256), "
                        "model VARCHAR, maker VARCHAR, lens VARCHAR, iso_min REAL, iso_max REAL, exposure_min REAL, exposure_max REAL, "
                        "aperture_min REAL, aperture_max REAL, focal_length_min REAL, focal_length_max REAL, writeprotect INTEGER, "
                        "autoapply INTEGER, filter INTEGER, def INTEGER, format INTEGER)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE UNIQUE INDEX presets_idx ON presets(name, operation, op_version)", NULL, NULL, NULL);

}
Exemplo n.º 28
0
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;

  int32_t width = widget->allocation.width;
  int32_t height = widget->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(widget->window); 

  /* 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;

  /* mouse over image position in filmstrip */
  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;

  const int max_cols = (int)(1+width/(float)wd);
  sqlite3_stmt *stmt = NULL;

  /* get the count of current collection */
  int 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 > count-max_cols+1) strip->offset = offset = count-max_cols+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);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_cols);
  

  cairo_save(cr);
  for(int col = 0; col < max_cols; col++)
  {
    if(sqlite3_step(stmt) == 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);
      cairo_restore(cr);
    }
    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;
}
Exemplo n.º 29
0
// This is basically the same as dt_image_remove() from common/image.c.
// It just does the iteration over all images in the SQL statement
void dt_film_remove(const int id)
{
  // only allowed if local copies have their original accessible

  sqlite3_stmt *stmt;

  gboolean remove_ok = TRUE;
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "SELECT id FROM images WHERE film_id = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);

  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    int imgid = sqlite3_column_int(stmt, 0);
    if (!dt_image_safe_remove(imgid))
    {
      remove_ok = FALSE;
      break;
    }
  }
  sqlite3_finalize(stmt);

  if (!remove_ok)
  {
    dt_control_log(_("cannot remove film roll having local copies with non accessible originals"));
    return;
  }

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from tagged_images where imgid in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from history where imgid in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from color_labels where imgid in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from meta_data where id in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from selected_images where imgid in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "select id from images where film_id = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    const uint32_t imgid = sqlite3_column_int(stmt, 0);
    dt_image_local_copy_reset(imgid);
    dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
    dt_image_cache_remove (darktable.image_cache, imgid);
  }
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from images where id in "
                              "(select id from images where film_id = ?1)", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);

  DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                              "delete from film_rolls where id = ?1", -1, &stmt, NULL);
  DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  // dt_control_update_recent_films();
  dt_control_signal_raise(darktable.signals , DT_SIGNAL_FILMROLLS_CHANGED);
}
Exemplo n.º 30
0
static void dt_gui_presets_popup_menu_show_internal(dt_dev_operation_t op, int32_t version,
                                                    dt_iop_params_t *params, int32_t params_size,
                                                    dt_develop_blend_params_t *bl_params,
                                                    dt_iop_module_t *module, const dt_image_t *image,
                                                    void (*pick_callback)(GtkMenuItem *, void *),
                                                    void *callback_data)
{
  GtkMenu *menu = darktable.gui->presets_popup_menu;
  if(menu) gtk_widget_destroy(GTK_WIDGET(menu));
  darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new());
  menu = darktable.gui->presets_popup_menu;

  GtkWidget *mi;
  int active_preset = -1, cnt = 0, writeprotect = 0; //, selected_default = 0;
  sqlite3_stmt *stmt;
  // order: get shipped defaults first
  if(image)
  {
    // only matching if filter is on:
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                "select name, op_params, writeprotect, description, blendop_params, "
                                "op_version, enabled from presets where operation=?1 and "
                                "(filter=0 or ( "
                                "((?2 like model and ?3 like maker) or (?4 like model and ?5 like maker)) and "
                                "?6 like lens and "
                                "?7 between iso_min and iso_max and "
                                "?8 between exposure_min and exposure_max and "
                                "?9 between aperture_min and aperture_max and "
                                "?10 between focal_length_min and focal_length_max and "
                                "(format = 0 or format&?9!=0)"
                                " ) )"
                                "order by writeprotect desc, lower(name), rowid",
                                -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT);
    DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, image->exif_iso);
    DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, image->exif_exposure);
    DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, image->exif_aperture);
    DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, image->exif_focal_length);
    int ldr = dt_image_is_ldr(image) ? FOR_LDR : (dt_image_is_raw(image) ? FOR_RAW : FOR_HDR);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, ldr);
  }
  else
  {
    // don't know for which image. show all we got:
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, "
                                                               "description, blendop_params, op_version, "
                                                               "enabled from presets where operation=?1 "
                                                               "order by writeprotect desc, lower(name), rowid",
                                -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
  }
  // collect all presets for op from db
  int found = 0;
  while(sqlite3_step(stmt) == SQLITE_ROW)
  {
    void *op_params = (void *)sqlite3_column_blob(stmt, 1);
    int32_t op_params_size = sqlite3_column_bytes(stmt, 1);
    void *blendop_params = (void *)sqlite3_column_blob(stmt, 4);
    int32_t bl_params_size = sqlite3_column_bytes(stmt, 4);
    int32_t preset_version = sqlite3_column_int(stmt, 5);
    int32_t enabled = sqlite3_column_int(stmt, 6);
    int32_t isdefault = 0;
    int32_t isdisabled = (preset_version == version ? 0 : 1);
    const char *name = (char *)sqlite3_column_text(stmt, 0);

    if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0) found = 1;

    if(module && !memcmp(module->default_params, op_params, MIN(op_params_size, module->params_size))
       && !memcmp(module->default_blendop_params, blendop_params,
                  MIN(bl_params_size, sizeof(dt_develop_blend_params_t))))
      isdefault = 1;
    if(module && !memcmp(params, op_params, MIN(op_params_size, params_size))
       && !memcmp(bl_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t)))
       && module->enabled == enabled)
    {
      active_preset = cnt;
      writeprotect = sqlite3_column_int(stmt, 2);
      char *markup;
      mi = gtk_menu_item_new_with_label("");
      if(isdefault)
      {
        markup = g_markup_printf_escaped("<span weight=\"bold\">%s %s</span>", name, _("(default)"));
      }
      else
        markup = g_markup_printf_escaped("<span weight=\"bold\">%s</span>", name);
      gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup);
      g_free(markup);
    }
    else
    {
      if(isdefault)
      {
        char *markup;
        mi = gtk_menu_item_new_with_label("");
        markup = g_markup_printf_escaped("%s %s", name, _("(default)"));
        gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup);
        g_free(markup);
      }
      else
        mi = gtk_menu_item_new_with_label((const char *)name);
    }

    if(isdisabled)
    {
      gtk_widget_set_sensitive(mi, 0);
      gtk_widget_set_tooltip_text(mi, _("disabled: wrong module version"));
    }
    else
    {
      if(module)
        g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_pick_preset), module);
      else if(pick_callback)
        g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), callback_data);
      gtk_widget_set_tooltip_text(mi, (const char *)sqlite3_column_text(stmt, 3));
    }
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
    cnt++;
  }
  sqlite3_finalize(stmt);

  if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());

  if(module)
  {
    if(active_preset >= 0 && !writeprotect)
    {
      mi = gtk_menu_item_new_with_label(_("edit this preset.."));
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_edit_preset), module);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);

      mi = gtk_menu_item_new_with_label(_("delete this preset"));
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_delete_preset), module);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
    }
    else
    {
      mi = gtk_menu_item_new_with_label(_("store new preset.."));
      g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_new_preset), module);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);

      if(darktable.gui->last_preset && found)
      {
        char *markup = g_markup_printf_escaped("%s <span weight=\"bold\">%s</span>", _("update preset"),
                                               darktable.gui->last_preset);
        mi = gtk_menu_item_new_with_label("");
        gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup);
        g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_update_preset), module);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
        g_free(markup);
      }
    }
  }
}