Skip to content

Commit

Permalink
Squash Changes
Browse files Browse the repository at this point in the history
commit ec4b041
Author: Mario Lueder <monsieur.mona@gmail.com>
Date:   Sun Jul 15 16:39:59 2018 +0200

    removeCamelCase

commit 16c4d77
Author: Mario Lueder <monsieur.mona@gmail.com>
Date:   Sun Jul 15 16:29:07 2018 +0200

    Fix custom image order

    * avoid double connection of events
    * dropping images from import should be possible in all sort modes
    * image position index is not unique

commit c143c59
Author: Mario Lueder <monsieur.mona@gmail.com>
Date:   Fri Jul 13 02:18:33 2018 +0200

    Fix: Enable Drag and Drop only if Custom Image Order is selected

    Additional
    * implemented Houz's review points

commit dfbe17d
Author: Mario Lueder <monsieur.mona@gmail.com>
Date:   Fri May 25 15:38:23 2018 +0200

    Added custom image order by drag and drop in lighttable
  • Loading branch information
mayio committed Oct 8, 2018
1 parent 0588beb commit 886fab0
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 26 deletions.
168 changes: 164 additions & 4 deletions src/common/collection.c
Expand Up @@ -188,8 +188,6 @@ int dt_collection_update(const dt_collection_t *collection)
else
selq = dt_util_dstrcat(selq, "SELECT DISTINCT id FROM main.images WHERE %s", wq);



/* build sort order part */
if(!(collection->params.query_flags & COLLECTION_QUERY_USE_ONLY_WHERE_EXT)
&& (collection->params.query_flags & COLLECTION_QUERY_USE_SORT))
Expand Down Expand Up @@ -390,6 +388,10 @@ gchar *dt_collection_get_sort_query(const dt_collection_t *collection)
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "folder DESC, filename DESC, version DESC");
break;

case DT_COLLECTION_SORT_CUSTOM_ORDER:
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "position DESC, filename DESC, version DESC");
break;

case DT_COLLECTION_SORT_TITLE:
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "caption DESC, filename DESC, version DESC");
break;
Expand Down Expand Up @@ -435,6 +437,10 @@ gchar *dt_collection_get_sort_query(const dt_collection_t *collection)
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "folder, filename, version");
break;

case DT_COLLECTION_SORT_CUSTOM_ORDER:
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "position, filename, version");
break;

case DT_COLLECTION_SORT_TITLE:
sq = dt_util_dstrcat(sq, ORDER_BY_QUERY, "caption, filename, version");
break;
Expand Down Expand Up @@ -532,7 +538,6 @@ GList *dt_collection_get(const dt_collection_t *collection, int limit, gboolean
if((collection->params.query_flags & COLLECTION_QUERY_USE_SORT))
sq = dt_collection_get_sort_query(collection);


sqlite3_stmt *stmt = NULL;

/* build the query string */
Expand Down Expand Up @@ -1233,7 +1238,6 @@ void dt_collection_update_query(const dt_collection_t *collection)
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);
}
Expand Down Expand Up @@ -1347,6 +1351,162 @@ static void _dt_collection_recount_callback_2(gpointer instance, uint8_t id, gpo
}
}

int64_t dt_collection_get_image_position(const int32_t image_id)
{
int64_t image_position = -1;

if (image_id >= 0)
{
sqlite3_stmt *stmt = NULL;
gchar *image_pos_query = NULL;
image_pos_query = dt_util_dstrcat(
image_pos_query,
"SELECT position FROM main.images WHERE id = ?1");

DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), image_pos_query, -1, &stmt, NULL);
DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, image_id);

if(sqlite3_step(stmt) == SQLITE_ROW)
{
image_position = sqlite3_column_int64(stmt, 0);
}

sqlite3_finalize(stmt);
g_free(image_pos_query);
}

return image_position;
}

void dt_collection_shift_image_positions(const unsigned int length, const int64_t image_position)
{
DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "BEGIN", NULL, NULL, NULL);
sqlite3_stmt *stmt = NULL;

// shift image positions to make some space
gchar * update_image_pos_query = "UPDATE main.images SET position = position + ?1 WHERE position >= ?2 AND position < ?3";

DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), update_image_pos_query, -1, &stmt, NULL);
DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, length);
DT_DEBUG_SQLITE3_BIND_INT64(stmt, 2, image_position);
DT_DEBUG_SQLITE3_BIND_INT64(stmt, 3, (image_position & 0xFFFFFFFF00000000) + (1l << 32));

sqlite3_step(stmt);
sqlite3_finalize(stmt);

DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
}

/* move images with drag and drop
*
* An int64 is used for the position index. The upper 31 bits define the initial order.
* The lower 32bit provide space to reorder images. That way only a small amount of images must be
* updated while reordering images.
*
* Example: (position values hex)
* Initial order:
* Img 1: 0000 0001 0000 0000
* Img 2: 0000 0002 0000 0000
* Img 3: 0000 0003 0000 0000
* Img 3: 0000 0004 0000 0000
*
* Putting Img 2 in front of Img 1. Would give
* Img 2: 0000 0001 0000 0000
* Img 1: 0000 0001 0000 0001
* Img 3: 0000 0003 0000 0000
* Img 4: 0000 0004 0000 0000
*
* Img 3 and Img 4 is not updated.
*/
void dt_collection_move_before(const int32_t image_id, GList * selected_images)
{
if (!selected_images)
{
return;
}

const guint selected_images_length = g_list_length(selected_images);

if (selected_images_length == 0)
{
return;
}

// getting the position of the target image
const int64_t target_image_pos = dt_collection_get_image_position(image_id);

if (target_image_pos >= 0)
{
dt_collection_shift_image_positions(selected_images_length, target_image_pos);

sqlite3_stmt *stmt = NULL;
DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "BEGIN", NULL, NULL, NULL);

// move images to their intended positons
int64_t new_image_pos = target_image_pos;

gchar *insert_image_pos_query = "UPDATE main.images SET position = ?1 WHERE id = ?2";

DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), insert_image_pos_query, -1, &stmt, NULL);

for (const GList * selected_images_iter = selected_images;
selected_images_iter != NULL;
selected_images_iter = selected_images_iter->next)
{
const int moved_image_id = GPOINTER_TO_INT(selected_images_iter->data);

DT_DEBUG_SQLITE3_BIND_INT64(stmt, 1, new_image_pos);
DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, moved_image_id);
sqlite3_step(stmt);
sqlite3_reset(stmt);
new_image_pos++;
}
sqlite3_finalize(stmt);
DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
}
else
{
// move images to the end of the list
sqlite3_stmt *stmt = NULL;

// get last position
int64_t max_position = -1;

gchar *max_position_query = "SELECT MAX(position) FROM main.images";
DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), max_position_query, -1, &stmt, NULL);

if (sqlite3_step(stmt) == SQLITE_ROW)
{
max_position = sqlite3_column_int64(stmt, 0);
max_position = (max_position & 0xFFFFFFFF00000000) >> 32;
}

sqlite3_finalize(stmt);
sqlite3_stmt *update_stmt = NULL;

DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "BEGIN", NULL, NULL, NULL);

// move images to last position in custom image order table
gchar *update_query = "UPDATE main.images SET position = ?1 WHERE id = ?2";
DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), update_query, -1, &update_stmt, NULL);

for (const GList * selected_images_iter = selected_images;
selected_images_iter != NULL;
selected_images_iter = selected_images_iter->next)
{
max_position++;
const int moved_image_id = GPOINTER_TO_INT(selected_images_iter->data);
DT_DEBUG_SQLITE3_BIND_INT64(update_stmt, 1, max_position << 32);
DT_DEBUG_SQLITE3_BIND_INT(update_stmt, 2, moved_image_id);
sqlite3_step(update_stmt);
sqlite3_reset(update_stmt);
}

sqlite3_finalize(update_stmt);
DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "COMMIT", NULL, NULL, NULL);
}
}

// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
7 changes: 7 additions & 0 deletions src/common/collection.h
Expand Up @@ -66,6 +66,7 @@ typedef enum dt_collection_sort_t
DT_COLLECTION_SORT_COLOR,
DT_COLLECTION_SORT_GROUP,
DT_COLLECTION_SORT_PATH,
DT_COLLECTION_SORT_CUSTOM_ORDER,
DT_COLLECTION_SORT_TITLE,
DT_COLLECTION_SORT_DESCRIPTION
} dt_collection_sort_t;
Expand Down Expand Up @@ -220,6 +221,12 @@ void dt_collection_split_operator_number(const gchar *input, char **number1, cha
void dt_collection_split_operator_datetime(const gchar *input, char **number1, char **number2,
char **operator);

int64_t dt_collection_get_image_position(const int32_t image_id);
void dt_collection_shift_image_positions(const unsigned int length, const int64_t image_position);

/* move images with drag and drop */
void dt_collection_move_before(const int32_t image_id, GList * selected_images);

// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
29 changes: 27 additions & 2 deletions src/common/database.c
Expand Up @@ -37,7 +37,7 @@

// whenever _create_*_schema() gets changed you HAVE to bump this version and add an update path to
// _upgrade_*_schema_step()!
#define CURRENT_DATABASE_VERSION_LIBRARY 15
#define CURRENT_DATABASE_VERSION_LIBRARY 16
#define CURRENT_DATABASE_VERSION_DATA 1

typedef struct dt_database_t
Expand Down Expand Up @@ -967,6 +967,29 @@ static int _upgrade_library_schema_step(dt_database_t *db, int version)

sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
new_version = 15;
}
else if(version == 15)
{
sqlite3_exec(db->handle, "BEGIN TRANSACTION", NULL, NULL, NULL);
////////////////////////////// custom image order
TRY_EXEC("ALTER TABLE main.images ADD COLUMN position INTEGER",
"[init] can't add `position' column to images table in database\n");
TRY_EXEC("CREATE INDEX main.image_position_index ON images (position)",
"[init] can't create index for custom image order table\n");

// Set the initial image sequence. The image id - the sequece images were imported -
// defines the initial order of images.
//
// An int64 is used for the position index. The upper 31 bits define the initial order.
// The lower 32bit provide space to reorder images.
//
// see: dt_collection_move_before()
//
TRY_EXEC("UPDATE main.images SET position = id << 32",
"[init] can't update positions custom image order table\n");

sqlite3_exec(db->handle, "COMMIT", NULL, NULL, NULL);
new_version = 16;
} // maybe in the future, see commented out code elsewhere
// else if(version == XXX)
// {
Expand Down Expand Up @@ -1084,11 +1107,13 @@ static void _create_library_schema(dt_database_t *db)
"caption VARCHAR, description VARCHAR, license VARCHAR, sha1sum CHAR(40), "
"orientation INTEGER, histogram BLOB, lightmap BLOB, longitude REAL, "
"latitude REAL, altitude REAL, color_matrix BLOB, colorspace INTEGER, version INTEGER, "
"max_version INTEGER, write_timestamp INTEGER, history_end INTEGER)",
"max_version INTEGER, write_timestamp INTEGER, history_end INTEGER, position INTEGER)",
NULL, NULL, NULL);
sqlite3_exec(db->handle, "CREATE INDEX main.images_group_id_index ON images (group_id)", NULL, NULL, NULL);
sqlite3_exec(db->handle, "CREATE INDEX main.images_film_id_index ON images (film_id)", NULL, NULL, NULL);
sqlite3_exec(db->handle, "CREATE INDEX main.images_filename_index ON images (filename)", NULL, NULL, NULL);
sqlite3_exec(db->handle, "CREATE INDEX main.image_position_index ON images (position)", NULL, NULL, NULL);

////////////////////////////// selected_images
sqlite3_exec(db->handle, "CREATE TABLE main.selected_images (imgid INTEGER PRIMARY KEY)", NULL, NULL, NULL);
////////////////////////////// history
Expand Down
1 change: 1 addition & 0 deletions src/common/debug.h
Expand Up @@ -100,6 +100,7 @@
} while(0)

#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c) __DT_DEBUG_ASSERT__(sqlite3_bind_int(a, b, c))
#define DT_DEBUG_SQLITE3_BIND_INT64(a, b, c) __DT_DEBUG_ASSERT__(sqlite3_bind_int64(a, b, c))
#define DT_DEBUG_SQLITE3_BIND_DOUBLE(a, b, c) __DT_DEBUG_ASSERT__(sqlite3_bind_double(a, b, c))
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e) __DT_DEBUG_ASSERT__(sqlite3_bind_text(a, b, c, d, e))
#define DT_DEBUG_SQLITE3_BIND_BLOB(a, b, c, d, e) __DT_DEBUG_ASSERT__(sqlite3_bind_blob(a, b, c, d, e))
Expand Down

0 comments on commit 886fab0

Please sign in to comment.