Mercurial > hg > forks > geeqie
annotate src/dupe.c @ 2909:2e7fd08bfbe4
DEBUG_NAME() function for use with GTKInspector
This debug function can be used with GTKInspector to provide a visual
indication of where a widget is declared.
This is a documentation facility to aid developers new to the project.
Sample call:
GTK_DEBUG=interactive src/geeqie
author | Colin Clark <colin.clark@cclark.uk> |
---|---|
date | Thu, 14 Feb 2019 12:05:04 +0000 |
parents | b20a96b979a3 |
children |
rev | line source |
---|---|
9 | 1 /* |
2350
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
2 * Copyright (C) 2005 John Ellis |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
3 * Copyright (C) 2008 - 2016 The Geeqie Team |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
2350
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
7 * This program is free software; you can redistribute it and/or modify |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
8 * it under the terms of the GNU General Public License as published by |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
9 * the Free Software Foundation; either version 2 of the License, or |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
10 * (at your option) any later version. |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
11 * |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
12 * This program is distributed in the hope that it will be useful, |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
15 * GNU General Public License for more details. |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
16 * |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
17 * You should have received a copy of the GNU General Public License along |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
18 * with this program; if not, write to the Free Software Foundation, Inc., |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2331
diff
changeset
|
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
9 | 20 */ |
21 | |
281 | 22 #include "main.h" |
9 | 23 #include "dupe.h" |
24 | |
25 #include "cache.h" | |
26 #include "collect.h" | |
27 #include "collect-table.h" | |
28 #include "dnd.h" | |
29 #include "editors.h" | |
586
122fc2223b42
split filelist.c to filefilter.c and filedata.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
516
diff
changeset
|
30 #include "filedata.h" |
9 | 31 #include "image-load.h" |
32 #include "img-view.h" | |
33 #include "layout.h" | |
34 #include "layout_image.h" | |
2694 | 35 #include "layout_util.h" |
9 | 36 #include "md5-util.h" |
37 #include "menu.h" | |
1022
d09059a8b243
Move miscellaneous functions to their own files (new misc.[ch]).
Laurent Monin <geeqie@norz.org>
parents:
1012
diff
changeset
|
38 #include "misc.h" |
2860
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
39 #include "pixbuf_util.h" |
9 | 40 #include "print.h" |
41 #include "thumb.h" | |
42 #include "ui_fileops.h" | |
43 #include "ui_menu.h" | |
44 #include "ui_misc.h" | |
45 #include "ui_tree_edit.h" | |
904
ab63ec98b0f6
Move uri_*() functions to separate files: uri_utils.[ch]
Laurent Monin <geeqie@norz.org>
parents:
864
diff
changeset
|
46 #include "uri_utils.h" |
1022
d09059a8b243
Move miscellaneous functions to their own files (new misc.[ch]).
Laurent Monin <geeqie@norz.org>
parents:
1012
diff
changeset
|
47 #include "utilops.h" |
648
36e8da5a771d
Move some functions from main.[ch] to new window.[ch].
Laurent Monin <geeqie@norz.org>
parents:
586
diff
changeset
|
48 #include "window.h" |
9 | 49 |
50 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
51 | |
52 | |
53 #include <math.h> | |
54 | |
55 | |
1049
ba6a2b6650b1
enlarge the dupe window - patch by Klaus Ethgen
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1043
diff
changeset
|
56 #define DUPE_DEF_WIDTH 800 |
9 | 57 #define DUPE_DEF_HEIGHT 400 |
58 | |
59 /* column assignment order (simply change them here) */ | |
60 enum { | |
61 DUPE_COLUMN_POINTER = 0, | |
62 DUPE_COLUMN_RANK, | |
63 DUPE_COLUMN_THUMB, | |
64 DUPE_COLUMN_NAME, | |
65 DUPE_COLUMN_SIZE, | |
66 DUPE_COLUMN_DATE, | |
67 DUPE_COLUMN_DIMENSIONS, | |
68 DUPE_COLUMN_PATH, | |
69 DUPE_COLUMN_COLOR, | |
70 DUPE_COLUMN_COUNT /* total columns */ | |
71 }; | |
72 | |
73 | |
74 static GList *dupe_window_list = NULL; /* list of open DupeWindow *s */ | |
75 | |
76 /* | |
77 * Well, after adding the 'compare two sets' option things got a little sloppy in here | |
78 * because we have to account for two 'modes' everywhere. (be careful). | |
79 */ | |
80 | |
81 static void dupe_match_unlink(DupeItem *a, DupeItem *b); | |
82 static DupeItem *dupe_match_find_parent(DupeWindow *dw, DupeItem *child); | |
83 | |
84 static gint dupe_match(DupeItem *a, DupeItem *b, DupeMatchType mask, gdouble *rank, gint fast); | |
85 | |
86 static void dupe_thumb_step(DupeWindow *dw); | |
87 static gint dupe_check_cb(gpointer data); | |
88 | |
89 static void dupe_second_add(DupeWindow *dw, DupeItem *di); | |
90 static void dupe_second_remove(DupeWindow *dw, DupeItem *di); | |
91 static GtkWidget *dupe_menu_popup_second(DupeWindow *dw, DupeItem *di); | |
92 | |
93 static void dupe_dnd_init(DupeWindow *dw); | |
94 | |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
95 static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data); |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
96 |
9 | 97 /* |
98 * ------------------------------------------------------------------ | |
99 * Window updates | |
100 * ------------------------------------------------------------------ | |
101 */ | |
102 | |
103 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
104 static void dupe_window_update_count(DupeWindow *dw, gboolean count_only) |
9 | 105 { |
106 gchar *text; | |
107 | |
108 if (!dw->list) | |
109 { | |
110 text = g_strdup(_("Drop files to compare them.")); | |
111 } | |
112 else if (count_only) | |
113 { | |
114 text = g_strdup_printf(_("%d files"), g_list_length(dw->list)); | |
115 } | |
116 else | |
117 { | |
118 text = g_strdup_printf(_("%d matches found in %d files"), g_list_length(dw->dupes), g_list_length(dw->list)); | |
119 } | |
120 | |
121 if (dw->second_set) | |
122 { | |
123 gchar *buf = g_strconcat(text, " ", _("[set 1]"), NULL); | |
124 g_free(text); | |
125 text = buf; | |
126 } | |
127 gtk_label_set_text(GTK_LABEL(dw->status_label), text); | |
128 | |
129 g_free(text); | |
130 } | |
131 | |
132 static guint64 msec_time(void) | |
133 { | |
134 struct timeval tv; | |
135 | |
136 if (gettimeofday(&tv, NULL) == -1) return 0; | |
137 | |
138 return (guint64)tv.tv_sec * 1000000 + (guint64)tv.tv_usec; | |
139 } | |
140 | |
141 static gint dupe_iterations(gint n) | |
142 { | |
143 return (n * ((n + 1) / 2)); | |
144 } | |
145 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
146 static void dupe_window_update_progress(DupeWindow *dw, const gchar *status, gdouble value, gboolean force) |
9 | 147 { |
148 const gchar *status_text; | |
149 | |
150 if (status) | |
151 { | |
152 guint64 new_time = 0; | |
153 | |
154 if (dw->setup_n % 10 == 0) | |
155 { | |
156 new_time = msec_time() - dw->setup_time; | |
157 } | |
442 | 158 |
9 | 159 if (!force && |
160 value != 0.0 && | |
161 dw->setup_count > 0 && | |
162 new_time > 2000000) | |
163 { | |
164 gchar *buf; | |
165 gint t; | |
166 gint d; | |
167 guint32 rem; | |
168 | |
169 if (new_time - dw->setup_time_count < 250000) return; | |
170 dw->setup_time_count = new_time; | |
171 | |
172 if (dw->setup_done) | |
173 { | |
174 if (dw->second_set) | |
175 { | |
176 t = dw->setup_count; | |
177 d = dw->setup_count - dw->setup_n; | |
178 } | |
179 else | |
180 { | |
181 t = dupe_iterations(dw->setup_count); | |
182 d = dupe_iterations(dw->setup_count - dw->setup_n); | |
183 } | |
184 } | |
185 else | |
186 { | |
187 t = dw->setup_count; | |
188 d = dw->setup_count - dw->setup_n; | |
189 } | |
190 | |
191 rem = (t - d) ? ((gdouble)(dw->setup_time_count / 1000000) / (t - d)) * d : 0; | |
192 | |
193 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), value); | |
194 | |
195 buf = g_strdup_printf("%s %d:%02d ", status, rem / 60, rem % 60); | |
196 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(dw->extra_label), buf); | |
197 g_free(buf); | |
198 | |
199 return; | |
200 } | |
201 else if (force || | |
202 value == 0.0 || | |
203 dw->setup_count == 0 || | |
204 dw->setup_time_count == 0 || | |
205 (new_time > 0 && new_time - dw->setup_time_count >= 250000)) | |
206 { | |
207 if (dw->setup_time_count == 0) dw->setup_time_count = 1; | |
208 if (new_time > 0) dw->setup_time_count = new_time; | |
209 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), value); | |
210 status_text = status; | |
211 } | |
212 else | |
213 { | |
214 status_text = NULL; | |
215 } | |
442 | 216 } |
9 | 217 else |
218 { | |
219 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), 0.0); | |
220 status_text = " "; | |
221 } | |
222 | |
223 if (status_text) gtk_progress_bar_set_text(GTK_PROGRESS_BAR(dw->extra_label), status_text); | |
224 } | |
225 | |
226 static void widget_set_cursor(GtkWidget *widget, gint icon) | |
227 { | |
228 GdkCursor *cursor; | |
229 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
230 if (!gtk_widget_get_window(widget)) return; |
442 | 231 |
9 | 232 if (icon == -1) |
233 { | |
234 cursor = NULL; | |
235 } | |
236 else | |
237 { | |
513
6743a5928e09
Remove whitespace between function name and first parenthesis for the sake of consistency. (pass 2)
Laurent Monin <geeqie@norz.org>
parents:
512
diff
changeset
|
238 cursor = gdk_cursor_new(icon); |
9 | 239 } |
442 | 240 |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
241 gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); |
442 | 242 |
9 | 243 if (cursor) gdk_cursor_unref(cursor); |
244 } | |
245 | |
246 /* | |
247 * ------------------------------------------------------------------ | |
248 * row color utils | |
249 * ------------------------------------------------------------------ | |
250 */ | |
251 | |
252 static void dupe_listview_realign_colors(DupeWindow *dw) | |
253 { | |
254 GtkTreeModel *store; | |
255 GtkTreeIter iter; | |
256 gboolean color_set = TRUE; | |
257 DupeItem *parent = NULL; | |
1444 | 258 gboolean valid; |
9 | 259 |
260 store = gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview)); | |
261 valid = gtk_tree_model_get_iter_first(store, &iter); | |
262 while (valid) | |
263 { | |
264 DupeItem *child; | |
265 DupeItem *child_parent; | |
266 | |
267 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &child, -1); | |
268 child_parent = dupe_match_find_parent(dw, child); | |
269 if (!parent || parent != child_parent) | |
270 { | |
271 if (!parent) | |
272 { | |
273 /* keep the first row as it is */ | |
274 gtk_tree_model_get(store, &iter, DUPE_COLUMN_COLOR, &color_set, -1); | |
275 } | |
276 else | |
277 { | |
278 color_set = !color_set; | |
279 } | |
280 parent = dupe_match_find_parent(dw, child); | |
281 } | |
282 gtk_list_store_set(GTK_LIST_STORE(store), &iter, DUPE_COLUMN_COLOR, color_set, -1); | |
283 | |
284 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); | |
285 } | |
286 } | |
287 | |
288 /* | |
289 * ------------------------------------------------------------------ | |
290 * Dupe item utils | |
291 * ------------------------------------------------------------------ | |
292 */ | |
293 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
294 static DupeItem *dupe_item_new(FileData *fd) |
9 | 295 { |
296 DupeItem *di; | |
297 | |
298 di = g_new0(DupeItem, 1); | |
299 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
300 di->fd = file_data_ref(fd); |
9 | 301 di->group_rank = 0.0; |
302 | |
303 return di; | |
304 } | |
305 | |
306 static void dupe_item_free(DupeItem *di) | |
307 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
308 file_data_unref(di->fd); |
9 | 309 image_sim_free(di->simd); |
310 g_free(di->md5sum); | |
311 if (di->pixbuf) g_object_unref(di->pixbuf); | |
312 | |
313 g_free(di); | |
314 } | |
315 | |
316 static void dupe_list_free(GList *list) | |
317 { | |
318 GList *work = list; | |
319 while (work) | |
320 { | |
321 DupeItem *di = work->data; | |
322 work = work->next; | |
323 dupe_item_free(di); | |
324 } | |
325 g_list_free(list); | |
326 } | |
327 | |
259 | 328 /* |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
329 static DupeItem *dupe_item_find_fd_by_list(FileData *fd, GList *work) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
330 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
331 while (work) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
332 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
333 DupeItem *di = work->data; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
334 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
335 if (di->fd == fd) return di; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
336 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
337 work = work->next; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
338 } |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
339 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
340 return NULL; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
341 } |
259 | 342 */ |
343 | |
344 /* | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
345 static DupeItem *dupe_item_find_fd(DupeWindow *dw, FileData *fd) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
346 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
347 DupeItem *di; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
348 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
349 di = dupe_item_find_fd_by_list(fd, dw->list); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
350 if (!di && dw->second_set) di = dupe_item_find_fd_by_list(fd, dw->second_list); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
351 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
352 return di; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
353 } |
259 | 354 */ |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
355 |
9 | 356 static DupeItem *dupe_item_find_path_by_list(const gchar *path, GList *work) |
357 { | |
358 while (work) | |
359 { | |
360 DupeItem *di = work->data; | |
361 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
362 if (strcmp(di->fd->path, path) == 0) return di; |
9 | 363 |
364 work = work->next; | |
365 } | |
366 | |
367 return NULL; | |
368 } | |
369 | |
370 static DupeItem *dupe_item_find_path(DupeWindow *dw, const gchar *path) | |
371 { | |
372 DupeItem *di; | |
373 | |
374 di = dupe_item_find_path_by_list(path, dw->list); | |
375 if (!di && dw->second_set) di = dupe_item_find_path_by_list(path, dw->second_list); | |
376 | |
377 return di; | |
378 } | |
379 | |
380 /* | |
381 * ------------------------------------------------------------------ | |
382 * Image property cache | |
383 * ------------------------------------------------------------------ | |
384 */ | |
385 | |
386 static void dupe_item_read_cache(DupeItem *di) | |
387 { | |
388 gchar *path; | |
389 CacheData *cd; | |
390 | |
391 if (!di) return; | |
392 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
393 path = cache_find_location(CACHE_TYPE_SIM, di->fd->path); |
9 | 394 if (!path) return; |
395 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
396 if (filetime(di->fd->path) != filetime(path)) |
9 | 397 { |
398 g_free(path); | |
399 return; | |
400 } | |
401 | |
402 cd = cache_sim_data_load(path); | |
403 g_free(path); | |
404 | |
405 if (cd) | |
406 { | |
407 if (!di->simd && cd->sim) | |
408 { | |
409 di->simd = cd->sim; | |
410 cd->sim = NULL; | |
411 } | |
412 if (di->width == 0 && di->height == 0 && cd->dimensions) | |
413 { | |
414 di->width = cd->width; | |
415 di->height = cd->height; | |
416 } | |
417 if (!di->md5sum && cd->have_md5sum) | |
418 { | |
419 di->md5sum = md5_digest_to_text(cd->md5sum); | |
420 } | |
421 cache_sim_data_free(cd); | |
422 } | |
423 } | |
424 | |
425 static void dupe_item_write_cache(DupeItem *di) | |
426 { | |
427 gchar *base; | |
428 mode_t mode = 0755; | |
429 | |
430 if (!di) return; | |
431 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
432 base = cache_get_location(CACHE_TYPE_SIM, di->fd->path, FALSE, &mode); |
1148
db3cdb2b9681
Replace cache_ensure_dir_exists() by new recursive_mkdir_if_not_exists().
Laurent Monin <geeqie@norz.org>
parents:
1055
diff
changeset
|
433 if (recursive_mkdir_if_not_exists(base, mode)) |
9 | 434 { |
435 CacheData *cd; | |
436 | |
437 cd = cache_sim_data_new(); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
438 cd->path = cache_get_location(CACHE_TYPE_SIM, di->fd->path, TRUE, NULL); |
9 | 439 |
440 if (di->width != 0) cache_sim_data_set_dimensions(cd, di->width, di->height); | |
441 if (di->md5sum) | |
442 { | |
443 guchar digest[16]; | |
444 if (md5_digest_from_text(di->md5sum, digest)) cache_sim_data_set_md5sum(cd, digest); | |
445 } | |
446 if (di->simd) cache_sim_data_set_similarity(cd, di->simd); | |
447 | |
448 if (cache_sim_data_save(cd)) | |
449 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
450 filetime_set(cd->path, filetime(di->fd->path)); |
9 | 451 } |
452 cache_sim_data_free(cd); | |
453 } | |
454 g_free(base); | |
455 } | |
456 | |
457 /* | |
458 * ------------------------------------------------------------------ | |
459 * Window list utils | |
460 * ------------------------------------------------------------------ | |
461 */ | |
462 | |
463 static gint dupe_listview_find_item(GtkListStore *store, DupeItem *item, GtkTreeIter *iter) | |
464 { | |
1444 | 465 gboolean valid; |
9 | 466 gint row = 0; |
467 | |
468 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), iter); | |
469 while (valid) | |
470 { | |
471 DupeItem *item_n; | |
472 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, DUPE_COLUMN_POINTER, &item_n, -1); | |
473 if (item_n == item) return row; | |
474 | |
475 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter); | |
476 row++; | |
477 } | |
478 | |
479 return -1; | |
480 } | |
481 | |
482 static void dupe_listview_add(DupeWindow *dw, DupeItem *parent, DupeItem *child) | |
483 { | |
484 DupeItem *di; | |
485 gint row; | |
486 gchar *text[DUPE_COLUMN_COUNT]; | |
487 GtkListStore *store; | |
488 GtkTreeIter iter; | |
489 gboolean color_set = FALSE; | |
490 gint rank; | |
491 | |
492 if (!parent) return; | |
493 | |
494 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
495 | |
496 if (child) | |
497 { | |
498 DupeMatch *dm; | |
499 | |
500 row = dupe_listview_find_item(store, parent, &iter); | |
501 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, DUPE_COLUMN_COLOR, &color_set, -1); | |
502 | |
503 row++; | |
504 | |
505 if (child->group) | |
506 { | |
507 dm = child->group->data; | |
508 rank = (gint)floor(dm->rank); | |
509 } | |
510 else | |
511 { | |
512 rank = 1; | |
673
c9c2bc042e10
Do not use printf() directly but use new wrapper function log_printf() instead.
Laurent Monin <geeqie@norz.org>
parents:
671
diff
changeset
|
513 log_printf("NULL group in item!\n"); |
9 | 514 } |
515 } | |
516 else | |
517 { | |
518 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) | |
519 { | |
520 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, DUPE_COLUMN_COLOR, &color_set, -1); | |
521 color_set = !color_set; | |
522 } | |
523 else | |
524 { | |
525 color_set = FALSE; | |
526 } | |
527 row = 0; | |
528 rank = 0; | |
529 } | |
530 | |
531 di = (child) ? child : parent; | |
532 | |
533 if (!child && dw->second_set) | |
534 { | |
535 text[DUPE_COLUMN_RANK] = g_strdup("[1]"); | |
536 } | |
537 else if (rank == 0) | |
538 { | |
539 text[DUPE_COLUMN_RANK] = g_strdup((di->second) ? "(2)" : ""); | |
540 } | |
541 else | |
542 { | |
543 text[DUPE_COLUMN_RANK] = g_strdup_printf("%d%s", rank, (di->second) ? " (2)" : ""); | |
544 } | |
545 | |
546 text[DUPE_COLUMN_THUMB] = ""; | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
547 text[DUPE_COLUMN_NAME] = (gchar *)di->fd->name; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
548 text[DUPE_COLUMN_SIZE] = text_from_size(di->fd->size); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
549 text[DUPE_COLUMN_DATE] = (gchar *)text_from_time(di->fd->date); |
9 | 550 if (di->width > 0 && di->height > 0) |
551 { | |
552 text[DUPE_COLUMN_DIMENSIONS] = g_strdup_printf("%d x %d", di->width, di->height); | |
553 } | |
554 else | |
555 { | |
556 text[DUPE_COLUMN_DIMENSIONS] = g_strdup(""); | |
557 } | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
558 text[DUPE_COLUMN_PATH] = di->fd->path; |
9 | 559 text[DUPE_COLUMN_COLOR] = NULL; |
560 | |
561 gtk_list_store_insert(store, &iter, row); | |
562 gtk_list_store_set(store, &iter, | |
563 DUPE_COLUMN_POINTER, di, | |
564 DUPE_COLUMN_RANK, text[DUPE_COLUMN_RANK], | |
565 DUPE_COLUMN_THUMB, NULL, | |
566 DUPE_COLUMN_NAME, text[DUPE_COLUMN_NAME], | |
567 DUPE_COLUMN_SIZE, text[DUPE_COLUMN_SIZE], | |
568 DUPE_COLUMN_DATE, text[DUPE_COLUMN_DATE], | |
569 DUPE_COLUMN_DIMENSIONS, text[DUPE_COLUMN_DIMENSIONS], | |
570 DUPE_COLUMN_PATH, text[DUPE_COLUMN_PATH], | |
571 DUPE_COLUMN_COLOR, color_set, | |
572 -1); | |
573 | |
574 g_free(text[DUPE_COLUMN_RANK]); | |
575 g_free(text[DUPE_COLUMN_SIZE]); | |
576 g_free(text[DUPE_COLUMN_DIMENSIONS]); | |
577 } | |
578 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
579 static void dupe_listview_select_dupes(DupeWindow *dw, DupeSelectType parents); |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
580 |
9 | 581 static void dupe_listview_populate(DupeWindow *dw) |
582 { | |
583 GtkListStore *store; | |
584 GList *work; | |
585 | |
586 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
587 gtk_list_store_clear(store); | |
588 | |
589 work = g_list_last(dw->dupes); | |
590 while (work) | |
591 { | |
592 DupeItem *parent = work->data; | |
593 GList *temp; | |
594 | |
595 dupe_listview_add(dw, parent, NULL); | |
596 | |
597 temp = g_list_last(parent->group); | |
598 while (temp) | |
599 { | |
600 DupeMatch *dm = temp->data; | |
601 DupeItem *child; | |
602 | |
603 child = dm->di; | |
604 | |
605 dupe_listview_add(dw, parent, child); | |
606 | |
607 temp = temp->prev; | |
608 } | |
609 | |
610 work = work->prev; | |
611 } | |
612 | |
613 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(dw->listview)); | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
614 |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
615 if (options->duplicates_select_type == DUPE_SELECT_GROUP1) |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
616 { |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
617 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP1); |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
618 } |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
619 else if (options->duplicates_select_type == DUPE_SELECT_GROUP2) |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
620 { |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
621 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP2); |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
622 } |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
623 |
9 | 624 } |
625 | |
626 static void dupe_listview_remove(DupeWindow *dw, DupeItem *di) | |
627 { | |
628 GtkListStore *store; | |
629 GtkTreeIter iter; | |
630 gint row; | |
631 | |
632 if (!di) return; | |
633 | |
634 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
635 row = dupe_listview_find_item(store, di, &iter); | |
636 if (row < 0) return; | |
637 | |
638 tree_view_move_cursor_away(GTK_TREE_VIEW(dw->listview), &iter, TRUE); | |
639 gtk_list_store_remove(store, &iter); | |
640 | |
641 if (g_list_find(dw->dupes, di) != NULL) | |
642 { | |
643 if (!dw->color_frozen) dupe_listview_realign_colors(dw); | |
644 } | |
645 } | |
646 | |
647 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
648 static GList *dupe_listview_get_filelist(DupeWindow *dw, GtkWidget *listview) |
9 | 649 { |
650 GtkTreeModel *store; | |
651 GtkTreeIter iter; | |
1444 | 652 gboolean valid; |
9 | 653 GList *list = NULL; |
654 | |
655 store = gtk_tree_view_get_model(GTK_TREE_VIEW(listview)); | |
656 valid = gtk_tree_model_get_iter_first(store, &iter); | |
657 while (valid) | |
658 { | |
659 DupeItem *di; | |
660 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
661 list = g_list_prepend(list, file_data_ref(di->fd)); |
9 | 662 |
663 valid = gtk_tree_model_iter_next(store, &iter); | |
664 } | |
665 | |
666 return g_list_reverse(list); | |
667 } | |
668 | |
669 | |
670 static GList *dupe_listview_get_selection(DupeWindow *dw, GtkWidget *listview) | |
671 { | |
672 GtkTreeModel *store; | |
673 GtkTreeSelection *selection; | |
674 GList *slist; | |
675 GList *list = NULL; | |
676 GList *work; | |
677 | |
678 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); | |
679 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
680 work = slist; | |
681 while (work) | |
682 { | |
683 GtkTreePath *tpath = work->data; | |
684 DupeItem *di = NULL; | |
685 GtkTreeIter iter; | |
686 | |
687 gtk_tree_model_get_iter(store, &iter, tpath); | |
688 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
689 if (di) | |
690 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
691 list = g_list_prepend(list, file_data_ref(di->fd)); |
9 | 692 } |
693 work = work->next; | |
694 } | |
695 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
696 g_list_free(slist); | |
697 | |
698 return g_list_reverse(list); | |
699 } | |
700 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
701 static gboolean dupe_listview_item_is_selected(DupeWindow *dw, DupeItem *di, GtkWidget *listview) |
9 | 702 { |
703 GtkTreeModel *store; | |
704 GtkTreeSelection *selection; | |
705 GList *slist; | |
706 GList *work; | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
707 gboolean found = FALSE; |
9 | 708 |
709 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); | |
710 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
711 work = slist; | |
712 while (!found && work) | |
713 { | |
714 GtkTreePath *tpath = work->data; | |
715 DupeItem *di_n; | |
716 GtkTreeIter iter; | |
717 | |
718 gtk_tree_model_get_iter(store, &iter, tpath); | |
719 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di_n, -1); | |
720 if (di_n == di) found = TRUE; | |
721 work = work->next; | |
722 } | |
723 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
724 g_list_free(slist); | |
725 | |
726 return found; | |
727 } | |
728 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
729 static void dupe_listview_select_dupes(DupeWindow *dw, DupeSelectType parents) |
9 | 730 { |
731 GtkTreeModel *store; | |
732 GtkTreeSelection *selection; | |
733 GtkTreeIter iter; | |
1444 | 734 gboolean valid; |
9 | 735 |
736 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->listview)); | |
737 gtk_tree_selection_unselect_all(selection); | |
738 | |
739 store = gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview)); | |
740 valid = gtk_tree_model_get_iter_first(store, &iter); | |
741 while (valid) | |
742 { | |
743 DupeItem *di; | |
744 | |
745 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
746 if ((dupe_match_find_parent(dw, di) == di) == (parents == DUPE_SELECT_GROUP1)) |
9 | 747 { |
748 gtk_tree_selection_select_iter(selection, &iter); | |
749 } | |
750 valid = gtk_tree_model_iter_next(store, &iter); | |
751 } | |
752 } | |
753 | |
754 /* | |
755 * ------------------------------------------------------------------ | |
756 * Match group manipulation | |
757 * ------------------------------------------------------------------ | |
758 */ | |
759 | |
760 static DupeMatch *dupe_match_find_match(DupeItem *child, DupeItem *parent) | |
761 { | |
762 GList *work; | |
763 | |
764 work = parent->group; | |
765 while (work) | |
766 { | |
767 DupeMatch *dm = work->data; | |
768 if (dm->di == child) return dm; | |
769 work = work->next; | |
770 } | |
771 return NULL; | |
772 } | |
773 | |
774 static void dupe_match_link_child(DupeItem *child, DupeItem *parent, gdouble rank) | |
775 { | |
776 DupeMatch *dm; | |
777 | |
778 dm = g_new0(DupeMatch, 1); | |
779 dm->di = child; | |
780 dm->rank = rank; | |
781 parent->group = g_list_append(parent->group, dm); | |
782 } | |
783 | |
784 static void dupe_match_link(DupeItem *a, DupeItem *b, gdouble rank) | |
785 { | |
786 dupe_match_link_child(a, b, rank); | |
787 dupe_match_link_child(b, a, rank); | |
788 } | |
789 | |
790 static void dupe_match_unlink_child(DupeItem *child, DupeItem *parent) | |
791 { | |
792 DupeMatch *dm; | |
793 | |
794 dm = dupe_match_find_match(child, parent); | |
795 if (dm) | |
796 { | |
797 parent->group = g_list_remove(parent->group, dm); | |
798 g_free(dm); | |
799 } | |
800 } | |
801 | |
802 static void dupe_match_unlink(DupeItem *a, DupeItem *b) | |
803 { | |
804 dupe_match_unlink_child(a, b); | |
805 dupe_match_unlink_child(b, a); | |
806 } | |
807 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
808 static void dupe_match_link_clear(DupeItem *parent, gboolean unlink_children) |
9 | 809 { |
810 GList *work; | |
442 | 811 |
9 | 812 work = parent->group; |
813 while (work) | |
814 { | |
815 DupeMatch *dm = work->data; | |
816 work = work->next; | |
817 | |
818 if (unlink_children) dupe_match_unlink_child(parent, dm->di); | |
819 | |
820 g_free(dm); | |
821 } | |
822 | |
823 g_list_free(parent->group); | |
824 parent->group = NULL; | |
825 parent->group_rank = 0.0; | |
826 } | |
827 | |
828 static gint dupe_match_link_exists(DupeItem *child, DupeItem *parent) | |
829 { | |
830 return (dupe_match_find_match(child, parent) != NULL); | |
831 } | |
832 | |
833 static gdouble dupe_match_link_rank(DupeItem *child, DupeItem *parent) | |
834 { | |
835 DupeMatch *dm; | |
836 | |
837 dm = dupe_match_find_match(child, parent); | |
838 if (dm) return dm->rank; | |
839 | |
840 return 0.0; | |
841 } | |
842 | |
843 static DupeItem *dupe_match_highest_rank(DupeItem *child) | |
844 { | |
845 DupeMatch *dr; | |
846 GList *work; | |
847 | |
848 dr = NULL; | |
849 work = child->group; | |
850 while (work) | |
851 { | |
852 DupeMatch *dm = work->data; | |
853 if (!dr || dm->rank > dr->rank) dr = dm; | |
854 work = work->next; | |
855 } | |
856 | |
857 return (dr) ? dr->di : NULL; | |
858 } | |
859 | |
860 static void dupe_match_rank_update(DupeItem *parent) | |
861 { | |
862 GList *work; | |
863 gdouble rank = 0.0; | |
864 gint c = 0; | |
865 | |
866 work = parent->group; | |
867 while (work) | |
868 { | |
869 DupeMatch *dm = work->data; | |
870 work = work->next; | |
871 rank += dm->rank; | |
872 c++; | |
873 } | |
874 | |
875 if (c > 0) | |
876 { | |
877 parent->group_rank = rank / c; | |
878 } | |
879 else | |
880 { | |
881 parent->group_rank = 0.0; | |
882 } | |
883 } | |
884 | |
885 static DupeItem *dupe_match_find_parent(DupeWindow *dw, DupeItem *child) | |
886 { | |
887 GList *work; | |
888 | |
889 if (g_list_find(dw->dupes, child)) return child; | |
890 | |
891 work = child->group; | |
892 while (work) | |
893 { | |
894 DupeMatch *dm = work->data; | |
895 if (g_list_find(dw->dupes, dm->di)) return dm->di; | |
896 work = work->next; | |
897 } | |
898 | |
899 return NULL; | |
900 } | |
901 | |
902 static void dupe_match_reset_list(GList *work) | |
903 { | |
904 while (work) | |
905 { | |
906 DupeItem *di = work->data; | |
907 work = work->next; | |
908 | |
909 dupe_match_link_clear(di, FALSE); | |
910 } | |
911 } | |
912 | |
913 static void dupe_match_reparent(DupeWindow *dw, DupeItem *old, DupeItem *new) | |
914 { | |
915 GList *work; | |
916 | |
917 if (!old || !new || !dupe_match_link_exists(old, new)) return; | |
918 | |
919 dupe_match_link_clear(new, TRUE); | |
920 work = old->group; | |
921 while (work) | |
922 { | |
923 DupeMatch *dm = work->data; | |
924 dupe_match_unlink_child(old, dm->di); | |
925 dupe_match_link_child(new, dm->di, dm->rank); | |
926 work = work->next; | |
927 } | |
928 | |
929 new->group = old->group; | |
930 old->group = NULL; | |
931 | |
932 work = g_list_find(dw->dupes, old); | |
933 if (work) work->data = new; | |
934 } | |
935 | |
936 static void dupe_match_print_group(DupeItem *di) | |
937 { | |
938 GList *work; | |
939 | |
673
c9c2bc042e10
Do not use printf() directly but use new wrapper function log_printf() instead.
Laurent Monin <geeqie@norz.org>
parents:
671
diff
changeset
|
940 log_printf("+ %f %s\n", di->group_rank, di->fd->name); |
9 | 941 |
942 work = di->group; | |
943 while (work) | |
944 { | |
945 DupeMatch *dm = work->data; | |
946 work = work->next; | |
947 | |
673
c9c2bc042e10
Do not use printf() directly but use new wrapper function log_printf() instead.
Laurent Monin <geeqie@norz.org>
parents:
671
diff
changeset
|
948 log_printf(" %f %s\n", dm->rank, dm->di->fd->name); |
9 | 949 } |
950 | |
673
c9c2bc042e10
Do not use printf() directly but use new wrapper function log_printf() instead.
Laurent Monin <geeqie@norz.org>
parents:
671
diff
changeset
|
951 log_printf("\n"); |
9 | 952 } |
953 | |
954 static void dupe_match_print_list(GList *list) | |
955 { | |
956 GList *work; | |
957 | |
958 work = list; | |
959 while (work) | |
960 { | |
961 DupeItem *di = work->data; | |
962 dupe_match_print_group(di); | |
963 work = work->next; | |
964 } | |
965 } | |
966 | |
967 /* level 3, unlinking and orphan handling */ | |
968 static GList *dupe_match_unlink_by_rank(DupeItem *child, DupeItem *parent, GList *list, DupeWindow *dw) | |
969 { | |
970 DupeItem *best; | |
971 | |
972 best = dupe_match_highest_rank(parent); | |
973 if (best == child || dupe_match_highest_rank(child) == parent) | |
974 { | |
975 GList *work; | |
976 gdouble rank; | |
977 | |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
978 DEBUG_2("link found %s to %s [%d]", child->fd->name, parent->fd->name, g_list_length(parent->group)); |
9 | 979 |
980 work = parent->group; | |
981 while (work) | |
982 { | |
983 DupeMatch *dm = work->data; | |
984 DupeItem *orphan; | |
985 | |
986 work = work->next; | |
987 orphan = dm->di; | |
988 if (orphan != child && g_list_length(orphan->group) < 2) | |
989 { | |
990 dupe_match_link_clear(orphan, TRUE); | |
991 if (!dw->second_set || orphan->second) | |
992 { | |
993 dupe_match(orphan, child, dw->match_mask, &rank, FALSE); | |
994 dupe_match_link(orphan, child, rank); | |
995 } | |
996 list = g_list_remove(list, orphan); | |
997 } | |
998 } | |
442 | 999 |
9 | 1000 rank = dupe_match_link_rank(child, parent); |
1001 dupe_match_link_clear(parent, TRUE); | |
1002 dupe_match_link(child, parent, rank); | |
1003 list = g_list_remove(list, parent); | |
1004 } | |
1005 else | |
1006 { | |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
1007 DEBUG_2("unlinking %s and %s", child->fd->name, parent->fd->name); |
442 | 1008 |
9 | 1009 dupe_match_unlink(child, parent); |
1010 } | |
1011 | |
1012 return list; | |
1013 } | |
1014 | |
1015 /* level 2 */ | |
1016 static GList *dupe_match_group_filter(GList *list, DupeItem *di, DupeWindow *dw) | |
1017 { | |
1018 GList *work; | |
1019 | |
1020 work = g_list_last(di->group); | |
1021 while (work) | |
1022 { | |
1023 DupeMatch *dm = work->data; | |
1024 work = work->prev; | |
1025 list = dupe_match_unlink_by_rank(di, dm->di, list, dw); | |
1026 } | |
1027 | |
1028 return list; | |
1029 } | |
1030 | |
1031 /* level 1 (top) */ | |
1032 static GList *dupe_match_group_trim(GList *list, DupeWindow *dw) | |
1033 { | |
1034 GList *work; | |
1035 | |
1036 work = list; | |
1037 while (work) | |
1038 { | |
1039 DupeItem *di = work->data; | |
1040 if (!di->second) list = dupe_match_group_filter(list, di, dw); | |
1041 work = work->next; | |
1042 if (di->second) list = g_list_remove(list, di); | |
1043 } | |
1044 | |
1045 return list; | |
1046 } | |
1047 | |
1048 static gint dupe_match_sort_groups_cb(gconstpointer a, gconstpointer b) | |
1049 { | |
1050 DupeMatch *da = (DupeMatch *)a; | |
1051 DupeMatch *db = (DupeMatch *)b; | |
1052 | |
1053 if (da->rank > db->rank) return -1; | |
1054 if (da->rank < db->rank) return 1; | |
1055 return 0; | |
1056 } | |
1057 | |
1058 static void dupe_match_sort_groups(GList *list) | |
1059 { | |
1060 GList *work; | |
1061 | |
1062 work = list; | |
1063 while (work) | |
1064 { | |
1065 DupeItem *di = work->data; | |
1066 di->group = g_list_sort(di->group, dupe_match_sort_groups_cb); | |
1067 work = work->next; | |
1068 } | |
1069 } | |
1070 | |
2489
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1071 static gint dupe_match_totals_sort_cb(gconstpointer a, gconstpointer b) |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1072 { |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1073 DupeItem *da = (DupeItem *)a; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1074 DupeItem *db = (DupeItem *)b; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1075 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1076 if (g_list_length(da->group) > g_list_length(db->group)) return -1; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1077 if (g_list_length(da->group) < g_list_length(db->group)) return 1; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1078 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1079 if (da->group_rank < db->group_rank) return -1; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1080 if (da->group_rank > db->group_rank) return 1; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1081 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1082 return 0; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1083 } |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1084 |
9 | 1085 static gint dupe_match_rank_sort_cb(gconstpointer a, gconstpointer b) |
1086 { | |
1087 DupeItem *da = (DupeItem *)a; | |
1088 DupeItem *db = (DupeItem *)b; | |
1089 | |
1090 if (da->group_rank > db->group_rank) return -1; | |
1091 if (da->group_rank < db->group_rank) return 1; | |
1092 return 0; | |
1093 } | |
1094 | |
1095 /* returns allocated GList of dupes sorted by rank */ | |
1096 static GList *dupe_match_rank_sort(GList *source_list) | |
1097 { | |
1098 GList *list = NULL; | |
1099 GList *work; | |
1100 | |
1101 work = source_list; | |
1102 while (work) | |
1103 { | |
1104 DupeItem *di = work->data; | |
1105 | |
1106 if (di->group) | |
1107 { | |
1108 dupe_match_rank_update(di); | |
1109 list = g_list_prepend(list, di); | |
1110 } | |
442 | 1111 |
9 | 1112 work = work->next; |
1113 } | |
1114 | |
1115 return g_list_sort(list, dupe_match_rank_sort_cb); | |
1116 } | |
1117 | |
2489
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1118 /* returns allocated GList of dupes sorted by totals */ |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1119 static GList *dupe_match_totals_sort(GList *source_list) |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1120 { |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1121 source_list = g_list_sort(source_list, dupe_match_totals_sort_cb); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1122 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1123 source_list = g_list_first(source_list); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1124 return g_list_reverse(source_list); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1125 } |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1126 |
9 | 1127 static void dupe_match_rank(DupeWindow *dw) |
1128 { | |
1129 GList *list; | |
1130 | |
1131 list = dupe_match_rank_sort(dw->list); | |
1132 | |
507
7408e89b601d
Move debug macros from main.h to new debug.h.
Laurent Monin <geeqie@norz.org>
parents:
506
diff
changeset
|
1133 if (required_debug_level(2)) dupe_match_print_list(list); |
495
cbe33f121dea
Introduce macros to display debug messages.
Laurent Monin <geeqie@norz.org>
parents:
479
diff
changeset
|
1134 |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
1135 DEBUG_1("Similar items: %d", g_list_length(list)); |
9 | 1136 list = dupe_match_group_trim(list, dw); |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
1137 DEBUG_1("Unique groups: %d", g_list_length(list)); |
9 | 1138 |
1139 dupe_match_sort_groups(list); | |
1140 | |
507
7408e89b601d
Move debug macros from main.h to new debug.h.
Laurent Monin <geeqie@norz.org>
parents:
506
diff
changeset
|
1141 if (required_debug_level(2)) dupe_match_print_list(list); |
9 | 1142 |
1143 list = dupe_match_rank_sort(list); | |
2489
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1144 if (options->sort_totals) |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1145 { |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1146 list = dupe_match_totals_sort(list); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1147 } |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
1148 if (required_debug_level(2)) dupe_match_print_list(list); |
9 | 1149 |
1150 g_list_free(dw->dupes); | |
1151 dw->dupes = list; | |
1152 } | |
1153 | |
1154 /* | |
1155 * ------------------------------------------------------------------ | |
1156 * Match group tests | |
1157 * ------------------------------------------------------------------ | |
1158 */ | |
1159 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
1160 static gboolean dupe_match(DupeItem *a, DupeItem *b, DupeMatchType mask, gdouble *rank, gint fast) |
9 | 1161 { |
1162 *rank = 0.0; | |
1163 | |
2011
8d6f372a067b
Ignore duplicates with same path
cybjit <cybjit@gmail.com>
parents:
1810
diff
changeset
|
1164 if (a->fd->path == b->fd->path) return FALSE; |
9 | 1165 |
1166 if (mask & DUPE_MATCH_PATH) | |
1167 { | |
786
cdcd3668e870
Compare paths using utf8_collate_key() since paths are utf8-encoded.
Laurent Monin <geeqie@norz.org>
parents:
785
diff
changeset
|
1168 if (utf8_compare(a->fd->path, b->fd->path, TRUE) != 0) return FALSE; |
9 | 1169 } |
1170 if (mask & DUPE_MATCH_NAME) | |
1171 { | |
785
9c54f243c2c6
Use uft8_collate_key() to sort utf8 strings.
Laurent Monin <geeqie@norz.org>
parents:
783
diff
changeset
|
1172 if (strcmp(a->fd->collate_key_name, b->fd->collate_key_name) != 0) return FALSE; |
9 | 1173 } |
264
6c3cf7eb45aa
Add the possibility to match duplicates on the name but ignoring the case.
Laurent Monin <geeqie@norz.org>
parents:
259
diff
changeset
|
1174 if (mask & DUPE_MATCH_NAME_CI) |
6c3cf7eb45aa
Add the possibility to match duplicates on the name but ignoring the case.
Laurent Monin <geeqie@norz.org>
parents:
259
diff
changeset
|
1175 { |
785
9c54f243c2c6
Use uft8_collate_key() to sort utf8 strings.
Laurent Monin <geeqie@norz.org>
parents:
783
diff
changeset
|
1176 if (strcmp(a->fd->collate_key_name_nocase, b->fd->collate_key_name_nocase) != 0) return FALSE; |
264
6c3cf7eb45aa
Add the possibility to match duplicates on the name but ignoring the case.
Laurent Monin <geeqie@norz.org>
parents:
259
diff
changeset
|
1177 } |
9 | 1178 if (mask & DUPE_MATCH_SIZE) |
1179 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1180 if (a->fd->size != b->fd->size) return FALSE; |
9 | 1181 } |
1182 if (mask & DUPE_MATCH_DATE) | |
1183 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1184 if (a->fd->date != b->fd->date) return FALSE; |
9 | 1185 } |
1186 if (mask & DUPE_MATCH_SUM) | |
1187 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1188 if (!a->md5sum) a->md5sum = md5_text_from_file_utf8(a->fd->path, ""); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1189 if (!b->md5sum) b->md5sum = md5_text_from_file_utf8(b->fd->path, ""); |
9 | 1190 if (a->md5sum[0] == '\0' || |
1191 b->md5sum[0] == '\0' || | |
1192 strcmp(a->md5sum, b->md5sum) != 0) return FALSE; | |
1193 } | |
1194 if (mask & DUPE_MATCH_DIM) | |
1195 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1196 if (a->width == 0) image_load_dimensions(a->fd, &a->width, &a->height); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1197 if (b->width == 0) image_load_dimensions(b->fd, &b->width, &b->height); |
9 | 1198 if (a->width != b->width || a->height != b->height) return FALSE; |
1199 } | |
1200 if (mask & DUPE_MATCH_SIM_HIGH || | |
1201 mask & DUPE_MATCH_SIM_MED || | |
1202 mask & DUPE_MATCH_SIM_LOW || | |
1203 mask & DUPE_MATCH_SIM_CUSTOM) | |
1204 { | |
1205 gdouble f; | |
1206 gdouble m; | |
1207 | |
1208 if (mask & DUPE_MATCH_SIM_HIGH) m = 0.95; | |
1209 else if (mask & DUPE_MATCH_SIM_MED) m = 0.90; | |
342
de6de19bd03a
Rename dupe_custom_threshold option to duplicates_similarity_threshold.
Laurent Monin <geeqie@norz.org>
parents:
333
diff
changeset
|
1210 else if (mask & DUPE_MATCH_SIM_CUSTOM) m = (gdouble)options->duplicates_similarity_threshold / 100.0; |
9 | 1211 else m = 0.85; |
1212 | |
1213 if (fast) | |
1214 { | |
1215 f = image_sim_compare_fast(a->simd, b->simd, m); | |
1216 } | |
1217 else | |
1218 { | |
1219 f = image_sim_compare(a->simd, b->simd); | |
1220 } | |
1221 | |
1222 *rank = f * 100.0; | |
1223 | |
1224 if (f < m) return FALSE; | |
1225 | |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
1226 DEBUG_3("similar: %32s %32s = %f", a->fd->name, b->fd->name, f); |
9 | 1227 } |
1228 | |
1229 return TRUE; | |
1230 } | |
1231 | |
1232 static void dupe_list_check_match(DupeWindow *dw, DupeItem *needle, GList *start) | |
1233 { | |
1234 GList *work; | |
1235 | |
1236 if (dw->second_set) | |
1237 { | |
1238 work = dw->second_list; | |
1239 } | |
1240 else if (start) | |
1241 { | |
1242 work = start; | |
1243 } | |
1244 else | |
1245 { | |
1246 work = g_list_last(dw->list); | |
1247 } | |
1248 | |
1249 while (work) | |
1250 { | |
1251 DupeItem *di = work->data; | |
1252 | |
1253 /* speed opt: forward for second set, back for simple compare */ | |
1254 if (dw->second_set) | |
1255 work = work->next; | |
1256 else | |
1257 work = work->prev; | |
1258 | |
1259 if (!dupe_match_link_exists(needle, di)) | |
1260 { | |
1261 gdouble rank; | |
1262 | |
1263 if (dupe_match(di, needle, dw->match_mask, &rank, TRUE)) | |
1264 { | |
1265 dupe_match_link(di, needle, rank); | |
1266 } | |
1267 } | |
1268 } | |
1269 } | |
1270 | |
1271 /* | |
1272 * ------------------------------------------------------------------ | |
1273 * Thumbnail handling | |
1274 * ------------------------------------------------------------------ | |
1275 */ | |
1276 | |
1277 static void dupe_listview_set_thumb(DupeWindow *dw, DupeItem *di, GtkTreeIter *iter) | |
1278 { | |
1279 GtkListStore *store; | |
1280 GtkTreeIter iter_n; | |
1281 | |
1282 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
1283 if (!iter) | |
1284 { | |
1285 if (dupe_listview_find_item(store, di, &iter_n) >= 0) | |
1286 { | |
1287 iter = &iter_n; | |
1288 } | |
1289 } | |
1290 | |
1291 if (iter) gtk_list_store_set(store, iter, DUPE_COLUMN_THUMB, di->pixbuf, -1); | |
1292 } | |
1293 | |
1294 static void dupe_thumb_do(DupeWindow *dw) | |
1295 { | |
1296 DupeItem *di; | |
1297 | |
1298 if (!dw->thumb_loader || !dw->thumb_item) return; | |
1299 di = dw->thumb_item; | |
1300 | |
1301 if (di->pixbuf) g_object_unref(di->pixbuf); | |
864
83be8234df2d
added pixbuf_fallback function
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
838
diff
changeset
|
1302 di->pixbuf = thumb_loader_get_pixbuf(dw->thumb_loader); |
9 | 1303 |
1304 dupe_listview_set_thumb(dw, di, NULL); | |
1305 } | |
1306 | |
1307 static void dupe_thumb_error_cb(ThumbLoader *tl, gpointer data) | |
1308 { | |
1309 DupeWindow *dw = data; | |
1310 | |
1311 dupe_thumb_do(dw); | |
1312 dupe_thumb_step(dw); | |
1313 } | |
1314 | |
1315 static void dupe_thumb_done_cb(ThumbLoader *tl, gpointer data) | |
1316 { | |
1317 DupeWindow *dw = data; | |
1318 | |
1319 dupe_thumb_do(dw); | |
1320 dupe_thumb_step(dw); | |
1321 } | |
1322 | |
1323 static void dupe_thumb_step(DupeWindow *dw) | |
1324 { | |
1325 GtkTreeModel *store; | |
1326 GtkTreeIter iter; | |
1327 DupeItem *di = NULL; | |
1444 | 1328 gboolean valid; |
9 | 1329 gint row = 0; |
1330 gint length = 0; | |
1331 | |
1332 store = gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview)); | |
1333 valid = gtk_tree_model_get_iter_first(store, &iter); | |
1334 | |
1335 while (!di && valid) | |
1336 { | |
1337 GdkPixbuf *pixbuf; | |
1338 | |
1339 length++; | |
1340 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, DUPE_COLUMN_THUMB, &pixbuf, -1); | |
1341 if (pixbuf || di->pixbuf) | |
1342 { | |
1343 if (!pixbuf) gtk_list_store_set(GTK_LIST_STORE(store), &iter, DUPE_COLUMN_THUMB, di->pixbuf, -1); | |
1344 row++; | |
1345 di = NULL; | |
1346 } | |
1347 valid = gtk_tree_model_iter_next(store, &iter); | |
1348 } | |
1349 if (valid) | |
1350 { | |
1351 while (gtk_tree_model_iter_next(store, &iter)) length++; | |
1352 } | |
1353 | |
1354 if (!di) | |
1355 { | |
1356 dw->thumb_item = NULL; | |
1357 thumb_loader_free(dw->thumb_loader); | |
1358 dw->thumb_loader = NULL; | |
1359 | |
1360 dupe_window_update_progress(dw, NULL, 0.0, FALSE); | |
1361 return; | |
1362 } | |
1363 | |
1364 dupe_window_update_progress(dw, _("Loading thumbs..."), | |
1365 length == 0 ? 0.0 : (gdouble)(row) / length, FALSE); | |
1366 | |
1367 dw->thumb_item = di; | |
1368 thumb_loader_free(dw->thumb_loader); | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1369 dw->thumb_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height); |
9 | 1370 |
1371 thumb_loader_set_callbacks(dw->thumb_loader, | |
1372 dupe_thumb_done_cb, | |
1373 dupe_thumb_error_cb, | |
1374 NULL, | |
1375 dw); | |
1376 | |
1377 /* start it */ | |
838
fd3a200281f6
use FileData in thumb_loader
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
803
diff
changeset
|
1378 if (!thumb_loader_start(dw->thumb_loader, di->fd)) |
9 | 1379 { |
1380 /* error, handle it, do next */ | |
506
03d66738b225
Handle the newline in DEBUG_N() macro instead of adding one
Laurent Monin <geeqie@norz.org>
parents:
497
diff
changeset
|
1381 DEBUG_1("error loading thumb for %s", di->fd->path); |
9 | 1382 dupe_thumb_do(dw); |
1383 dupe_thumb_step(dw); | |
1384 } | |
1385 } | |
1386 | |
1387 /* | |
1388 * ------------------------------------------------------------------ | |
1389 * Dupe checking loop | |
1390 * ------------------------------------------------------------------ | |
1391 */ | |
1392 | |
1393 static void dupe_check_stop(DupeWindow *dw) | |
1394 { | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1395 if (dw->idle_id || dw->img_loader || dw->thumb_loader) |
9 | 1396 { |
1397 g_source_remove(dw->idle_id); | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1398 dw->idle_id = 0; |
9 | 1399 dupe_window_update_progress(dw, NULL, 0.0, FALSE); |
1400 widget_set_cursor(dw->listview, -1); | |
1401 } | |
1402 | |
1403 thumb_loader_free(dw->thumb_loader); | |
1404 dw->thumb_loader = NULL; | |
1405 | |
1406 image_loader_free(dw->img_loader); | |
1407 dw->img_loader = NULL; | |
1408 } | |
1409 | |
1410 static void dupe_loader_done_cb(ImageLoader *il, gpointer data) | |
1411 { | |
1412 DupeWindow *dw = data; | |
1413 GdkPixbuf *pixbuf; | |
1414 | |
1415 pixbuf = image_loader_get_pixbuf(il); | |
1416 | |
1417 if (dw->setup_point) | |
1418 { | |
1419 DupeItem *di = dw->setup_point->data; | |
1420 | |
1421 if (!di->simd) | |
1422 { | |
1423 di->simd = image_sim_new_from_pixbuf(pixbuf); | |
1424 } | |
1425 else | |
1426 { | |
1427 image_sim_fill_data(di->simd, pixbuf); | |
1428 } | |
1429 | |
1430 if (di->width == 0 && di->height == 0) | |
1431 { | |
1432 di->width = gdk_pixbuf_get_width(pixbuf); | |
1433 di->height = gdk_pixbuf_get_height(pixbuf); | |
1434 } | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1435 if (options->thumbnails.enable_caching) |
9 | 1436 { |
1437 dupe_item_write_cache(di); | |
1438 } | |
1439 | |
1440 image_sim_alternate_processing(di->simd); | |
1441 } | |
1442 | |
1443 image_loader_free(dw->img_loader); | |
1444 dw->img_loader = NULL; | |
1445 | |
1446 dw->idle_id = g_idle_add(dupe_check_cb, dw); | |
1447 } | |
1448 | |
1449 static void dupe_setup_reset(DupeWindow *dw) | |
1450 { | |
1451 dw->setup_point = NULL; | |
1452 dw->setup_n = 0; | |
1453 dw->setup_time = msec_time(); | |
1454 dw->setup_time_count = 0; | |
1455 } | |
1456 | |
1457 static GList *dupe_setup_point_step(DupeWindow *dw, GList *p) | |
1458 { | |
1459 if (!p) return NULL; | |
1460 | |
1461 if (p->next) return p->next; | |
1462 | |
1463 if (dw->second_set && g_list_first(p) == dw->list) return dw->second_list; | |
1464 | |
1465 return NULL; | |
1466 } | |
1467 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
1468 static gboolean dupe_check_cb(gpointer data) |
9 | 1469 { |
1470 DupeWindow *dw = data; | |
1471 | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1472 if (!dw->idle_id) return FALSE; |
9 | 1473 |
1474 if (!dw->setup_done) | |
1475 { | |
1476 if ((dw->match_mask & DUPE_MATCH_SUM) && | |
1477 !(dw->setup_mask & DUPE_MATCH_SUM) ) | |
1478 { | |
1479 if (!dw->setup_point) dw->setup_point = dw->list; | |
1480 | |
1481 while (dw->setup_point) | |
1482 { | |
1483 DupeItem *di = dw->setup_point->data; | |
1484 | |
1485 dw->setup_point = dupe_setup_point_step(dw, dw->setup_point); | |
1486 dw->setup_n++; | |
1487 | |
1488 if (!di->md5sum) | |
1489 { | |
1490 dupe_window_update_progress(dw, _("Reading checksums..."), | |
1491 dw->setup_count == 0 ? 0.0 : (gdouble)(dw->setup_n - 1) / dw->setup_count, FALSE); | |
1492 | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1493 if (options->thumbnails.enable_caching) |
9 | 1494 { |
1495 dupe_item_read_cache(di); | |
1496 if (di->md5sum) return TRUE; | |
1497 } | |
1498 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1499 di->md5sum = md5_text_from_file_utf8(di->fd->path, ""); |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1500 if (options->thumbnails.enable_caching) |
9 | 1501 { |
1502 dupe_item_write_cache(di); | |
1503 } | |
1504 return TRUE; | |
1505 } | |
1506 } | |
1507 dw->setup_mask |= DUPE_MATCH_SUM; | |
1508 dupe_setup_reset(dw); | |
1509 } | |
1510 if ((dw->match_mask & DUPE_MATCH_DIM) && | |
1511 !(dw->setup_mask & DUPE_MATCH_DIM) ) | |
1512 { | |
1513 if (!dw->setup_point) dw->setup_point = dw->list; | |
1514 | |
1515 while (dw->setup_point) | |
1516 { | |
1517 DupeItem *di = dw->setup_point->data; | |
1518 | |
1519 dw->setup_point = dupe_setup_point_step(dw, dw->setup_point); | |
1520 dw->setup_n++; | |
1521 if (di->width == 0 && di->height == 0) | |
1522 { | |
1523 dupe_window_update_progress(dw, _("Reading dimensions..."), | |
1524 dw->setup_count == 0 ? 0.0 : (gdouble)(dw->setup_n - 1) / dw->setup_count, FALSE); | |
1525 | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1526 if (options->thumbnails.enable_caching) |
9 | 1527 { |
1528 dupe_item_read_cache(di); | |
1529 if (di->width != 0 || di->height != 0) return TRUE; | |
1530 } | |
1531 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1532 image_load_dimensions(di->fd, &di->width, &di->height); |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1533 if (options->thumbnails.enable_caching) |
9 | 1534 { |
1535 dupe_item_write_cache(di); | |
1536 } | |
1537 return TRUE; | |
1538 } | |
1539 } | |
1540 dw->setup_mask |= DUPE_MATCH_DIM; | |
1541 dupe_setup_reset(dw); | |
1542 } | |
1543 if ((dw->match_mask & DUPE_MATCH_SIM_HIGH || | |
1544 dw->match_mask & DUPE_MATCH_SIM_MED || | |
1545 dw->match_mask & DUPE_MATCH_SIM_LOW || | |
1546 dw->match_mask & DUPE_MATCH_SIM_CUSTOM) && | |
1547 !(dw->setup_mask & DUPE_MATCH_SIM_MED) ) | |
1548 { | |
1549 if (!dw->setup_point) dw->setup_point = dw->list; | |
1550 | |
1551 while (dw->setup_point) | |
1552 { | |
1553 DupeItem *di = dw->setup_point->data; | |
1554 | |
1555 if (!di->simd) | |
1556 { | |
1557 dupe_window_update_progress(dw, _("Reading similarity data..."), | |
1558 dw->setup_count == 0 ? 0.0 : (gdouble)dw->setup_n / dw->setup_count, FALSE); | |
1559 | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
1560 if (options->thumbnails.enable_caching) |
9 | 1561 { |
1562 dupe_item_read_cache(di); | |
1563 if (cache_sim_data_filled(di->simd)) | |
1564 { | |
1565 image_sim_alternate_processing(di->simd); | |
1566 return TRUE; | |
1567 } | |
1568 } | |
1569 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1570 dw->img_loader = image_loader_new(di->fd); |
9 | 1571 image_loader_set_buffer_size(dw->img_loader, 8); |
1346
b3378273091e
No space between function name and first parenthesis, it eases greping (see CODING).
Laurent Monin <geeqie@norz.org>
parents:
1292
diff
changeset
|
1572 g_signal_connect(G_OBJECT(dw->img_loader), "error", (GCallback)dupe_loader_done_cb, dw); |
b3378273091e
No space between function name and first parenthesis, it eases greping (see CODING).
Laurent Monin <geeqie@norz.org>
parents:
1292
diff
changeset
|
1573 g_signal_connect(G_OBJECT(dw->img_loader), "done", (GCallback)dupe_loader_done_cb, dw); |
1012
409b52dfe683
converted image loader to a GObject and use signals for notification
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
904
diff
changeset
|
1574 |
409b52dfe683
converted image loader to a GObject and use signals for notification
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
904
diff
changeset
|
1575 if (!image_loader_start(dw->img_loader)) |
9 | 1576 { |
1577 image_sim_free(di->simd); | |
1578 di->simd = image_sim_new(); | |
1579 image_loader_free(dw->img_loader); | |
1580 dw->img_loader = NULL; | |
1581 return TRUE; | |
1582 } | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1583 dw->idle_id = 0; |
9 | 1584 return FALSE; |
1585 } | |
1586 | |
1587 dw->setup_point = dupe_setup_point_step(dw, dw->setup_point); | |
1588 dw->setup_n++; | |
1589 } | |
1590 dw->setup_mask |= DUPE_MATCH_SIM_MED; | |
1591 dupe_setup_reset(dw); | |
1592 } | |
1593 dupe_window_update_progress(dw, _("Comparing..."), 0.0, FALSE); | |
1594 dw->setup_done = TRUE; | |
1595 dupe_setup_reset(dw); | |
1596 dw->setup_count = g_list_length(dw->list); | |
1597 } | |
1598 | |
1599 if (!dw->working) | |
1600 { | |
1601 if (dw->setup_count > 0) | |
1602 { | |
1603 dw->setup_count = 0; | |
1604 dupe_window_update_progress(dw, _("Sorting..."), 1.0, TRUE); | |
1605 return TRUE; | |
1606 } | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1607 dw->idle_id = 0; |
9 | 1608 dupe_window_update_progress(dw, NULL, 0.0, FALSE); |
1609 | |
1610 dupe_match_rank(dw); | |
1611 dupe_window_update_count(dw, FALSE); | |
1612 | |
1613 dupe_listview_populate(dw); | |
1614 | |
1615 /* check thumbs */ | |
1616 if (dw->show_thumbs) dupe_thumb_step(dw); | |
1617 | |
1618 widget_set_cursor(dw->listview, -1); | |
1619 | |
1620 return FALSE; | |
1621 } | |
1622 | |
1623 dupe_list_check_match(dw, (DupeItem *)dw->working->data, dw->working); | |
1624 dupe_window_update_progress(dw, _("Comparing..."), dw->setup_count == 0 ? 0.0 : (gdouble) dw->setup_n / dw->setup_count, FALSE); | |
1625 dw->setup_n++; | |
1626 | |
1627 dw->working = dw->working->prev; | |
1628 | |
1629 return TRUE; | |
1630 } | |
1631 | |
1632 static void dupe_check_start(DupeWindow *dw) | |
1633 { | |
1634 dw->setup_done = FALSE; | |
1635 | |
1636 dw->setup_count = g_list_length(dw->list); | |
1637 if (dw->second_set) dw->setup_count += g_list_length(dw->second_list); | |
1638 | |
1639 dw->setup_mask = 0; | |
1640 dupe_setup_reset(dw); | |
1641 | |
1642 dw->working = g_list_last(dw->list); | |
1643 | |
1644 dupe_window_update_count(dw, TRUE); | |
1645 widget_set_cursor(dw->listview, GDK_WATCH); | |
1646 | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1513
diff
changeset
|
1647 if (dw->idle_id) return; |
9 | 1648 |
1649 dw->idle_id = g_idle_add(dupe_check_cb, dw); | |
1650 } | |
1651 | |
1652 /* | |
1653 * ------------------------------------------------------------------ | |
1654 * Item addition, removal | |
1655 * ------------------------------------------------------------------ | |
1656 */ | |
1657 | |
1658 static void dupe_item_remove(DupeWindow *dw, DupeItem *di) | |
1659 { | |
1660 if (!di) return; | |
1661 | |
1662 /* handle things that may be in progress... */ | |
1663 if (dw->working && dw->working->data == di) | |
1664 { | |
1665 dw->working = dw->working->prev; | |
1666 } | |
1667 if (dw->thumb_loader && dw->thumb_item == di) | |
1668 { | |
1669 dupe_thumb_step(dw); | |
1670 } | |
1671 if (dw->setup_point && dw->setup_point->data == di) | |
1672 { | |
1673 dw->setup_point = dupe_setup_point_step(dw, dw->setup_point); | |
1674 if (dw->img_loader) | |
1675 { | |
1676 image_loader_free(dw->img_loader); | |
1677 dw->img_loader = NULL; | |
1678 dw->idle_id = g_idle_add(dupe_check_cb, dw); | |
1679 } | |
1680 } | |
1681 | |
1682 if (di->group && dw->dupes) | |
1683 { | |
1684 /* is a dupe, must remove from group/reset children if a parent */ | |
1685 DupeItem *parent; | |
1686 | |
1687 parent = dupe_match_find_parent(dw, di); | |
1688 if (di == parent) | |
1689 { | |
1690 if (g_list_length(parent->group) < 2) | |
1691 { | |
1692 DupeItem *child; | |
1693 | |
1694 child = dupe_match_highest_rank(parent); | |
1695 dupe_match_link_clear(child, TRUE); | |
1696 dupe_listview_remove(dw, child); | |
1697 | |
1698 dupe_match_link_clear(parent, TRUE); | |
1699 dupe_listview_remove(dw, parent); | |
1700 dw->dupes = g_list_remove(dw->dupes, parent); | |
1701 } | |
1702 else | |
1703 { | |
1704 DupeItem *new_parent; | |
1705 DupeMatch *dm; | |
442 | 1706 |
9 | 1707 dm = parent->group->data; |
1708 new_parent = dm->di; | |
1709 dupe_match_reparent(dw, parent, new_parent); | |
1710 dupe_listview_remove(dw, parent); | |
1711 } | |
1712 } | |
1713 else | |
1714 { | |
1715 if (g_list_length(parent->group) < 2) | |
1716 { | |
1717 dupe_match_link_clear(parent, TRUE); | |
1718 dupe_listview_remove(dw, parent); | |
1719 dw->dupes = g_list_remove(dw->dupes, parent); | |
1720 } | |
1721 dupe_match_link_clear(di, TRUE); | |
1722 dupe_listview_remove(dw, di); | |
1723 } | |
1724 } | |
1725 else | |
1726 { | |
1727 /* not a dupe, or not sorted yet, simply reset */ | |
1728 dupe_match_link_clear(di, TRUE); | |
1729 } | |
1730 | |
1731 if (dw->second_list && g_list_find(dw->second_list, di)) | |
1732 { | |
1733 dupe_second_remove(dw, di); | |
1734 } | |
1735 else | |
1736 { | |
1737 dw->list = g_list_remove(dw->list, di); | |
1738 } | |
1739 dupe_item_free(di); | |
1740 | |
1741 dupe_window_update_count(dw, FALSE); | |
1742 } | |
1743 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
1744 static gboolean dupe_item_remove_by_path(DupeWindow *dw, const gchar *path) |
9 | 1745 { |
1746 DupeItem *di; | |
1747 | |
1748 di = dupe_item_find_path(dw, path); | |
1749 if (!di) return FALSE; | |
1750 | |
1751 dupe_item_remove(dw, di); | |
1752 | |
1753 return TRUE; | |
1754 } | |
1755 | |
1756 static void dupe_files_add(DupeWindow *dw, CollectionData *collection, CollectInfo *info, | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
1757 FileData *fd, gboolean recurse) |
9 | 1758 { |
1759 DupeItem *di = NULL; | |
1760 | |
1761 if (info) | |
1762 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1763 di = dupe_item_new(info->fd); |
9 | 1764 } |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1765 else if (fd) |
9 | 1766 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1767 if (isfile(fd->path)) |
9 | 1768 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1769 di = dupe_item_new(fd); |
9 | 1770 } |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1771 else if (isdir(fd->path) && recurse) |
9 | 1772 { |
1773 GList *f, *d; | |
783
0e45ed008a1c
replaced directory path with FileData* dir_fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
780
diff
changeset
|
1774 if (filelist_read(fd, &f, &d)) |
9 | 1775 { |
1776 GList *work; | |
1777 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1778 f = filelist_filter(f, FALSE); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1779 d = filelist_filter(d, TRUE); |
9 | 1780 |
1781 work = f; | |
516
768d10237b88
Convert the minority of while() to while ().
Laurent Monin <geeqie@norz.org>
parents:
513
diff
changeset
|
1782 while (work) |
9 | 1783 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1784 dupe_files_add(dw, NULL, NULL, (FileData *)work->data, TRUE); |
9 | 1785 work = work->next; |
1786 } | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1787 filelist_free(f); |
9 | 1788 work = d; |
516
768d10237b88
Convert the minority of while() to while ().
Laurent Monin <geeqie@norz.org>
parents:
513
diff
changeset
|
1789 while (work) |
9 | 1790 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1791 dupe_files_add(dw, NULL, NULL, (FileData *)work->data, TRUE); |
9 | 1792 work = work->next; |
1793 } | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1794 filelist_free(d); |
9 | 1795 } |
1796 } | |
1797 } | |
1798 | |
1799 if (!di) return; | |
1800 | |
2425
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1801 /* Ensure images in the lists have unique FileDatas */ |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1802 GList *work; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1803 DupeItem *di_list; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1804 work = g_list_first(dw->list); |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1805 while (work) |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1806 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1807 di_list = work->data; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1808 if (di_list->fd == di->fd) |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1809 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1810 return; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1811 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1812 else |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1813 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1814 work = work->next; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1815 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1816 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1817 |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1818 if (dw->second_list) |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1819 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1820 work = g_list_first(dw->second_list); |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1821 while (work) |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1822 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1823 di_list = work->data; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1824 if (di_list->fd == di->fd) |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1825 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1826 return; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1827 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1828 else |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1829 { |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1830 work = work->next; |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1831 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1832 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1833 } |
0af6b94854c2
Fix #460: Multiple duplicates
Colin Clark <cclark@mcb.net>
parents:
2422
diff
changeset
|
1834 |
9 | 1835 if (dw->second_drop) |
1836 { | |
1837 dupe_second_add(dw, di); | |
1838 } | |
1839 else | |
1840 { | |
1841 dw->list = g_list_prepend(dw->list, di); | |
1842 } | |
1843 } | |
1844 | |
1845 void dupe_window_add_collection(DupeWindow *dw, CollectionData *collection) | |
1846 { | |
1847 CollectInfo *info; | |
1848 | |
1849 info = collection_get_first(collection); | |
516
768d10237b88
Convert the minority of while() to while ().
Laurent Monin <geeqie@norz.org>
parents:
513
diff
changeset
|
1850 while (info) |
9 | 1851 { |
1852 dupe_files_add(dw, collection, info, NULL, FALSE); | |
1853 info = collection_next_by_info(collection, info); | |
1854 } | |
1855 | |
1856 dupe_check_start(dw); | |
1857 } | |
1858 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
1859 void dupe_window_add_files(DupeWindow *dw, GList *list, gboolean recurse) |
9 | 1860 { |
1861 GList *work; | |
1862 | |
1863 work = list; | |
516
768d10237b88
Convert the minority of while() to while ().
Laurent Monin <geeqie@norz.org>
parents:
513
diff
changeset
|
1864 while (work) |
9 | 1865 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1866 FileData *fd = work->data; |
9 | 1867 work = work->next; |
1868 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1869 dupe_files_add(dw, NULL, NULL, fd, recurse); |
9 | 1870 } |
1871 | |
1872 dupe_check_start(dw); | |
1873 } | |
1874 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1875 static void dupe_item_update(DupeWindow *dw, DupeItem *di) |
9 | 1876 { |
264
6c3cf7eb45aa
Add the possibility to match duplicates on the name but ignoring the case.
Laurent Monin <geeqie@norz.org>
parents:
259
diff
changeset
|
1877 if ( (dw->match_mask & DUPE_MATCH_NAME) || (dw->match_mask & DUPE_MATCH_PATH || (dw->match_mask & DUPE_MATCH_NAME_CI)) ) |
9 | 1878 { |
1879 /* only effects matches on name or path */ | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1880 /* |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1881 FileData *fd = file_data_ref(di->fd); |
9 | 1882 gint second; |
1883 | |
1884 second = di->second; | |
1885 dupe_item_remove(dw, di); | |
1886 | |
1887 dw->second_drop = second; | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1888 dupe_files_add(dw, NULL, NULL, fd, FALSE); |
9 | 1889 dw->second_drop = FALSE; |
442 | 1890 |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1891 file_data_unref(fd); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1892 */ |
9 | 1893 dupe_check_start(dw); |
1894 } | |
1895 else | |
1896 { | |
1897 GtkListStore *store; | |
1898 GtkTreeIter iter; | |
1899 gint row; | |
1900 /* update the listview(s) */ | |
1901 | |
1902 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
1903 row = dupe_listview_find_item(store, di, &iter); | |
1904 if (row >= 0) | |
1905 { | |
1906 gtk_list_store_set(store, &iter, | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1907 DUPE_COLUMN_NAME, di->fd->name, |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1908 DUPE_COLUMN_PATH, di->fd->path, -1); |
9 | 1909 } |
1910 | |
1911 if (dw->second_listview) | |
1912 { | |
1913 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->second_listview))); | |
1914 row = dupe_listview_find_item(store, di, &iter); | |
1915 if (row >= 0) | |
1916 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1917 gtk_list_store_set(store, &iter, 1, di->fd->path, -1); |
9 | 1918 } |
1919 } | |
1920 } | |
1921 | |
1922 } | |
1923 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1924 static void dupe_item_update_fd_in_list(DupeWindow *dw, FileData *fd, GList *work) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1925 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1926 while (work) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1927 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1928 DupeItem *di = work->data; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1929 |
442 | 1930 if (di->fd == fd) |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1931 dupe_item_update(dw, di); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1932 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1933 work = work->next; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1934 } |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1935 } |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1936 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1937 static void dupe_item_update_fd(DupeWindow *dw, FileData *fd) |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1938 { |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1939 dupe_item_update_fd_in_list(dw, fd, dw->list); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1940 if (dw->second_set) dupe_item_update_fd_in_list(dw, fd, dw->second_list); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1941 } |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1942 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1943 |
9 | 1944 /* |
1945 * ------------------------------------------------------------------ | |
1946 * Misc. | |
1947 * ------------------------------------------------------------------ | |
1948 */ | |
1949 | |
1950 static GtkWidget *dupe_display_label(GtkWidget *vbox, const gchar *description, const gchar *text) | |
1951 { | |
1952 GtkWidget *hbox; | |
1953 GtkWidget *label; | |
1954 | |
1955 hbox = gtk_hbox_new(FALSE, 10); | |
1956 | |
1957 label = gtk_label_new(description); | |
1958 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1959 gtk_widget_show(label); | |
1960 | |
1961 label = gtk_label_new(text); | |
1962 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
1963 gtk_widget_show(label); | |
442 | 1964 |
9 | 1965 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
1966 gtk_widget_show(hbox); | |
1967 | |
1968 return label; | |
1969 } | |
1970 | |
1971 static void dupe_display_stats(DupeWindow *dw, DupeItem *di) | |
1972 { | |
1973 GenericDialog *gd; | |
1974 gchar *buf; | |
442 | 1975 |
9 | 1976 if (!di) return; |
1977 | |
1174
f809d57aed0c
Drop useless wmclass stuff. Gtk will take care of it and as said in the documentation using gtk_window_set_wmclass() is sort of pointless.
Laurent Monin <geeqie@norz.org>
parents:
1148
diff
changeset
|
1978 gd = file_util_gen_dlg("Image thumbprint debug info", "thumbprint", |
9 | 1979 dw->window, TRUE, |
1980 NULL, NULL); | |
1981 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL, NULL, TRUE); | |
1982 | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1983 dupe_display_label(gd->vbox, "name:", di->fd->name); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1984 buf = text_from_size(di->fd->size); |
9 | 1985 dupe_display_label(gd->vbox, "size:", buf); |
1986 g_free(buf); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
1987 dupe_display_label(gd->vbox, "date:", text_from_time(di->fd->date)); |
9 | 1988 buf = g_strdup_printf("%d x %d", di->width, di->height); |
1989 dupe_display_label(gd->vbox, "dimensions:", buf); | |
1990 g_free(buf); | |
1991 dupe_display_label(gd->vbox, "md5sum:", (di->md5sum) ? di->md5sum : "not generated"); | |
1992 | |
1993 dupe_display_label(gd->vbox, "thumbprint:", (di->simd) ? "" : "not generated"); | |
1994 if (di->simd) | |
1995 { | |
1996 GtkWidget *image; | |
1997 GdkPixbuf *pixbuf; | |
1998 gint x, y; | |
1999 guchar *d_pix; | |
2000 guchar *dp; | |
2001 gint rs; | |
2002 gint sp; | |
442 | 2003 |
9 | 2004 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 32, 32); |
2005 rs = gdk_pixbuf_get_rowstride(pixbuf); | |
2006 d_pix = gdk_pixbuf_get_pixels(pixbuf); | |
2007 | |
2008 for (y = 0; y < 32; y++) | |
2009 { | |
2010 dp = d_pix + (y * rs); | |
2011 sp = y * 32; | |
2012 for (x = 0; x < 32; x++) | |
2013 { | |
2014 *(dp++) = di->simd->avg_r[sp + x]; | |
2015 *(dp++) = di->simd->avg_g[sp + x]; | |
2016 *(dp++) = di->simd->avg_b[sp + x]; | |
2017 } | |
2018 } | |
2019 | |
2020 image = gtk_image_new_from_pixbuf(pixbuf); | |
2021 gtk_box_pack_start(GTK_BOX(gd->vbox), image, FALSE, FALSE, 0); | |
2022 gtk_widget_show(image); | |
442 | 2023 |
1043
718ab8111f48
Replaced gtk depreceated code.
Petr Ostadal <postadal@suse.cz>
parents:
1029
diff
changeset
|
2024 g_object_unref(pixbuf); |
9 | 2025 } |
442 | 2026 |
9 | 2027 gtk_widget_show(gd->dialog); |
2028 } | |
2029 | |
2030 static void dupe_window_recompare(DupeWindow *dw) | |
2031 { | |
2032 GtkListStore *store; | |
2033 | |
2034 dupe_check_stop(dw); | |
2035 | |
2036 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
2037 gtk_list_store_clear(store); | |
2038 | |
2039 g_list_free(dw->dupes); | |
2040 dw->dupes = NULL; | |
2041 | |
2042 dupe_match_reset_list(dw->list); | |
2043 dupe_match_reset_list(dw->second_list); | |
2044 | |
2045 dupe_check_start(dw); | |
2046 } | |
2047 | |
2048 static void dupe_menu_view(DupeWindow *dw, DupeItem *di, GtkWidget *listview, gint new_window) | |
2049 { | |
2050 if (!di) return; | |
2051 | |
2052 if (di->collection && collection_info_valid(di->collection, di->info)) | |
2053 { | |
2054 if (new_window) | |
2055 { | |
2056 view_window_new_from_collection(di->collection, di->info); | |
2057 } | |
2058 else | |
2059 { | |
2060 layout_image_set_collection(NULL, di->collection, di->info); | |
2061 } | |
2062 } | |
2063 else | |
2064 { | |
2065 if (new_window) | |
2066 { | |
2067 GList *list; | |
2068 | |
2069 list = dupe_listview_get_selection(dw, listview); | |
2070 view_window_new_from_list(list); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2071 filelist_free(list); |
9 | 2072 } |
2073 else | |
2074 { | |
1445
f52adf8f0daf
fixed viewing image from dupe and search windows
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1444
diff
changeset
|
2075 layout_set_fd(NULL, di->fd); |
9 | 2076 } |
2077 } | |
2078 } | |
2079 | |
2080 static void dupe_window_remove_selection(DupeWindow *dw, GtkWidget *listview) | |
2081 { | |
2082 GtkTreeSelection *selection; | |
2083 GtkTreeModel *store; | |
2084 GtkTreeIter iter; | |
2085 GList *slist; | |
2086 GList *list = NULL; | |
2087 GList *work; | |
2088 | |
2089 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); | |
2090 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
2091 work = slist; | |
2092 while (work) | |
2093 { | |
2094 GtkTreePath *tpath = work->data; | |
2095 DupeItem *di = NULL; | |
2096 | |
2097 gtk_tree_model_get_iter(store, &iter, tpath); | |
2098 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
2099 if (di) list = g_list_prepend(list, di); | |
2100 work = work->next; | |
2101 } | |
2102 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
2103 g_list_free(slist); | |
2104 | |
2105 dw->color_frozen = TRUE; | |
2106 work = list; | |
2107 while (work) | |
2108 { | |
2109 DupeItem *di; | |
2110 | |
2111 di = work->data; | |
2112 work = work->next; | |
2113 dupe_item_remove(dw, di); | |
2114 } | |
2115 dw->color_frozen = FALSE; | |
2116 | |
2117 g_list_free(list); | |
2118 | |
2119 dupe_listview_realign_colors(dw); | |
2120 } | |
2121 | |
1272
661e170bf4f7
read external editors from .desktop files
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1211
diff
changeset
|
2122 static void dupe_window_edit_selected(DupeWindow *dw, const gchar *key) |
9 | 2123 { |
1656
84034de67e74
fixed leak in file_util_* functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1652
diff
changeset
|
2124 file_util_start_editor_from_filelist(key, dupe_listview_get_selection(dw, dw->listview), NULL, dw->window); |
9 | 2125 } |
2126 | |
2127 static void dupe_window_collection_from_selection(DupeWindow *dw) | |
2128 { | |
2129 CollectWindow *w; | |
2130 GList *list; | |
2131 | |
2132 list = dupe_listview_get_selection(dw, dw->listview); | |
2133 w = collection_window_new(NULL); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2134 collection_table_add_filelist(w->table, list); |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2135 filelist_free(list); |
9 | 2136 } |
2137 | |
2138 static void dupe_window_append_file_list(DupeWindow *dw, gint on_second) | |
2139 { | |
2140 GList *list; | |
2141 | |
2142 dw->second_drop = (dw->second_set && on_second); | |
2143 | |
2144 list = layout_list(NULL); | |
2145 dupe_window_add_files(dw, list, FALSE); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2146 filelist_free(list); |
9 | 2147 } |
2148 | |
2149 /* | |
2150 *------------------------------------------------------------------- | |
2151 * main pop-up menu callbacks | |
2152 *------------------------------------------------------------------- | |
2153 */ | |
2154 | |
2155 static void dupe_menu_view_cb(GtkWidget *widget, gpointer data) | |
2156 { | |
2157 DupeWindow *dw = data; | |
2158 | |
2159 if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->listview, FALSE); | |
2160 } | |
2161 | |
2162 static void dupe_menu_viewnew_cb(GtkWidget *widget, gpointer data) | |
2163 { | |
2164 DupeWindow *dw = data; | |
2165 | |
2166 if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->listview, TRUE); | |
2167 } | |
2168 | |
2169 static void dupe_menu_select_all_cb(GtkWidget *widget, gpointer data) | |
2170 { | |
2171 DupeWindow *dw = data; | |
2172 GtkTreeSelection *selection; | |
2173 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2174 options->duplicates_select_type = DUPE_SELECT_NONE; |
9 | 2175 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->listview)); |
2176 gtk_tree_selection_select_all(selection); | |
2177 } | |
2178 | |
2179 static void dupe_menu_select_none_cb(GtkWidget *widget, gpointer data) | |
2180 { | |
2181 DupeWindow *dw = data; | |
2182 GtkTreeSelection *selection; | |
2183 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2184 options->duplicates_select_type = DUPE_SELECT_NONE; |
9 | 2185 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->listview)); |
2186 gtk_tree_selection_unselect_all(selection); | |
2187 } | |
2188 | |
2189 static void dupe_menu_select_dupes_set1_cb(GtkWidget *widget, gpointer data) | |
2190 { | |
2191 DupeWindow *dw = data; | |
2192 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2193 options->duplicates_select_type = DUPE_SELECT_GROUP1; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2194 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP1); |
9 | 2195 } |
2196 | |
2197 static void dupe_menu_select_dupes_set2_cb(GtkWidget *widget, gpointer data) | |
2198 { | |
2199 DupeWindow *dw = data; | |
2200 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2201 options->duplicates_select_type = DUPE_SELECT_GROUP2; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2202 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP2); |
9 | 2203 } |
2204 | |
2205 static void dupe_menu_edit_cb(GtkWidget *widget, gpointer data) | |
2206 { | |
2207 DupeWindow *dw; | |
1272
661e170bf4f7
read external editors from .desktop files
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1211
diff
changeset
|
2208 const gchar *key = data; |
9 | 2209 |
2210 dw = submenu_item_get_data(widget); | |
2211 if (!dw) return; | |
2212 | |
1272
661e170bf4f7
read external editors from .desktop files
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1211
diff
changeset
|
2213 dupe_window_edit_selected(dw, key); |
9 | 2214 } |
2215 | |
2216 static void dupe_menu_print_cb(GtkWidget *widget, gpointer data) | |
2217 { | |
2218 DupeWindow *dw = data; | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2219 FileData *fd; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2220 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2221 fd = (dw->click_item) ? dw->click_item->fd : NULL; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2222 |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2223 print_window_new(fd, |
9 | 2224 dupe_listview_get_selection(dw, dw->listview), |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2225 dupe_listview_get_filelist(dw, dw->listview), dw->window); |
9 | 2226 } |
2227 | |
2228 static void dupe_menu_copy_cb(GtkWidget *widget, gpointer data) | |
2229 { | |
2230 DupeWindow *dw = data; | |
2231 | |
2232 file_util_copy(NULL, dupe_listview_get_selection(dw, dw->listview), NULL, dw->window); | |
2233 } | |
2234 | |
2235 static void dupe_menu_move_cb(GtkWidget *widget, gpointer data) | |
2236 { | |
2237 DupeWindow *dw = data; | |
2238 | |
2239 file_util_move(NULL, dupe_listview_get_selection(dw, dw->listview), NULL, dw->window); | |
2240 } | |
2241 | |
2242 static void dupe_menu_rename_cb(GtkWidget *widget, gpointer data) | |
2243 { | |
2244 DupeWindow *dw = data; | |
2245 | |
2246 file_util_rename(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window); | |
2247 } | |
2248 | |
2249 static void dupe_menu_delete_cb(GtkWidget *widget, gpointer data) | |
2250 { | |
2251 DupeWindow *dw = data; | |
2252 | |
2860
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2253 options->file_ops.safe_delete_enable = FALSE; |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2254 file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window); |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2255 } |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2256 |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2257 static void dupe_menu_move_to_trash_cb(GtkWidget *widget, gpointer data) |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2258 { |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2259 DupeWindow *dw = data; |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2260 |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2261 options->file_ops.safe_delete_enable = TRUE; |
9 | 2262 file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window); |
2263 } | |
2264 | |
497
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2265 static void dupe_menu_copy_path_cb(GtkWidget *widget, gpointer data) |
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2266 { |
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2267 DupeWindow *dw = data; |
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2268 |
2663
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2269 file_util_copy_path_list_to_clipboard(dupe_listview_get_selection(dw, dw->listview), TRUE); |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2270 } |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2271 |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2272 static void dupe_menu_copy_path_unquoted_cb(GtkWidget *widget, gpointer data) |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2273 { |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2274 DupeWindow *dw = data; |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2275 |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2276 file_util_copy_path_list_to_clipboard(dupe_listview_get_selection(dw, dw->listview), FALSE); |
497
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2277 } |
29dc838f7d6b
Allow the copy of file paths to clipboard.
Laurent Monin <geeqie@norz.org>
parents:
495
diff
changeset
|
2278 |
9 | 2279 static void dupe_menu_remove_cb(GtkWidget *widget, gpointer data) |
2280 { | |
2281 DupeWindow *dw = data; | |
2282 | |
2283 dupe_window_remove_selection(dw, dw->listview); | |
2284 } | |
2285 | |
2286 static void dupe_menu_clear_cb(GtkWidget *widget, gpointer data) | |
2287 { | |
2288 DupeWindow *dw = data; | |
2289 | |
2290 dupe_window_clear(dw); | |
2291 } | |
2292 | |
2293 static void dupe_menu_close_cb(GtkWidget *widget, gpointer data) | |
2294 { | |
2295 DupeWindow *dw = data; | |
2296 | |
2297 dupe_window_close(dw); | |
2298 } | |
2299 | |
1397
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2300 static void dupe_menu_popup_destroy_cb(GtkWidget *widget, gpointer data) |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2301 { |
1698
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2302 GList *editmenu_fd_list = data; |
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2303 |
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2304 filelist_free(editmenu_fd_list); |
2184 | 2305 } |
1397
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2306 |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2307 static GList *dupe_window_get_fd_list(DupeWindow *dw) |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2308 { |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2309 GList *list; |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2310 |
1810
c3a79dda8ea7
GTK marks several functions as deprecated
Klaus Ethgen <Klaus@Ethgen.de>
parents:
1802
diff
changeset
|
2311 if (gtk_widget_has_focus(dw->second_listview)) |
1397
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2312 { |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2313 list = dupe_listview_get_selection(dw, dw->second_listview); |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2314 } |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2315 else |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2316 { |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2317 list = dupe_listview_get_selection(dw, dw->listview); |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2318 } |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2319 |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2320 return list; |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2321 } |
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2322 |
2583
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2323 /** |
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2324 * @brief Add file selection list to a collection |
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2325 * @param[in] widget |
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2326 * @param[in] data Index to the collection list menu item selected, or -1 for new collection |
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2327 * |
6e92c0ad76f2
Change recent code comments to Doxygen style
Colin Clark <colin.clark@cclark.uk>
parents:
2582
diff
changeset
|
2328 * |
2582
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2329 */ |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2330 static void dupe_pop_menu_collections_cb(GtkWidget *widget, gpointer data) |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2331 { |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2332 DupeWindow *dw; |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2333 GList *selection_list; |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2334 |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2335 dw = submenu_item_get_data(widget); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2336 selection_list = dupe_listview_get_selection(dw, dw->listview); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2337 pop_menu_collections(selection_list, data); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2338 |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2339 filelist_free(selection_list); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2340 } |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2341 |
9 | 2342 static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di) |
2343 { | |
2344 GtkWidget *menu; | |
2345 GtkWidget *item; | |
2346 gint on_row; | |
1698
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2347 GList *editmenu_fd_list; |
2582
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2348 GtkWidget *submenu; |
9 | 2349 |
2350 on_row = (di != NULL); | |
2351 | |
2352 menu = popup_menu_short_lived(); | |
1397
db1b3d950a8c
In various Edit context menus, only display editors that match the file types in the selection.
Laurent Monin <geeqie@norz.org>
parents:
1367
diff
changeset
|
2353 |
9 | 2354 menu_item_add_sensitive(menu, _("_View"), on_row, |
2355 G_CALLBACK(dupe_menu_view_cb), dw); | |
2356 menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, on_row, | |
2357 G_CALLBACK(dupe_menu_viewnew_cb), dw); | |
2358 menu_item_add_divider(menu); | |
2359 menu_item_add_sensitive(menu, _("Select all"), (dw->dupes != NULL), | |
2360 G_CALLBACK(dupe_menu_select_all_cb), dw); | |
2361 menu_item_add_sensitive(menu, _("Select none"), (dw->dupes != NULL), | |
2362 G_CALLBACK(dupe_menu_select_none_cb), dw); | |
2363 menu_item_add_sensitive(menu, _("Select group _1 duplicates"), (dw->dupes != NULL), | |
2364 G_CALLBACK(dupe_menu_select_dupes_set1_cb), dw); | |
2365 menu_item_add_sensitive(menu, _("Select group _2 duplicates"), (dw->dupes != NULL), | |
2366 G_CALLBACK(dupe_menu_select_dupes_set2_cb), dw); | |
2367 menu_item_add_divider(menu); | |
2185
c14a1d8e6aa4
Trim trailing white spaces on empty lines.
Laurent Monin <zas@norz.org>
parents:
2184
diff
changeset
|
2368 |
1698
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2369 editmenu_fd_list = dupe_window_get_fd_list(dw); |
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2370 g_signal_connect(G_OBJECT(menu), "destroy", |
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2371 G_CALLBACK(dupe_menu_popup_destroy_cb), editmenu_fd_list); |
dc7c36ce2b92
fixed destroying of menu data
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1656
diff
changeset
|
2372 submenu_add_edit(menu, &item, G_CALLBACK(dupe_menu_edit_cb), dw, editmenu_fd_list); |
9 | 2373 if (!on_row) gtk_widget_set_sensitive(item, FALSE); |
2582
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2374 |
2701
3f5967ca0a37
Fix #566: submenu items "variable set but not used" errors in 1.4
Colin Clark <colin.clark@cclark.uk>
parents:
2694
diff
changeset
|
2375 submenu_add_collections(menu, &item, |
2582
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2376 G_CALLBACK(dupe_pop_menu_collections_cb), dw); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2377 gtk_widget_set_sensitive(item, on_row); |
03014a1eb7e7
Right-click menus - collections
Colin Clark <colin.clark@cclark.uk>
parents:
2572
diff
changeset
|
2378 |
9 | 2379 menu_item_add_stock_sensitive(menu, _("Print..."), GTK_STOCK_PRINT, on_row, |
2380 G_CALLBACK(dupe_menu_print_cb), dw); | |
2381 menu_item_add_divider(menu); | |
2382 menu_item_add_stock_sensitive(menu, _("_Copy..."), GTK_STOCK_COPY, on_row, | |
2383 G_CALLBACK(dupe_menu_copy_cb), dw); | |
2384 menu_item_add_sensitive(menu, _("_Move..."), on_row, | |
2385 G_CALLBACK(dupe_menu_move_cb), dw); | |
2386 menu_item_add_sensitive(menu, _("_Rename..."), on_row, | |
2387 G_CALLBACK(dupe_menu_rename_cb), dw); | |
2572
31c6e3c9163e
Fix #505: ‘Copy path’ and ‘Delete’ are too close in the drop down menu
Colin Clark <colin.clark@cclark.uk>
parents:
2489
diff
changeset
|
2388 menu_item_add_sensitive(menu, _("_Copy path"), on_row, |
31c6e3c9163e
Fix #505: ‘Copy path’ and ‘Delete’ are too close in the drop down menu
Colin Clark <colin.clark@cclark.uk>
parents:
2489
diff
changeset
|
2389 G_CALLBACK(dupe_menu_copy_path_cb), dw); |
2663
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2390 menu_item_add_sensitive(menu, _("_Copy path unquoted"), on_row, |
3e6d26094fb4
Fix #520: copy path inserts quotes around path
Colin Clark <colin.clark@cclark.uk>
parents:
2606
diff
changeset
|
2391 G_CALLBACK(dupe_menu_copy_path_unquoted_cb), dw); |
2860
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2392 |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2393 menu_item_add_divider(menu); |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2394 menu_item_add_stock_sensitive(menu, |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2395 options->file_ops.confirm_move_to_trash ? _("Move to Trash...") : |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2396 _("Move to Trash"), PIXBUF_INLINE_ICON_TRASH, on_row, |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2397 G_CALLBACK(dupe_menu_move_to_trash_cb), dw); |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2398 menu_item_add_stock_sensitive(menu, |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2399 options->file_ops.confirm_delete ? _("_Delete...") : |
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2400 _("_Delete"), GTK_STOCK_DELETE, on_row, |
9 | 2401 G_CALLBACK(dupe_menu_delete_cb), dw); |
2860
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
2402 |
9 | 2403 menu_item_add_divider(menu); |
2404 menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row, | |
2405 G_CALLBACK(dupe_menu_remove_cb), dw); | |
2406 menu_item_add_stock_sensitive(menu, _("C_lear"), GTK_STOCK_CLEAR, (dw->list != NULL), | |
2407 G_CALLBACK(dupe_menu_clear_cb), dw); | |
2408 menu_item_add_divider(menu); | |
2409 menu_item_add_stock(menu, _("Close _window"), GTK_STOCK_CLOSE, | |
2410 G_CALLBACK(dupe_menu_close_cb), dw); | |
2411 | |
2412 return menu; | |
2413 } | |
2414 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2415 static gboolean dupe_listview_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) |
9 | 2416 { |
2417 DupeWindow *dw = data; | |
2418 GtkTreeModel *store; | |
2419 GtkTreePath *tpath; | |
2420 GtkTreeIter iter; | |
2421 DupeItem *di = NULL; | |
2422 | |
2423 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
2424 | |
2425 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
2426 &tpath, NULL, NULL, NULL)) | |
2427 { | |
2428 gtk_tree_model_get_iter(store, &iter, tpath); | |
2429 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
2430 gtk_tree_path_free(tpath); | |
2431 } | |
2432 | |
2433 dw->click_item = di; | |
2434 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2435 if (bevent->button == MOUSE_BUTTON_RIGHT) |
9 | 2436 { |
2437 /* right click menu */ | |
2438 GtkWidget *menu; | |
2439 | |
2440 if (bevent->state & GDK_CONTROL_MASK && bevent->state & GDK_SHIFT_MASK) | |
2441 { | |
2442 dupe_display_stats(dw, di); | |
2443 return TRUE; | |
2444 } | |
2445 if (widget == dw->listview) | |
2446 { | |
2447 menu = dupe_menu_popup_main(dw, di); | |
2448 } | |
2449 else | |
2450 { | |
2451 menu = dupe_menu_popup_second(dw, di); | |
2452 } | |
2453 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time); | |
2454 } | |
2455 | |
2456 if (!di) return FALSE; | |
2457 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2458 if (bevent->button == MOUSE_BUTTON_LEFT && |
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2459 bevent->type == GDK_2BUTTON_PRESS) |
9 | 2460 { |
2461 dupe_menu_view(dw, di, widget, FALSE); | |
2462 } | |
2463 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2464 if (bevent->button == MOUSE_BUTTON_MIDDLE) return TRUE; |
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2465 |
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2466 if (bevent->button == MOUSE_BUTTON_RIGHT) |
9 | 2467 { |
2468 if (!dupe_listview_item_is_selected(dw, di, widget)) | |
2469 { | |
2470 GtkTreeSelection *selection; | |
2471 | |
2472 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
2473 gtk_tree_selection_unselect_all(selection); | |
2474 gtk_tree_selection_select_iter(selection, &iter); | |
2475 | |
2476 tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); | |
2477 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
2478 gtk_tree_path_free(tpath); | |
2479 } | |
2480 | |
2481 return TRUE; | |
2482 } | |
2483 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2484 if (bevent->button == MOUSE_BUTTON_LEFT && |
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2485 bevent->type == GDK_BUTTON_PRESS && |
9 | 2486 !(bevent->state & GDK_SHIFT_MASK ) && |
2487 !(bevent->state & GDK_CONTROL_MASK ) && | |
2488 dupe_listview_item_is_selected(dw, di, widget)) | |
2489 { | |
2490 /* this selection handled on release_cb */ | |
2491 gtk_widget_grab_focus(widget); | |
2492 return TRUE; | |
2493 } | |
2494 | |
2495 return FALSE; | |
2496 } | |
2497 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2498 static gboolean dupe_listview_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) |
9 | 2499 { |
2500 DupeWindow *dw = data; | |
2501 GtkTreeModel *store; | |
2502 GtkTreePath *tpath; | |
2503 GtkTreeIter iter; | |
2504 DupeItem *di = NULL; | |
2505 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2506 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE) return TRUE; |
9 | 2507 |
2508 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
2509 | |
2510 if ((bevent->x != 0 || bevent->y != 0) && | |
2511 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
2512 &tpath, NULL, NULL, NULL)) | |
2513 { | |
2514 gtk_tree_model_get_iter(store, &iter, tpath); | |
2515 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
2516 gtk_tree_path_free(tpath); | |
2517 } | |
2518 | |
448
2c1500b5c933
Use explicit names for mouse buttons instead of numbers.
Laurent Monin <geeqie@norz.org>
parents:
446
diff
changeset
|
2519 if (bevent->button == MOUSE_BUTTON_MIDDLE) |
9 | 2520 { |
2521 if (di && dw->click_item == di) | |
2522 { | |
2523 GtkTreeSelection *selection; | |
2524 | |
2525 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
2526 if (dupe_listview_item_is_selected(dw, di, widget)) | |
2527 { | |
2528 gtk_tree_selection_unselect_iter(selection, &iter); | |
2529 } | |
2530 else | |
2531 { | |
2532 gtk_tree_selection_select_iter(selection, &iter); | |
2533 } | |
2534 } | |
2535 return TRUE; | |
2536 } | |
2537 | |
2538 if (di && dw->click_item == di && | |
2539 !(bevent->state & GDK_SHIFT_MASK ) && | |
2540 !(bevent->state & GDK_CONTROL_MASK ) && | |
2541 dupe_listview_item_is_selected(dw, di, widget)) | |
2542 { | |
2543 GtkTreeSelection *selection; | |
2544 | |
2545 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
2546 gtk_tree_selection_unselect_all(selection); | |
2547 gtk_tree_selection_select_iter(selection, &iter); | |
2548 | |
2549 tpath = gtk_tree_model_get_path(store, &iter); | |
2550 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
2551 gtk_tree_path_free(tpath); | |
2552 | |
2553 return TRUE; | |
2554 } | |
2555 | |
2556 return FALSE; | |
2557 } | |
2558 | |
2559 /* | |
2560 *------------------------------------------------------------------- | |
2561 * second set stuff | |
2562 *------------------------------------------------------------------- | |
2563 */ | |
2564 | |
2565 static void dupe_second_update_status(DupeWindow *dw) | |
2566 { | |
2567 gchar *buf; | |
2568 | |
2569 buf = g_strdup_printf(_("%d files (set 2)"), g_list_length(dw->second_list)); | |
2570 gtk_label_set_text(GTK_LABEL(dw->second_status_label), buf); | |
2571 g_free(buf); | |
2572 } | |
2573 | |
2574 static void dupe_second_add(DupeWindow *dw, DupeItem *di) | |
2575 { | |
2576 GtkListStore *store; | |
2577 GtkTreeIter iter; | |
2578 | |
2579 if (!di) return; | |
2580 | |
2581 di->second = TRUE; | |
2582 dw->second_list = g_list_prepend(dw->second_list, di); | |
2583 | |
2584 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->second_listview))); | |
2585 gtk_list_store_append(store, &iter); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
2586 gtk_list_store_set(store, &iter, DUPE_COLUMN_POINTER, di, 1, di->fd->path, -1); |
9 | 2587 |
2588 dupe_second_update_status(dw); | |
2589 } | |
2590 | |
2591 static void dupe_second_remove(DupeWindow *dw, DupeItem *di) | |
2592 { | |
2593 GtkListStore *store; | |
2594 GtkTreeIter iter; | |
2595 | |
2596 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->second_listview))); | |
2597 if (dupe_listview_find_item(store, di, &iter) >= 0) | |
2598 { | |
2599 tree_view_move_cursor_away(GTK_TREE_VIEW(dw->second_listview), &iter, TRUE); | |
2600 gtk_list_store_remove(store, &iter); | |
2601 } | |
2602 | |
2603 dw->second_list = g_list_remove(dw->second_list, di); | |
2604 | |
2605 dupe_second_update_status(dw); | |
2606 } | |
2607 | |
2608 static void dupe_second_clear(DupeWindow *dw) | |
2609 { | |
2610 GtkListStore *store; | |
2611 | |
2612 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->second_listview))); | |
2613 gtk_list_store_clear(store); | |
2614 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(dw->second_listview)); | |
2615 | |
2616 g_list_free(dw->dupes); | |
2617 dw->dupes = NULL; | |
2618 | |
2619 dupe_list_free(dw->second_list); | |
2620 dw->second_list = NULL; | |
2621 | |
2622 dupe_match_reset_list(dw->list); | |
2623 | |
2624 dupe_second_update_status(dw); | |
2625 } | |
2626 | |
2627 static void dupe_second_menu_view_cb(GtkWidget *widget, gpointer data) | |
2628 { | |
2629 DupeWindow *dw = data; | |
2630 | |
2631 if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->second_listview, FALSE); | |
2632 } | |
2633 | |
2634 static void dupe_second_menu_viewnew_cb(GtkWidget *widget, gpointer data) | |
2635 { | |
2636 DupeWindow *dw = data; | |
2637 | |
2638 if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->second_listview, TRUE); | |
2639 } | |
2640 | |
2641 static void dupe_second_menu_select_all_cb(GtkWidget *widget, gpointer data) | |
2642 { | |
2643 GtkTreeSelection *selection; | |
2644 DupeWindow *dw = data; | |
2645 | |
2646 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->second_listview)); | |
2647 gtk_tree_selection_select_all(selection); | |
2648 } | |
2649 | |
2650 static void dupe_second_menu_select_none_cb(GtkWidget *widget, gpointer data) | |
2651 { | |
2652 GtkTreeSelection *selection; | |
2653 DupeWindow *dw = data; | |
2654 | |
2655 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->second_listview)); | |
2656 gtk_tree_selection_unselect_all(selection); | |
2657 } | |
2658 | |
2659 static void dupe_second_menu_remove_cb(GtkWidget *widget, gpointer data) | |
2660 { | |
2661 DupeWindow *dw = data; | |
2662 | |
2663 dupe_window_remove_selection(dw, dw->second_listview); | |
2664 } | |
2665 | |
2666 static void dupe_second_menu_clear_cb(GtkWidget *widget, gpointer data) | |
2667 { | |
2668 DupeWindow *dw = data; | |
2669 | |
2670 dupe_second_clear(dw); | |
2671 dupe_window_recompare(dw); | |
2672 } | |
2673 | |
2674 static GtkWidget *dupe_menu_popup_second(DupeWindow *dw, DupeItem *di) | |
2675 { | |
2676 GtkWidget *menu; | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2677 gboolean notempty = (dw->second_list != NULL); |
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2678 gboolean on_row = (di != NULL); |
9 | 2679 |
2680 menu = popup_menu_short_lived(); | |
2681 menu_item_add_sensitive(menu, _("_View"), on_row, | |
2682 G_CALLBACK(dupe_second_menu_view_cb), dw); | |
2683 menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, on_row, | |
2684 G_CALLBACK(dupe_second_menu_viewnew_cb), dw); | |
2685 menu_item_add_divider(menu); | |
2686 menu_item_add_sensitive(menu, _("Select all"), notempty, | |
2687 G_CALLBACK(dupe_second_menu_select_all_cb), dw); | |
2688 menu_item_add_sensitive(menu, _("Select none"), notempty, | |
2689 G_CALLBACK(dupe_second_menu_select_none_cb), dw); | |
2690 menu_item_add_divider(menu); | |
2691 menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row, | |
2692 G_CALLBACK(dupe_second_menu_remove_cb), dw); | |
2693 menu_item_add_stock_sensitive(menu, _("C_lear"), GTK_STOCK_CLEAR, notempty, | |
2694 G_CALLBACK(dupe_second_menu_clear_cb), dw); | |
2695 menu_item_add_divider(menu); | |
2696 menu_item_add_stock(menu, _("Close _window"), GTK_STOCK_CLOSE, | |
2697 G_CALLBACK(dupe_menu_close_cb), dw); | |
2698 | |
2699 return menu; | |
2700 } | |
2701 | |
2702 static void dupe_second_set_toggle_cb(GtkWidget *widget, gpointer data) | |
2703 { | |
2704 DupeWindow *dw = data; | |
2705 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
2706 dw->second_set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); |
9 | 2707 |
2708 if (dw->second_set) | |
2709 { | |
2710 dupe_second_update_status(dw); | |
2711 gtk_table_set_col_spacings(GTK_TABLE(dw->table), PREF_PAD_GAP); | |
2712 gtk_widget_show(dw->second_vbox); | |
2713 } | |
2714 else | |
2715 { | |
2716 gtk_table_set_col_spacings(GTK_TABLE(dw->table), 0); | |
2717 gtk_widget_hide(dw->second_vbox); | |
2718 dupe_second_clear(dw); | |
2719 } | |
2720 | |
2721 dupe_window_recompare(dw); | |
2722 } | |
2723 | |
2489
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2724 static void dupe_sort_totals_toggle_cb(GtkWidget *widget, gpointer data) |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2725 { |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2726 DupeWindow *dw = data; |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2727 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2728 options->sort_totals = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2729 dupe_window_recompare(dw); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2730 |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2731 } |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
2732 |
9 | 2733 /* |
2734 *------------------------------------------------------------------- | |
2735 * match type menu | |
2736 *------------------------------------------------------------------- | |
2737 */ | |
2738 | |
2739 enum { | |
2740 DUPE_MENU_COLUMN_NAME = 0, | |
2741 DUPE_MENU_COLUMN_MASK | |
2742 }; | |
2743 | |
2744 static void dupe_menu_type_cb(GtkWidget *combo, gpointer data) | |
2745 { | |
2746 DupeWindow *dw = data; | |
2747 GtkTreeModel *store; | |
2748 GtkTreeIter iter; | |
2749 | |
2750 store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); | |
2751 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return; | |
2752 gtk_tree_model_get(store, &iter, DUPE_MENU_COLUMN_MASK, &dw->match_mask, -1); | |
2753 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2754 options->duplicates_match = dw->match_mask; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2755 |
9 | 2756 dupe_window_recompare(dw); |
2757 } | |
2758 | |
2759 static void dupe_menu_add_item(GtkListStore *store, const gchar *text, DupeMatchType type, DupeWindow *dw) | |
2760 { | |
2761 GtkTreeIter iter; | |
2762 | |
2763 gtk_list_store_append(store, &iter); | |
2764 gtk_list_store_set(store, &iter, DUPE_MENU_COLUMN_NAME, text, | |
2765 DUPE_MENU_COLUMN_MASK, type, -1); | |
2766 | |
2767 if (dw->match_mask == type) gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dw->combo), &iter); | |
2768 } | |
2769 | |
2770 static void dupe_menu_setup(DupeWindow *dw) | |
2771 { | |
2772 GtkListStore *store; | |
2773 GtkCellRenderer *renderer; | |
2774 | |
2775 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); | |
2776 dw->combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); | |
2777 g_object_unref(store); | |
2778 | |
2779 renderer = gtk_cell_renderer_text_new(); | |
2780 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dw->combo), renderer, TRUE); | |
2781 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dw->combo), renderer, | |
2782 "text", DUPE_MENU_COLUMN_NAME, NULL); | |
2783 | |
2784 dupe_menu_add_item(store, _("Name"), DUPE_MATCH_NAME, dw); | |
264
6c3cf7eb45aa
Add the possibility to match duplicates on the name but ignoring the case.
Laurent Monin <geeqie@norz.org>
parents:
259
diff
changeset
|
2785 dupe_menu_add_item(store, _("Name case-insensitive"), DUPE_MATCH_NAME_CI, dw); |
9 | 2786 dupe_menu_add_item(store, _("Size"), DUPE_MATCH_SIZE, dw); |
2787 dupe_menu_add_item(store, _("Date"), DUPE_MATCH_DATE, dw); | |
2788 dupe_menu_add_item(store, _("Dimensions"), DUPE_MATCH_DIM, dw); | |
2789 dupe_menu_add_item(store, _("Checksum"), DUPE_MATCH_SUM, dw); | |
2790 dupe_menu_add_item(store, _("Path"), DUPE_MATCH_PATH, dw); | |
2791 dupe_menu_add_item(store, _("Similarity (high)"), DUPE_MATCH_SIM_HIGH, dw); | |
2792 dupe_menu_add_item(store, _("Similarity"), DUPE_MATCH_SIM_MED, dw); | |
2793 dupe_menu_add_item(store, _("Similarity (low)"), DUPE_MATCH_SIM_LOW, dw); | |
2794 dupe_menu_add_item(store, _("Similarity (custom)"), DUPE_MATCH_SIM_CUSTOM, dw); | |
2795 | |
2796 g_signal_connect(G_OBJECT(dw->combo), "changed", | |
2797 G_CALLBACK(dupe_menu_type_cb), dw); | |
2798 } | |
2799 | |
2800 /* | |
2801 *------------------------------------------------------------------- | |
2802 * list view columns | |
2803 *------------------------------------------------------------------- | |
2804 */ | |
2805 | |
2806 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */ | |
2807 | |
2808 #define CELL_HEIGHT_OVERRIDE 512 | |
442 | 2809 |
9 | 2810 void cell_renderer_height_override(GtkCellRenderer *renderer) |
2811 { | |
2812 GParamSpec *spec; | |
2813 | |
2814 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height"); | |
2815 if (spec && G_IS_PARAM_SPEC_INT(spec)) | |
2816 { | |
2817 GParamSpecInt *spec_int; | |
2818 | |
2819 spec_int = G_PARAM_SPEC_INT(spec); | |
2820 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE; | |
2821 } | |
2822 } | |
2823 | |
2824 static GdkColor *dupe_listview_color_shifted(GtkWidget *widget) | |
2825 { | |
2826 static GdkColor color; | |
2827 static GtkWidget *done = NULL; | |
2828 | |
2829 if (done != widget) | |
2830 { | |
2831 GtkStyle *style; | |
2832 | |
2833 style = gtk_widget_get_style(widget); | |
2834 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color)); | |
2835 shift_color(&color, -1, 0); | |
2836 done = widget; | |
2837 } | |
2838 | |
2839 return &color; | |
2840 } | |
2841 | |
2842 static void dupe_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, | |
2843 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) | |
2844 { | |
2845 DupeWindow *dw = data; | |
2846 gboolean set; | |
2847 | |
2848 gtk_tree_model_get(tree_model, iter, DUPE_COLUMN_COLOR, &set, -1); | |
2849 g_object_set(G_OBJECT(cell), | |
2850 "cell-background-gdk", dupe_listview_color_shifted(dw->listview), | |
2851 "cell-background-set", set, NULL); | |
2852 } | |
2853 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2854 static void dupe_listview_add_column(DupeWindow *dw, GtkWidget *listview, gint n, const gchar *title, gboolean image, gboolean right_justify) |
9 | 2855 { |
2856 GtkTreeViewColumn *column; | |
2857 GtkCellRenderer *renderer; | |
2858 | |
2859 column = gtk_tree_view_column_new(); | |
2860 gtk_tree_view_column_set_title(column, title); | |
2861 gtk_tree_view_column_set_min_width(column, 4); | |
2862 | |
2863 if (n != DUPE_COLUMN_RANK && | |
2864 n != DUPE_COLUMN_THUMB) | |
2865 { | |
2866 gtk_tree_view_column_set_resizable(column, TRUE); | |
2867 } | |
2868 | |
2869 if (!image) | |
2870 { | |
2871 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
2872 renderer = gtk_cell_renderer_text_new(); | |
2873 if (right_justify) | |
2874 { | |
2875 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); | |
2876 } | |
2877 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2878 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
2879 } | |
2880 else | |
2881 { | |
2882 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); | |
2883 renderer = gtk_cell_renderer_pixbuf_new(); | |
2884 cell_renderer_height_override(renderer); | |
2885 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2886 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n); | |
2887 } | |
2888 | |
2889 if (listview == dw->listview) | |
2890 { | |
2891 /* sets background before rendering */ | |
2892 gtk_tree_view_column_set_cell_data_func(column, renderer, dupe_listview_color_cb, dw, NULL); | |
2893 } | |
2894 | |
2895 gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); | |
2896 } | |
2897 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
2898 static void dupe_listview_set_height(GtkWidget *listview, gboolean thumb) |
9 | 2899 { |
2900 GtkTreeViewColumn *column; | |
2901 GtkCellRenderer *cell; | |
2902 GList *list; | |
2903 | |
2904 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), DUPE_COLUMN_THUMB - 1); | |
2905 if (!column) return; | |
2906 | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
2907 gtk_tree_view_column_set_fixed_width(column, (thumb) ? options->thumbnails.max_width : 4); |
442 | 2908 |
1767
96381fd3d133
Add compatibility for GTK 2.18
Klaus Ethgen <Klaus@Ethgen.de>
parents:
1698
diff
changeset
|
2909 list = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column)); |
9 | 2910 if (!list) return; |
2911 cell = list->data; | |
2912 g_list_free(list); | |
2913 | |
333
1ebdf8fb2c1a
Rename thumbnails related options.
Laurent Monin <geeqie@norz.org>
parents:
318
diff
changeset
|
2914 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL); |
9 | 2915 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview)); |
2916 } | |
2917 | |
2918 | |
2919 /* | |
2920 *------------------------------------------------------------------- | |
2921 * misc cb | |
2922 *------------------------------------------------------------------- | |
2923 */ | |
2924 | |
2925 static void dupe_window_show_thumb_cb(GtkWidget *widget, gpointer data) | |
2926 { | |
2927 DupeWindow *dw = data; | |
2928 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
2929 dw->show_thumbs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
2930 options->duplicates_thumbnails = dw->show_thumbs; |
9 | 2931 |
2932 if (dw->show_thumbs) | |
2933 { | |
2934 if (!dw->working) dupe_thumb_step(dw); | |
2935 } | |
2936 else | |
2937 { | |
2938 GtkTreeModel *store; | |
2939 GtkTreeIter iter; | |
1444 | 2940 gboolean valid; |
9 | 2941 |
2942 thumb_loader_free(dw->thumb_loader); | |
2943 dw->thumb_loader = NULL; | |
2944 | |
2945 store = gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview)); | |
2946 valid = gtk_tree_model_get_iter_first(store, &iter); | |
2947 | |
2948 while (valid) | |
2949 { | |
2950 gtk_list_store_set(GTK_LIST_STORE(store), &iter, DUPE_COLUMN_THUMB, NULL, -1); | |
2951 valid = gtk_tree_model_iter_next(store, &iter); | |
2952 } | |
2953 dupe_window_update_progress(dw, NULL, 0.0, FALSE); | |
2954 } | |
2955 | |
2956 dupe_listview_set_height(dw->listview, dw->show_thumbs); | |
2957 } | |
2958 | |
2429 | 2959 static void dupe_window_rotation_invariant_cb(GtkWidget *widget, gpointer data) |
2960 { | |
2961 DupeWindow *dw = data; | |
2962 | |
2963 options->rot_invariant_sim = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
2964 dupe_window_recompare(dw); | |
2965 } | |
2966 | |
2967 static void dupe_window_custom_threshold_cb(GtkWidget *widget, gpointer data) | |
2968 { | |
2969 DupeWindow *dw = data; | |
2970 DupeMatchType match_type; | |
2431 | 2971 GtkTreeModel *store; |
2429 | 2972 gboolean valid; |
2973 GtkTreeIter iter; | |
2974 | |
2975 options->duplicates_similarity_threshold = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); | |
2976 dw->match_mask = DUPE_MATCH_SIM_CUSTOM; | |
2977 | |
2978 store = gtk_combo_box_get_model(GTK_COMBO_BOX(dw->combo)); | |
2979 valid = gtk_tree_model_get_iter_first(store, &iter); | |
2980 while (valid) | |
2981 { | |
2982 gtk_tree_model_get(store, &iter, DUPE_MENU_COLUMN_MASK, &match_type, -1); | |
2983 if (match_type == DUPE_MATCH_SIM_CUSTOM) | |
2984 { | |
2985 break; | |
2986 } | |
2987 valid = gtk_tree_model_iter_next(store, &iter); | |
2988 } | |
2989 | |
2990 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dw->combo), &iter); | |
2991 dupe_window_recompare(dw); | |
2992 } | |
2993 | |
9 | 2994 static void dupe_popup_menu_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) |
2995 { | |
2996 GtkWidget *view = data; | |
2997 GtkTreePath *tpath; | |
2998 gint cx, cy, cw, ch; | |
2999 gint column; | |
3000 | |
3001 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view), &tpath, NULL); | |
3002 if (!tpath) return; | |
3003 | |
3004 if (gtk_tree_view_get_column(GTK_TREE_VIEW(view), DUPE_COLUMN_NAME - 1) != NULL) | |
3005 { | |
3006 column = DUPE_COLUMN_NAME - 1; | |
3007 } | |
3008 else | |
3009 { | |
3010 /* dw->second_listview */ | |
3011 column = 0; | |
3012 } | |
3013 tree_view_get_cell_clamped(GTK_TREE_VIEW(view), tpath, column, TRUE, &cx, &cy, &cw, &ch); | |
3014 gtk_tree_path_free(tpath); | |
3015 cy += ch; | |
3016 popup_menu_position_clamp(menu, &cx, &cy, 0); | |
3017 *x = cx; | |
3018 *y = cy; | |
3019 } | |
3020 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
3021 static gboolean dupe_window_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) |
9 | 3022 { |
3023 DupeWindow *dw = data; | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
3024 gboolean stop_signal = FALSE; |
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
3025 gboolean on_second; |
9 | 3026 GtkWidget *listview; |
3027 GtkTreeModel *store; | |
3028 GtkTreeSelection *selection; | |
3029 GList *slist; | |
3030 DupeItem *di = NULL; | |
3031 | |
1810
c3a79dda8ea7
GTK marks several functions as deprecated
Klaus Ethgen <Klaus@Ethgen.de>
parents:
1802
diff
changeset
|
3032 on_second = gtk_widget_has_focus(dw->second_listview); |
9 | 3033 |
3034 if (on_second) | |
3035 { | |
3036 listview = dw->second_listview; | |
3037 } | |
3038 else | |
3039 { | |
3040 listview = dw->listview; | |
3041 } | |
3042 | |
3043 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); | |
3044 slist = gtk_tree_selection_get_selected_rows(selection, &store); | |
3045 if (slist) | |
3046 { | |
3047 GtkTreePath *tpath; | |
3048 GtkTreeIter iter; | |
3049 GList *last; | |
3050 | |
3051 last = g_list_last(slist); | |
3052 tpath = last->data; | |
3053 | |
3054 /* last is newest selected file */ | |
3055 gtk_tree_model_get_iter(store, &iter, tpath); | |
3056 gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1); | |
3057 } | |
3058 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL); | |
3059 g_list_free(slist); | |
3060 | |
3061 if (event->state & GDK_CONTROL_MASK) | |
3062 { | |
3063 if (!on_second) | |
3064 { | |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3065 stop_signal = TRUE; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3066 switch (event->keyval) |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3067 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3068 case '1': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3069 case '2': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3070 case '3': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3071 case '4': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3072 case '5': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3073 case '6': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3074 case '7': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3075 case '8': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3076 case '9': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3077 case '0': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3078 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3079 case 'C': case 'c': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3080 file_util_copy(NULL, dupe_listview_get_selection(dw, listview), |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3081 NULL, dw->window); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3082 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3083 case 'M': case 'm': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3084 file_util_move(NULL, dupe_listview_get_selection(dw, listview), |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3085 NULL, dw->window); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3086 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3087 case 'R': case 'r': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3088 file_util_rename(NULL, dupe_listview_get_selection(dw, listview), dw->window); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3089 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3090 case 'D': case 'd': |
2860
b20a96b979a3
Fix #437: Delete to standard Trash directory
Colin Clark <colin.clark@cclark.uk>
parents:
2701
diff
changeset
|
3091 options->file_ops.safe_delete_enable = TRUE; |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3092 file_util_delete(NULL, dupe_listview_get_selection(dw, listview), dw->window); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3093 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3094 default: |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3095 stop_signal = FALSE; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3096 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3097 } |
9 | 3098 } |
3099 | |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3100 if (!stop_signal) |
9 | 3101 { |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3102 stop_signal = TRUE; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3103 switch (event->keyval) |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3104 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3105 case 'A': case 'a': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3106 if (event->state & GDK_SHIFT_MASK) |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3107 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3108 gtk_tree_selection_unselect_all(selection); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3109 } |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3110 else |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3111 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3112 gtk_tree_selection_select_all(selection); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3113 } |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3114 break; |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
3115 case GDK_KEY_Delete: case GDK_KEY_KP_Delete: |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3116 if (on_second) |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3117 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3118 dupe_second_clear(dw); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3119 dupe_window_recompare(dw); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3120 } |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3121 else |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3122 { |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3123 dupe_window_clear(dw); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3124 } |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3125 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3126 case 'L': case 'l': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3127 dupe_window_append_file_list(dw, FALSE); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3128 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3129 case 'T': case 't': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3130 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_thumbs), |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3131 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dw->button_thumbs))); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3132 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3133 case 'W': case 'w': |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3134 dupe_window_close(dw); |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3135 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3136 default: |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3137 stop_signal = FALSE; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3138 break; |
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3139 } |
9 | 3140 } |
3141 } | |
3142 else | |
3143 { | |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3144 stop_signal = TRUE; |
9 | 3145 switch (event->keyval) |
3146 { | |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
3147 case GDK_KEY_Return: case GDK_KEY_KP_Enter: |
9 | 3148 dupe_menu_view(dw, di, listview, FALSE); |
3149 break; | |
3150 case 'V': case 'v': | |
3151 dupe_menu_view(dw, di, listview, TRUE); | |
3152 break; | |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
3153 case GDK_KEY_Delete: case GDK_KEY_KP_Delete: |
9 | 3154 dupe_window_remove_selection(dw, listview); |
3155 break; | |
3156 case 'C': case 'c': | |
3157 if (!on_second) | |
3158 { | |
3159 dupe_window_collection_from_selection(dw); | |
3160 } | |
3161 break; | |
3162 case '1': | |
2483
b6ae0dd3a0c9
Fix assignment in dupe keypress function
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2431
diff
changeset
|
3163 options->duplicates_select_type = DUPE_SELECT_GROUP1; |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3164 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP1); |
9 | 3165 break; |
3166 case '2': | |
2483
b6ae0dd3a0c9
Fix assignment in dupe keypress function
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2431
diff
changeset
|
3167 options->duplicates_select_type = DUPE_SELECT_GROUP2; |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3168 dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP2); |
9 | 3169 break; |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
3170 case GDK_KEY_Menu: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
3171 case GDK_KEY_F10: |
9 | 3172 if (!on_second) |
3173 { | |
3174 GtkWidget *menu; | |
3175 | |
3176 menu = dupe_menu_popup_main(dw, di); | |
3177 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, | |
3178 dupe_popup_menu_pos_cb, listview, 0, GDK_CURRENT_TIME); | |
3179 } | |
3180 else | |
3181 { | |
3182 GtkWidget *menu; | |
3183 | |
3184 menu = dupe_menu_popup_second(dw, di); | |
3185 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, | |
3186 dupe_popup_menu_pos_cb, listview, 0, GDK_CURRENT_TIME); | |
3187 } | |
3188 break; | |
3189 default: | |
85
f5f7943f2f60
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
John Ellis <johne@verizon.net>
parents:
64
diff
changeset
|
3190 stop_signal = FALSE; |
9 | 3191 break; |
3192 } | |
3193 } | |
2694 | 3194 if (!stop_signal && is_help_key(event)) |
3195 { | |
3196 help_window_show("GuideImageSearchFindingDuplicates.html"); | |
3197 stop_signal = TRUE; | |
3198 } | |
9 | 3199 |
3200 return stop_signal; | |
3201 } | |
3202 | |
3203 | |
3204 void dupe_window_clear(DupeWindow *dw) | |
3205 { | |
3206 GtkListStore *store; | |
3207 | |
3208 dupe_check_stop(dw); | |
3209 | |
3210 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview))); | |
3211 gtk_list_store_clear(store); | |
3212 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(dw->listview)); | |
3213 | |
3214 g_list_free(dw->dupes); | |
3215 dw->dupes = NULL; | |
3216 | |
3217 dupe_list_free(dw->list); | |
3218 dw->list = NULL; | |
3219 | |
3220 dupe_match_reset_list(dw->second_list); | |
3221 | |
3222 dupe_window_update_count(dw, FALSE); | |
3223 dupe_window_update_progress(dw, NULL, 0.0, FALSE); | |
3224 } | |
3225 | |
3226 void dupe_window_close(DupeWindow *dw) | |
3227 { | |
3228 dupe_check_stop(dw); | |
3229 | |
3230 dupe_window_list = g_list_remove(dupe_window_list, dw); | |
3231 gtk_widget_destroy(dw->window); | |
3232 | |
3233 g_list_free(dw->dupes); | |
3234 dupe_list_free(dw->list); | |
3235 | |
3236 dupe_list_free(dw->second_list); | |
3237 | |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3238 file_data_unregister_notify_func(dupe_notify_cb, dw); |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3239 |
9 | 3240 g_free(dw); |
3241 } | |
3242 | |
3243 static gint dupe_window_delete(GtkWidget *widget, GdkEvent *event, gpointer data) | |
3244 { | |
3245 DupeWindow *dw = data; | |
3246 dupe_window_close(dw); | |
3247 | |
3248 return TRUE; | |
3249 } | |
3250 | |
3251 /* collection and files can be NULL */ | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3252 DupeWindow *dupe_window_new() |
9 | 3253 { |
3254 DupeWindow *dw; | |
3255 GtkWidget *vbox; | |
3256 GtkWidget *scrolled; | |
3257 GtkWidget *frame; | |
3258 GtkWidget *status_box; | |
3259 GtkWidget *label; | |
3260 GtkWidget *button; | |
3261 GtkListStore *store; | |
3262 GtkTreeSelection *selection; | |
3263 GdkGeometry geometry; | |
3264 | |
3265 dw = g_new0(DupeWindow, 1); | |
3266 | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3267 dw->match_mask = DUPE_MATCH_NAME; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3268 if (options->duplicates_match == DUPE_MATCH_NAME) dw->match_mask = DUPE_MATCH_NAME; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3269 if (options->duplicates_match == DUPE_MATCH_SIZE) dw->match_mask = DUPE_MATCH_SIZE; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3270 if (options->duplicates_match == DUPE_MATCH_DATE) dw->match_mask = DUPE_MATCH_DATE; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3271 if (options->duplicates_match == DUPE_MATCH_DIM) dw->match_mask = DUPE_MATCH_DIM; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3272 if (options->duplicates_match == DUPE_MATCH_SUM) dw->match_mask = DUPE_MATCH_SUM; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3273 if (options->duplicates_match == DUPE_MATCH_PATH) dw->match_mask = DUPE_MATCH_PATH; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3274 if (options->duplicates_match == DUPE_MATCH_SIM_HIGH) dw->match_mask = DUPE_MATCH_SIM_HIGH; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3275 if (options->duplicates_match == DUPE_MATCH_SIM_MED) dw->match_mask = DUPE_MATCH_SIM_MED; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3276 if (options->duplicates_match == DUPE_MATCH_SIM_LOW) dw->match_mask = DUPE_MATCH_SIM_LOW; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3277 if (options->duplicates_match == DUPE_MATCH_SIM_CUSTOM) dw->match_mask = DUPE_MATCH_SIM_CUSTOM; |
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3278 if (options->duplicates_match == DUPE_MATCH_NAME_CI) dw->match_mask = DUPE_MATCH_NAME_CI; |
9 | 3279 |
289
d4d7e7aa0d88
Simplify and unify gtk_window creation with the help of
Laurent Monin <geeqie@norz.org>
parents:
288
diff
changeset
|
3280 dw->window = window_new(GTK_WINDOW_TOPLEVEL, "dupe", NULL, NULL, _("Find duplicates")); |
2909
2e7fd08bfbe4
DEBUG_NAME() function for use with GTKInspector
Colin Clark <colin.clark@cclark.uk>
parents:
2860
diff
changeset
|
3281 DEBUG_NAME(dw->window); |
442 | 3282 |
1029
b1a912dee214
Use a constant for minimal window size. Set it to 32 for all dialogs.
Laurent Monin <geeqie@norz.org>
parents:
1022
diff
changeset
|
3283 geometry.min_width = DEFAULT_MINIMAL_WINDOW_SIZE; |
b1a912dee214
Use a constant for minimal window size. Set it to 32 for all dialogs.
Laurent Monin <geeqie@norz.org>
parents:
1022
diff
changeset
|
3284 geometry.min_height = DEFAULT_MINIMAL_WINDOW_SIZE; |
9 | 3285 geometry.base_width = DUPE_DEF_WIDTH; |
3286 geometry.base_height = DUPE_DEF_HEIGHT; | |
3287 gtk_window_set_geometry_hints(GTK_WINDOW(dw->window), NULL, &geometry, | |
3288 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); | |
3289 | |
3290 gtk_window_set_default_size(GTK_WINDOW(dw->window), DUPE_DEF_WIDTH, DUPE_DEF_HEIGHT); | |
3291 | |
3292 gtk_window_set_resizable(GTK_WINDOW(dw->window), TRUE); | |
513
6743a5928e09
Remove whitespace between function name and first parenthesis for the sake of consistency. (pass 2)
Laurent Monin <geeqie@norz.org>
parents:
512
diff
changeset
|
3293 gtk_container_set_border_width(GTK_CONTAINER(dw->window), 0); |
442 | 3294 |
3295 g_signal_connect(G_OBJECT(dw->window), "delete_event", | |
9 | 3296 G_CALLBACK(dupe_window_delete), dw); |
3297 g_signal_connect(G_OBJECT(dw->window), "key_press_event", | |
3298 G_CALLBACK(dupe_window_keypress_cb), dw); | |
3299 | |
3300 vbox = gtk_vbox_new(FALSE, 0); | |
3301 gtk_container_add(GTK_CONTAINER(dw->window), vbox); | |
3302 gtk_widget_show(vbox); | |
3303 | |
3304 dw->table = gtk_table_new(1, 3, FALSE); | |
3305 gtk_box_pack_start(GTK_BOX(vbox), dw->table, TRUE, TRUE, 0); | |
3306 gtk_widget_show(dw->table); | |
3307 | |
3308 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
3309 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
3310 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
3311 gtk_table_attach_defaults(GTK_TABLE(dw->table), scrolled, 0, 2, 0, 1); | |
442 | 3312 gtk_widget_show(scrolled); |
9 | 3313 |
3314 store = gtk_list_store_new(9, G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF, | |
3315 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, | |
3316 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); | |
3317 dw->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
3318 g_object_unref(store); | |
3319 | |
3320 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->listview)); | |
3321 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE); | |
3322 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dw->listview), TRUE); | |
3323 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(dw->listview), FALSE); | |
3324 | |
3325 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_RANK, "", FALSE, TRUE); | |
3326 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_THUMB, "", TRUE, FALSE); | |
3327 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_NAME, _("Name"), FALSE, FALSE); | |
3328 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_SIZE, _("Size"), FALSE, TRUE); | |
3329 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_DATE, _("Date"), FALSE, TRUE); | |
3330 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_DIMENSIONS, _("Dimensions"), FALSE, FALSE); | |
3331 dupe_listview_add_column(dw, dw->listview, DUPE_COLUMN_PATH, _("Path"), FALSE, FALSE); | |
3332 | |
3333 gtk_container_add(GTK_CONTAINER(scrolled), dw->listview); | |
3334 gtk_widget_show(dw->listview); | |
3335 | |
3336 dw->second_vbox = gtk_vbox_new(FALSE, 0); | |
3337 gtk_table_attach_defaults(GTK_TABLE(dw->table), dw->second_vbox, 2, 3, 0, 1); | |
3338 if (dw->second_set) | |
3339 { | |
3340 gtk_table_set_col_spacings(GTK_TABLE(dw->table), PREF_PAD_GAP); | |
3341 gtk_widget_show(dw->second_vbox); | |
3342 } | |
3343 else | |
3344 { | |
3345 gtk_table_set_col_spacings(GTK_TABLE(dw->table), 0); | |
3346 } | |
3347 | |
3348 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
3349 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
3350 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
3351 gtk_box_pack_start(GTK_BOX(dw->second_vbox), scrolled, TRUE, TRUE, 0); | |
442 | 3352 gtk_widget_show(scrolled); |
9 | 3353 |
3354 store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); | |
3355 dw->second_listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
3356 | |
3357 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dw->second_listview)); | |
3358 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE); | |
3359 | |
3360 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dw->second_listview), TRUE); | |
3361 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(dw->second_listview), FALSE); | |
3362 | |
3363 dupe_listview_add_column(dw, dw->second_listview, 1, _("Compare to:"), FALSE, FALSE); | |
3364 | |
3365 gtk_container_add(GTK_CONTAINER(scrolled), dw->second_listview); | |
442 | 3366 gtk_widget_show(dw->second_listview); |
9 | 3367 |
3368 dw->second_status_label = gtk_label_new(""); | |
3369 gtk_box_pack_start(GTK_BOX(dw->second_vbox), dw->second_status_label, FALSE, FALSE, 0); | |
3370 gtk_widget_show(dw->second_status_label); | |
3371 | |
3372 pref_line(dw->second_vbox, GTK_ORIENTATION_HORIZONTAL); | |
3373 | |
3374 status_box = pref_box_new(vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0); | |
3375 | |
3376 label = gtk_label_new(_("Compare by:")); | |
3377 gtk_box_pack_start(GTK_BOX(status_box), label, FALSE, FALSE, PREF_PAD_SPACE); | |
3378 gtk_widget_show(label); | |
3379 | |
3380 dupe_menu_setup(dw); | |
3381 gtk_box_pack_start(GTK_BOX(status_box), dw->combo, FALSE, FALSE, 0); | |
3382 gtk_widget_show(dw->combo); | |
3383 | |
3384 dw->button_thumbs = gtk_check_button_new_with_label(_("Thumbnails")); | |
2426
28546abc2b90
Fix #435: Remember duplicates settings
Colin Clark <cclark@mcb.net>
parents:
2425
diff
changeset
|
3385 dw->show_thumbs = options->duplicates_thumbnails; |
9 | 3386 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_thumbs), dw->show_thumbs); |
3387 g_signal_connect(G_OBJECT(dw->button_thumbs), "toggled", | |
3388 G_CALLBACK(dupe_window_show_thumb_cb), dw); | |
3389 gtk_box_pack_start(GTK_BOX(status_box), dw->button_thumbs, FALSE, FALSE, PREF_PAD_SPACE); | |
3390 gtk_widget_show(dw->button_thumbs); | |
3391 | |
2429 | 3392 dw->button_rotation_invariant = gtk_check_button_new_with_label(_("Ignore Rotation")); |
3393 gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_rotation_invariant), "Ignore image orientation"); | |
3394 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_rotation_invariant), options->rot_invariant_sim); | |
3395 g_signal_connect(G_OBJECT(dw->button_rotation_invariant), "toggled", | |
3396 G_CALLBACK(dupe_window_rotation_invariant_cb), dw); | |
3397 gtk_box_pack_start(GTK_BOX(status_box), dw->button_rotation_invariant, FALSE, FALSE, PREF_PAD_SPACE); | |
3398 gtk_widget_show(dw->button_rotation_invariant); | |
3399 | |
9 | 3400 button = gtk_check_button_new_with_label(_("Compare two file sets")); |
3401 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dw->second_set); | |
3402 g_signal_connect(G_OBJECT(button), "toggled", | |
3403 G_CALLBACK(dupe_second_set_toggle_cb), dw); | |
3404 gtk_box_pack_end(GTK_BOX(status_box), button, FALSE, FALSE, PREF_PAD_SPACE); | |
3405 gtk_widget_show(button); | |
3406 | |
3407 status_box = gtk_hbox_new(FALSE, 0); | |
442 | 3408 gtk_box_pack_start(GTK_BOX(vbox), status_box, FALSE, FALSE, 0); |
3409 gtk_widget_show(status_box); | |
9 | 3410 |
3411 frame = gtk_frame_new(NULL); | |
2909
2e7fd08bfbe4
DEBUG_NAME() function for use with GTKInspector
Colin Clark <colin.clark@cclark.uk>
parents:
2860
diff
changeset
|
3412 DEBUG_NAME(frame); |
9 | 3413 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); |
3414 gtk_box_pack_start(GTK_BOX(status_box), frame, TRUE, TRUE, 0); | |
3415 gtk_widget_show(frame); | |
3416 | |
3417 dw->status_label = gtk_label_new(""); | |
3418 gtk_container_add(GTK_CONTAINER(frame), dw->status_label); | |
3419 gtk_widget_show(dw->status_label); | |
3420 | |
2489
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3421 button = gtk_check_button_new_with_label(_("Sort")); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3422 gtk_widget_set_tooltip_text(GTK_WIDGET(button), "Sort by group totals"); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3423 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), options->sort_totals); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3424 g_signal_connect(G_OBJECT(button), "toggled", |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3425 G_CALLBACK(dupe_sort_totals_toggle_cb), dw); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3426 gtk_box_pack_start(GTK_BOX(status_box), button, FALSE, FALSE, PREF_PAD_SPACE); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3427 gtk_widget_show(button); |
ab6a0d1bd821
Fix #477: similarity duplicate search
Colin Clark <colin.clark@cclark.uk>
parents:
2483
diff
changeset
|
3428 |
2429 | 3429 label = gtk_label_new(_("Custom Threshold")); |
3430 gtk_box_pack_start(GTK_BOX(status_box), label, FALSE, FALSE, PREF_PAD_SPACE); | |
3431 gtk_widget_show(label); | |
3432 dw->custom_threshold = gtk_spin_button_new_with_range(1, 100, 1); | |
3433 gtk_widget_set_tooltip_text(GTK_WIDGET(dw->custom_threshold), "Custom similarity threshold"); | |
3434 gtk_spin_button_set_value(GTK_SPIN_BUTTON(dw->custom_threshold), options->duplicates_similarity_threshold); | |
3435 g_signal_connect(G_OBJECT(dw->custom_threshold), "value_changed", | |
3436 G_CALLBACK(dupe_window_custom_threshold_cb), dw); | |
3437 gtk_box_pack_start(GTK_BOX(status_box), dw->custom_threshold, FALSE, FALSE, PREF_PAD_SPACE); | |
3438 gtk_widget_show(dw->custom_threshold); | |
3439 | |
9 | 3440 dw->extra_label = gtk_progress_bar_new(); |
3441 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), 0.0); | |
2408
5d4305b34e8f
Fix #401: Find duplicates status bar text
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
3442 #if GTK_CHECK_VERSION(3,0,0) |
5d4305b34e8f
Fix #401: Find duplicates status bar text
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
3443 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(dw->extra_label), ""); |
5d4305b34e8f
Fix #401: Find duplicates status bar text
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
3444 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(dw->extra_label), TRUE); |
5d4305b34e8f
Fix #401: Find duplicates status bar text
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
3445 #endif |
9 | 3446 gtk_box_pack_end(GTK_BOX(status_box), dw->extra_label, FALSE, FALSE, 0); |
3447 gtk_widget_show(dw->extra_label); | |
3448 | |
3449 dupe_dnd_init(dw); | |
3450 | |
3451 /* order is important here, dnd_init should be seeing mouse | |
3452 * presses before we possibly handle (and stop) the signal | |
3453 */ | |
3454 g_signal_connect(G_OBJECT(dw->listview), "button_press_event", | |
3455 G_CALLBACK(dupe_listview_press_cb), dw); | |
3456 g_signal_connect(G_OBJECT(dw->listview), "button_release_event", | |
3457 G_CALLBACK(dupe_listview_release_cb), dw); | |
3458 g_signal_connect(G_OBJECT(dw->second_listview), "button_press_event", | |
3459 G_CALLBACK(dupe_listview_press_cb), dw); | |
3460 g_signal_connect(G_OBJECT(dw->second_listview), "button_release_event", | |
3461 G_CALLBACK(dupe_listview_release_cb), dw); | |
3462 | |
3463 gtk_widget_show(dw->window); | |
3464 | |
3465 dupe_window_update_count(dw, TRUE); | |
3466 dupe_window_update_progress(dw, NULL, 0.0, FALSE); | |
3467 | |
3468 dupe_window_list = g_list_append(dupe_window_list, dw); | |
3469 | |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3470 file_data_register_notify_func(dupe_notify_cb, dw, NOTIFY_PRIORITY_MEDIUM); |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3471 |
9 | 3472 return dw; |
3473 } | |
3474 | |
3475 /* | |
3476 *------------------------------------------------------------------- | |
3477 * dnd confirm dir | |
3478 *------------------------------------------------------------------- | |
3479 */ | |
3480 | |
3481 typedef struct { | |
3482 DupeWindow *dw; | |
3483 GList *list; | |
3484 } CDupeConfirmD; | |
3485 | |
3486 static void confirm_dir_list_cancel(GtkWidget *widget, gpointer data) | |
3487 { | |
3488 /* do nothing */ | |
3489 } | |
3490 | |
3491 static void confirm_dir_list_add(GtkWidget *widget, gpointer data) | |
3492 { | |
3493 CDupeConfirmD *d = data; | |
3494 GList *work; | |
3495 | |
3496 dupe_window_add_files(d->dw, d->list, FALSE); | |
3497 | |
3498 work = d->list; | |
3499 while (work) | |
3500 { | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3501 FileData *fd = work->data; |
9 | 3502 work = work->next; |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3503 if (isdir(fd->path)) |
9 | 3504 { |
780
f5dc8c7d6a5a
Drop initialization to NULL since filelist_read() will take care of it.
Laurent Monin <geeqie@norz.org>
parents:
753
diff
changeset
|
3505 GList *list; |
9 | 3506 |
783
0e45ed008a1c
replaced directory path with FileData* dir_fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
780
diff
changeset
|
3507 filelist_read(fd, &list, NULL); |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3508 list = filelist_filter(list, FALSE); |
9 | 3509 if (list) |
3510 { | |
3511 dupe_window_add_files(d->dw, list, FALSE); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3512 filelist_free(list); |
9 | 3513 } |
3514 } | |
3515 } | |
3516 } | |
3517 | |
3518 static void confirm_dir_list_recurse(GtkWidget *widget, gpointer data) | |
3519 { | |
3520 CDupeConfirmD *d = data; | |
3521 dupe_window_add_files(d->dw, d->list, TRUE); | |
3522 } | |
3523 | |
3524 static void confirm_dir_list_skip(GtkWidget *widget, gpointer data) | |
3525 { | |
3526 CDupeConfirmD *d = data; | |
3527 dupe_window_add_files(d->dw, d->list, FALSE); | |
3528 } | |
3529 | |
3530 static void confirm_dir_list_destroy(GtkWidget *widget, gpointer data) | |
3531 { | |
3532 CDupeConfirmD *d = data; | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3533 filelist_free(d->list); |
9 | 3534 g_free(d); |
3535 } | |
3536 | |
3537 static GtkWidget *dupe_confirm_dir_list(DupeWindow *dw, GList *list) | |
3538 { | |
3539 GtkWidget *menu; | |
3540 CDupeConfirmD *d; | |
3541 | |
3542 d = g_new0(CDupeConfirmD, 1); | |
3543 d->dw = dw; | |
3544 d->list = list; | |
3545 | |
3546 menu = popup_menu_short_lived(); | |
3547 g_signal_connect(G_OBJECT(menu), "destroy", | |
3548 G_CALLBACK(confirm_dir_list_destroy), d); | |
3549 | |
3550 menu_item_add_stock(menu, _("Dropped list includes folders."), GTK_STOCK_DND_MULTIPLE, NULL, NULL); | |
3551 menu_item_add_divider(menu); | |
3552 menu_item_add_stock(menu, _("_Add contents"), GTK_STOCK_OK, G_CALLBACK(confirm_dir_list_add), d); | |
3553 menu_item_add_stock(menu, _("Add contents _recursive"), GTK_STOCK_ADD, G_CALLBACK(confirm_dir_list_recurse), d); | |
3554 menu_item_add_stock(menu, _("_Skip folders"), GTK_STOCK_REMOVE, G_CALLBACK(confirm_dir_list_skip), d); | |
3555 menu_item_add_divider(menu); | |
3556 menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, G_CALLBACK(confirm_dir_list_cancel), d); | |
3557 | |
3558 return menu; | |
3559 } | |
3560 | |
3561 /* | |
3562 *------------------------------------------------------------------- | |
3563 * dnd | |
3564 *------------------------------------------------------------------- | |
3565 */ | |
3566 | |
3567 static GtkTargetEntry dupe_drag_types[] = { | |
442 | 3568 { "text/uri-list", 0, TARGET_URI_LIST }, |
3569 { "text/plain", 0, TARGET_TEXT_PLAIN } | |
9 | 3570 }; |
3571 static gint n_dupe_drag_types = 2; | |
3572 | |
3573 static GtkTargetEntry dupe_drop_types[] = { | |
442 | 3574 { TARGET_APP_COLLECTION_MEMBER_STRING, 0, TARGET_APP_COLLECTION_MEMBER }, |
3575 { "text/uri-list", 0, TARGET_URI_LIST } | |
9 | 3576 }; |
3577 static gint n_dupe_drop_types = 2; | |
3578 | |
3579 static void dupe_dnd_data_set(GtkWidget *widget, GdkDragContext *context, | |
3580 GtkSelectionData *selection_data, guint info, | |
3581 guint time, gpointer data) | |
3582 { | |
3583 DupeWindow *dw = data; | |
3584 GList *list; | |
3585 | |
3586 switch (info) | |
3587 { | |
3588 case TARGET_URI_LIST: | |
3589 case TARGET_TEXT_PLAIN: | |
3590 list = dupe_listview_get_selection(dw, widget); | |
3591 if (!list) return; | |
2040 | 3592 uri_selection_data_set_uris_from_filelist(selection_data, list); |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3593 filelist_free(list); |
9 | 3594 break; |
3595 default: | |
3596 break; | |
3597 } | |
3598 } | |
3599 | |
3600 static void dupe_dnd_data_get(GtkWidget *widget, GdkDragContext *context, | |
3601 gint x, gint y, | |
3602 GtkSelectionData *selection_data, guint info, | |
3603 guint time, gpointer data) | |
3604 { | |
3605 DupeWindow *dw = data; | |
3606 GtkWidget *source; | |
3607 GList *list = NULL; | |
3608 GList *work; | |
3609 | |
3610 source = gtk_drag_get_source_widget(context); | |
3611 if (source == dw->listview || source == dw->second_listview) return; | |
3612 | |
3613 dw->second_drop = (dw->second_set && widget == dw->second_listview); | |
3614 | |
3615 switch (info) | |
3616 { | |
3617 case TARGET_APP_COLLECTION_MEMBER: | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
3618 collection_from_dnd_data((gchar *)gtk_selection_data_get_data(selection_data), &list, NULL); |
9 | 3619 break; |
3620 case TARGET_URI_LIST: | |
2040 | 3621 list = uri_filelist_from_gtk_selection_data(selection_data); |
9 | 3622 work = list; |
516
768d10237b88
Convert the minority of while() to while ().
Laurent Monin <geeqie@norz.org>
parents:
513
diff
changeset
|
3623 while (work) |
9 | 3624 { |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3625 FileData *fd = work->data; |
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3626 if (isdir(fd->path)) |
9 | 3627 { |
3628 GtkWidget *menu; | |
3629 menu = dupe_confirm_dir_list(dw, list); | |
3630 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, time); | |
3631 return; | |
3632 } | |
3633 work = work->next; | |
3634 } | |
3635 break; | |
3636 default: | |
3637 list = NULL; | |
3638 break; | |
3639 } | |
3640 | |
3641 if (list) | |
3642 { | |
3643 dupe_window_add_files(dw, list, FALSE); | |
138
5be5d1c53016
replaced gchar* path with FileData *fd
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
85
diff
changeset
|
3644 filelist_free(list); |
9 | 3645 } |
3646 } | |
3647 | |
1420
6cda3d9d6a7b
Use gboolean where applicable, for the sake of consistency.
Laurent Monin <geeqie@norz.org>
parents:
1397
diff
changeset
|
3648 static void dupe_dest_set(GtkWidget *widget, gboolean enable) |
9 | 3649 { |
3650 if (enable) | |
3651 { | |
3652 gtk_drag_dest_set(widget, | |
3653 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, | |
3654 dupe_drop_types, n_dupe_drop_types, | |
3655 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); | |
3656 | |
3657 } | |
3658 else | |
3659 { | |
3660 gtk_drag_dest_unset(widget); | |
3661 } | |
3662 } | |
3663 | |
3664 static void dupe_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
3665 { | |
3666 DupeWindow *dw = data; | |
3667 dupe_dest_set(dw->listview, FALSE); | |
3668 dupe_dest_set(dw->second_listview, FALSE); | |
3669 | |
3670 if (dw->click_item && !dupe_listview_item_is_selected(dw, dw->click_item, widget)) | |
3671 { | |
3672 GtkListStore *store; | |
3673 GtkTreeIter iter; | |
3674 | |
3675 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(widget))); | |
3676 if (dupe_listview_find_item(store, dw->click_item, &iter) >= 0) | |
3677 { | |
3678 GtkTreeSelection *selection; | |
3679 GtkTreePath *tpath; | |
3680 | |
3681 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
3682 gtk_tree_selection_unselect_all(selection); | |
3683 gtk_tree_selection_select_iter(selection, &iter); | |
3684 | |
3685 tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); | |
3686 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
3687 gtk_tree_path_free(tpath); | |
3688 } | |
3689 } | |
3690 | |
3691 if (dw->show_thumbs && | |
3692 widget == dw->listview && | |
3693 dw->click_item && dw->click_item->pixbuf) | |
3694 { | |
3695 GtkTreeSelection *selection; | |
3696 gint items; | |
3697 | |
3698 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); | |
3699 items = gtk_tree_selection_count_selected_rows(selection); | |
3700 dnd_set_drag_icon(widget, context, dw->click_item->pixbuf, items); | |
3701 } | |
3702 } | |
3703 | |
3704 static void dupe_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
3705 { | |
3706 DupeWindow *dw = data; | |
3707 dupe_dest_set(dw->listview, TRUE); | |
3708 dupe_dest_set(dw->second_listview, TRUE); | |
3709 } | |
3710 | |
3711 static void dupe_dnd_init(DupeWindow *dw) | |
3712 { | |
3713 gtk_drag_source_set(dw->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, | |
3714 dupe_drag_types, n_dupe_drag_types, | |
3715 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
3716 g_signal_connect(G_OBJECT(dw->listview), "drag_data_get", | |
3717 G_CALLBACK(dupe_dnd_data_set), dw); | |
3718 g_signal_connect(G_OBJECT(dw->listview), "drag_begin", | |
3719 G_CALLBACK(dupe_dnd_begin), dw); | |
3720 g_signal_connect(G_OBJECT(dw->listview), "drag_end", | |
3721 G_CALLBACK(dupe_dnd_end), dw); | |
3722 | |
3723 dupe_dest_set(dw->listview, TRUE); | |
3724 g_signal_connect(G_OBJECT(dw->listview), "drag_data_received", | |
3725 G_CALLBACK(dupe_dnd_data_get), dw); | |
3726 | |
3727 gtk_drag_source_set(dw->second_listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, | |
3728 dupe_drag_types, n_dupe_drag_types, | |
3729 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
3730 g_signal_connect(G_OBJECT(dw->second_listview), "drag_data_get", | |
3731 G_CALLBACK(dupe_dnd_data_set), dw); | |
3732 g_signal_connect(G_OBJECT(dw->second_listview), "drag_begin", | |
3733 G_CALLBACK(dupe_dnd_begin), dw); | |
3734 g_signal_connect(G_OBJECT(dw->second_listview), "drag_end", | |
3735 G_CALLBACK(dupe_dnd_end), dw); | |
3736 | |
3737 dupe_dest_set(dw->second_listview, TRUE); | |
3738 g_signal_connect(G_OBJECT(dw->second_listview), "drag_data_received", | |
3739 G_CALLBACK(dupe_dnd_data_get), dw); | |
3740 } | |
3741 | |
3742 /* | |
3743 *------------------------------------------------------------------- | |
3744 * maintenance (move, delete, etc.) | |
3745 *------------------------------------------------------------------- | |
3746 */ | |
3747 | |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3748 static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data) |
9 | 3749 { |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3750 DupeWindow *dw = data; |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3751 |
1432
7f454e7d07a3
improved notification system
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1420
diff
changeset
|
3752 if (!(type & NOTIFY_CHANGE) || !fd->change) return; |
1498
2b0712dcf139
improved debug messages
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1445
diff
changeset
|
3753 |
2b0712dcf139
improved debug messages
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1445
diff
changeset
|
3754 DEBUG_1("Notify dupe: %s %04x", fd->path, type); |
2185
c14a1d8e6aa4
Trim trailing white spaces on empty lines.
Laurent Monin <zas@norz.org>
parents:
2184
diff
changeset
|
3755 |
1347
84d289bde1ea
Add missing space between switch and first parenthesis.
Laurent Monin <geeqie@norz.org>
parents:
1346
diff
changeset
|
3756 switch (fd->change->type) |
9 | 3757 { |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3758 case FILEDATA_CHANGE_MOVE: |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3759 case FILEDATA_CHANGE_RENAME: |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3760 dupe_item_update_fd(dw, fd); |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3761 break; |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3762 case FILEDATA_CHANGE_COPY: |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3763 break; |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3764 case FILEDATA_CHANGE_DELETE: |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3765 while (dupe_item_remove_by_path(dw, fd->path)); |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3766 break; |
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3767 case FILEDATA_CHANGE_UNSPECIFIED: |
1211
cc4d3023ced3
most of the metadata options now works
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1174
diff
changeset
|
3768 case FILEDATA_CHANGE_WRITE_METADATA: |
794
b02c3ea4b28d
used new notification in dupe.c
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
786
diff
changeset
|
3769 break; |
9 | 3770 } |
3771 | |
3772 } | |
1055
4bbdfab3c89a
Adding a vim modeline to all files - patch by Klaus Ethgen
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1049
diff
changeset
|
3773 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ |