Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
history_snapshot_repository.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20
21#include "database/database.h"
22#include "database/sql_debug.h"
23#include "system/macros.h"
24
25#include <sqlite3.h>
26
27/* Run one `?1 = snap_id, ?2 = imgid` statement to completion. Every query in this file has
28 * that shape, which is what makes the file short. */
29static gboolean _run_snap_imgid(const char *query, const int snap_id, const int32_t imgid,
30 const int expected)
31{
36 const gboolean ok = (sqlite3_step(stmt) == expected);
38 return ok;
39}
40
42{
44 // clang-format off
46 "SELECT MAX(id) FROM memory.undo_history WHERE imgid=?1", -1, &stmt, NULL);
47 // clang-format on
49
50 int snap_id = 0;
53 return snap_id;
54}
55
56gboolean dt_history_snapshot_repository_create(const int snap_id, const int32_t imgid,
57 const gboolean empty_history)
58{
59 gboolean all_ok = TRUE;
60
62
64 {
65 // insert a dummy undo_histroy to ensure proper snap_id later
66 // clang-format off
67 all_ok = _run_snap_imgid("INSERT INTO memory.undo_history"
68 " VALUES (?1, ?2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)",
69 snap_id, imgid, SQLITE_DONE);
70 // clang-format on
71 }
72 else
73 {
74 // copy current state into undo_history
75 // clang-format off
76 all_ok = _run_snap_imgid("INSERT INTO memory.undo_history"
77 " SELECT ?1, imgid, num, module, operation, op_params, enabled, "
78 " blendop_params, blendop_version, multi_priority, multi_name "
79 " FROM main.history"
80 " WHERE imgid=?2",
81 snap_id, imgid, SQLITE_DONE);
82
83 // copy current state into undo_masks_history
84 /* `&&` in this order, not the other: the original short-circuits, so once one copy
85 * has failed the rest are not attempted. The transaction rolls back either way, but
86 * this keeps the statement count identical. */
87 all_ok = all_ok && _run_snap_imgid("INSERT INTO memory.undo_masks_history"
88 " SELECT ?1, imgid, num, formid, form, name, version,"
89 " points, points_count, source"
90 " FROM main.masks_history"
91 " WHERE imgid=?2",
92 snap_id, imgid, SQLITE_DONE);
93
94 // copy the module order
95 all_ok = all_ok && _run_snap_imgid("INSERT INTO memory.undo_module_order"
96 " SELECT ?1, imgid, version, iop_list"
97 " FROM main.module_order"
98 " WHERE imgid=?2",
99 snap_id, imgid, SQLITE_DONE);
100 // clang-format on
101 }
102
103 if(all_ok)
105 else
107
108 return all_ok;
109}
110
111gboolean dt_history_snapshot_repository_restore(const int snap_id, const int32_t imgid)
112{
113 // clang-format off
114 gboolean all_ok = _run_snap_imgid("INSERT INTO main.history"
115 " SELECT imgid, num, module, operation, op_params, enabled, "
116 " blendop_params, blendop_version, multi_priority, multi_name "
117 " FROM memory.undo_history"
118 " WHERE imgid=?2 AND id=?1",
119 snap_id, imgid, SQLITE_DONE);
120
121 /* `&= ` in the original, which does NOT short-circuit: all three copies are attempted
122 * even after one fails. Kept. */
123 all_ok = _run_snap_imgid("INSERT INTO main.masks_history"
124 " SELECT imgid, num, formid, form, name, version, "
125 " points, points_count, source"
126 " FROM memory.undo_masks_history"
127 " WHERE imgid=?2 AND id=?1",
128 snap_id, imgid, SQLITE_DONE) && all_ok;
129
130 all_ok = _run_snap_imgid("INSERT INTO main.module_order"
131 " SELECT imgid, version, iop_list"
132 " FROM memory.undo_module_order"
133 " WHERE imgid=?2 AND id=?1",
134 snap_id, imgid, SQLITE_DONE) && all_ok;
135 // clang-format on
136
137 return all_ok;
138}
139
140void dt_history_snapshot_repository_clear(const int snap_id, const int32_t imgid)
141{
142 _run_snap_imgid("DELETE FROM memory.undo_history WHERE id=?1 AND imgid=?2",
143 snap_id, imgid, SQLITE_DONE);
144 _run_snap_imgid("DELETE FROM memory.undo_masks_history WHERE id=?1 AND imgid=?2",
145 snap_id, imgid, SQLITE_DONE);
146 _run_snap_imgid("DELETE FROM memory.undo_module_order WHERE id=?1 AND imgid=?2",
147 snap_id, imgid, SQLITE_DONE);
148}
149
150// clang-format off
151// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
152// vim: shiftwidth=2 expandtab tabstop=2 cindent
153// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
154// clang-format on
#define TRUE
Definition ashift_lsd.c:162
sqlite3 * dt_database_get_sqlite3_global(void)
Definition database.c:3753
void dt_database_rollback_transaction(void)
Definition database.c:4870
#define dt_database_start_transaction()
Definition database.h:290
#define dt_database_release_transaction()
Definition database.h:291
gboolean dt_history_snapshot_repository_restore(const int snap_id, const int32_t imgid)
Copy snapshot snap_id of imgid back over the live history tables.
void dt_history_snapshot_repository_clear(const int snap_id, const int32_t imgid)
Drop snapshot snap_id of imgid from all three undo tables.
gboolean dt_history_snapshot_repository_create(const int snap_id, const int32_t imgid, const gboolean empty_history)
Copy imgid's history, masks history and module order into the undo tables.
int dt_history_snapshot_repository_next_id(const int32_t imgid)
The id the next snapshot of imgid should use: one past the highest taken.
static gboolean _run_snap_imgid(const char *query, const int snap_id, const int32_t imgid, const int expected)
memory.undo_history, memory.undo_masks_history, memory.undo_module_order.
Checked wrappers around the sqlite3_* calls: trace the statement, assert the return code,...
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition sql_debug.h:137
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition sql_debug.h:145