2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "collect-dlg.h"
26 #include "collect-io.h"
27 #include "collect-table.h"
32 #include "layout_image.h"
33 #include "layout_util.h"
35 #include "pixbuf_util.h"
37 #include "ui_fileops.h"
38 #include "ui_tree_edit.h"
42 #include <gdk/gdkkeysyms.h> /* for keyboard values */
45 #define COLLECT_DEF_WIDTH 440
46 #define COLLECT_DEF_HEIGHT 450
49 * list of paths to collections */
52 * @brief List of currently open Collections.
54 * Type ::_CollectionData
56 static GList *collection_list = NULL;
59 * @brief List of currently open Collection windows.
61 * Type ::_CollectWindow
63 static GList *collection_window_list = NULL;
65 static void collection_window_get_geometry(CollectWindow *cw);
66 static void collection_window_refresh(CollectWindow *cw);
67 static void collection_window_update_title(CollectWindow *cw);
68 static void collection_window_add(CollectWindow *cw, CollectInfo *ci);
69 static void collection_window_insert(CollectWindow *cw, CollectInfo *ci);
70 static void collection_window_remove(CollectWindow *cw, CollectInfo *ci);
71 static void collection_window_update(CollectWindow *cw, CollectInfo *ci);
73 static void collection_window_close(CollectWindow *cw);
75 static void collection_notify_cb(FileData *fd, NotifyType type, gpointer data);
78 *-------------------------------------------------------------------
80 *-------------------------------------------------------------------
83 CollectInfo *collection_info_new(FileData *fd, struct stat *st, GdkPixbuf *pixbuf)
89 ci = g_new0(CollectInfo, 1);
90 ci->fd = file_data_ref(fd);
93 if (ci->pixbuf) g_object_ref(ci->pixbuf);
98 void collection_info_free_thumb(CollectInfo *ci)
100 if (ci->pixbuf) g_object_unref(ci->pixbuf);
104 void collection_info_free(CollectInfo *ci)
108 file_data_unref(ci->fd);
109 collection_info_free_thumb(ci);
113 void collection_info_set_thumb(CollectInfo *ci, GdkPixbuf *pixbuf)
115 if (pixbuf) g_object_ref(pixbuf);
116 collection_info_free_thumb(ci);
120 gboolean collection_info_load_thumb(CollectInfo *ci)
122 if (!ci) return FALSE;
124 collection_info_free_thumb(ci);
126 log_printf("collection_info_load_thumb not implemented!\n(because an instant thumb loader not implemented)");
130 void collection_list_free(GList *list)
136 collection_info_free((CollectInfo *)work->data);
142 /* an ugly static var, well what ya gonna do ? */
143 static SortType collection_list_sort_method = SORT_NAME;
145 static gint collection_list_sort_cb(gconstpointer a, gconstpointer b)
147 const CollectInfo *cia = a;
148 const CollectInfo *cib = b;
150 switch (collection_list_sort_method)
158 if (cia->fd->size < cib->fd->size) return -1;
159 if (cia->fd->size > cib->fd->size) return 1;
163 if (cia->fd->date < cib->fd->date) return -1;
164 if (cia->fd->date > cib->fd->date) return 1;
168 if (cia->fd->cdate < cib->fd->cdate) return -1;
169 if (cia->fd->cdate > cib->fd->cdate) return 1;
173 return utf8_compare(cia->fd->path, cib->fd->path, options->file_sort.case_sensitive);
176 if (cia->fd->format_class < cib->fd->format_class) return -1;
177 if (cia->fd->format_class > cib->fd->format_class) return 1;
179 #ifdef HAVE_STRVERSCMP
181 return strverscmp(cia->fd->name, cib->fd->name);
188 if (options->file_sort.case_sensitive)
189 return strcmp(cia->fd->collate_key_name, cib->fd->collate_key_name);
191 return strcmp(cia->fd->collate_key_name_nocase, cib->fd->collate_key_name_nocase);
194 GList *collection_list_sort(GList *list, SortType method)
196 if (method == SORT_NONE) return list;
198 collection_list_sort_method = method;
200 return g_list_sort(list, collection_list_sort_cb);
203 GList *collection_list_randomize(GList *list)
205 guint random, length, i;
207 GList *nlist, *olist;
209 length = g_list_length(list);
210 if (!length) return NULL;
212 srand((unsigned int)time(NULL)); // Initialize random generator (hasn't to be that much strong)
214 for (i = 0; i < length; i++)
216 random = (guint) (1.0 * length * rand()/(RAND_MAX + 1.0));
217 olist = g_list_nth(list, i);
218 nlist = g_list_nth(list, random);
220 olist->data = nlist->data;
227 GList *collection_list_add(GList *list, CollectInfo *ci, SortType method)
229 if (method != SORT_NONE)
231 collection_list_sort_method = method;
232 list = g_list_insert_sorted(list, ci, collection_list_sort_cb);
236 list = g_list_append(list, ci);
242 GList *collection_list_insert(GList *list, CollectInfo *ci, CollectInfo *insert_ci, SortType method)
244 if (method != SORT_NONE)
246 collection_list_sort_method = method;
247 list = g_list_insert_sorted(list, ci, collection_list_sort_cb);
253 point = g_list_find(list, insert_ci);
254 list = uig_list_insert_link(list, point, ci);
260 GList *collection_list_remove(GList *list, CollectInfo *ci)
262 list = g_list_remove(list, ci);
263 collection_info_free(ci);
267 CollectInfo *collection_list_find_fd(GList *list, FileData *fd)
273 CollectInfo *ci = work->data;
274 if (ci->fd == fd) return ci;
281 GList *collection_list_to_filelist(GList *list)
283 GList *filelist = NULL;
288 CollectInfo *info = work->data;
289 filelist = g_list_prepend(filelist, file_data_ref(info->fd));
293 filelist = g_list_reverse(filelist);
297 CollectWindow *collection_window_find(CollectionData *cd)
301 work = collection_window_list;
304 CollectWindow *cw = work->data;
305 if (cw->cd == cd) return cw;
312 CollectWindow *collection_window_find_by_path(const gchar *path)
316 if (!path) return NULL;
318 work = collection_window_list;
321 CollectWindow *cw = work->data;
322 if (cw->cd->path && strcmp(cw->cd->path, path) == 0) return cw;
330 * @brief Checks string for existence of Collection.
331 * @param[in] param Filename, with or without extension of any collection
332 * @returns full pathname if found or NULL
334 * Return value must be freed with g_free()
336 gchar *collection_path(gchar *param)
339 gchar *full_name = NULL;
341 if (file_extension_match(param, GQ_COLLECTION_EXT))
343 path = g_build_filename(get_collections_dir(), param, NULL);
345 else if (file_extension_match(param, NULL))
347 full_name = g_strconcat(param, GQ_COLLECTION_EXT, NULL);
348 path = g_build_filename(get_collections_dir(), full_name, NULL);
362 * @brief Checks input string for existence of Collection.
363 * @param[in] param Filename with or without extension of any collection
364 * @returns TRUE if found
368 gboolean is_collection(gchar *param)
372 name = collection_path(param);
382 *-------------------------------------------------------------------
383 * please use these to actually add/remove stuff
384 *-------------------------------------------------------------------
387 CollectionData *collection_new(const gchar *path)
390 static gint untitled_counter = 0;
392 cd = g_new0(CollectionData, 1);
394 cd->ref = 1; /* starts with a ref of 1 */
395 cd->sort_method = SORT_NONE;
396 cd->window_w = COLLECT_DEF_WIDTH;
397 cd->window_h = COLLECT_DEF_HEIGHT;
398 cd->existence = g_hash_table_new(NULL, NULL);
402 cd->path = g_strdup(path);
403 cd->name = g_strdup(filename_from_path(cd->path));
408 if (untitled_counter == 0)
410 cd->name = g_strdup(_("Untitled"));
414 cd->name = g_strdup_printf(_("Untitled (%d)"), untitled_counter + 1);
420 file_data_register_notify_func(collection_notify_cb, cd, NOTIFY_PRIORITY_MEDIUM);
423 collection_list = g_list_append(collection_list, cd);
428 void collection_free(CollectionData *cd)
432 DEBUG_1("collection \"%s\" freed", cd->name);
434 collection_load_stop(cd);
435 collection_list_free(cd->list);
437 file_data_unregister_notify_func(collection_notify_cb, cd);
439 collection_list = g_list_remove(collection_list, cd);
441 g_hash_table_destroy(cd->existence);
449 void collection_ref(CollectionData *cd)
453 DEBUG_1("collection \"%s\" ref count = %d", cd->name, cd->ref);
456 void collection_unref(CollectionData *cd)
460 DEBUG_1("collection \"%s\" ref count = %d", cd->name, cd->ref);
468 void collection_path_changed(CollectionData *cd)
470 collection_window_update_title(collection_window_find(cd));
473 gint collection_to_number(CollectionData *cd)
475 return g_list_index(collection_list, cd);
478 CollectionData *collection_from_number(gint n)
480 return g_list_nth_data(collection_list, n);
483 CollectionData *collection_from_dnd_data(const gchar *data, GList **list, GList **info_list)
486 gint collection_number;
489 if (list) *list = NULL;
490 if (info_list) *info_list = NULL;
492 if (strncmp(data, "COLLECTION:", 11) != 0) return NULL;
496 collection_number = atoi(ptr);
497 cd = collection_from_number(collection_number);
498 if (!cd) return NULL;
500 if (!list && !info_list) return cd;
502 while (*ptr != '\0' && *ptr != '\n' ) ptr++;
503 if (*ptr == '\0') return cd;
511 item_number = (guint) atoi(ptr);
512 while (*ptr != '\n' && *ptr != '\0') ptr++;
516 while (*ptr == '\n') ptr++;
518 info = g_list_nth_data(cd->list, item_number);
521 if (list) *list = g_list_append(*list, file_data_ref(info->fd));
522 if (info_list) *info_list = g_list_append(*info_list, info);
528 gchar *collection_info_list_to_dnd_data(CollectionData *cd, GList *list, gint *length)
535 gint collection_number;
538 if (!list) return NULL;
540 collection_number = collection_to_number(cd);
541 if (collection_number < 0) return NULL;
543 text = g_strdup_printf("COLLECTION:%d\n", collection_number);
544 *length += strlen(text);
545 temp = g_list_prepend(temp, text);
550 gint item_number = g_list_index(cd->list, work->data);
554 if (item_number < 0) continue;
556 text = g_strdup_printf("%d\n", item_number);
557 temp = g_list_prepend(temp, text);
558 *length += strlen(text);
561 *length += 1; /* ending nul char */
563 uri_text = g_malloc(*length);
566 work = g_list_last(temp);
570 gchar *text = work->data;
575 memcpy(ptr, text, len);
581 string_list_free(temp);
586 gint collection_info_valid(CollectionData *cd, CollectInfo *info)
588 if (collection_to_number(cd) < 0) return FALSE;
590 return (g_list_index(cd->list, info) != 0);
593 CollectInfo *collection_next_by_info(CollectionData *cd, CollectInfo *info)
597 work = g_list_find(cd->list, info);
599 if (!work) return NULL;
601 if (work) return work->data;
605 CollectInfo *collection_prev_by_info(CollectionData *cd, CollectInfo *info)
609 work = g_list_find(cd->list, info);
611 if (!work) return NULL;
613 if (work) return work->data;
617 CollectInfo *collection_get_first(CollectionData *cd)
619 if (cd->list) return cd->list->data;
624 CollectInfo *collection_get_last(CollectionData *cd)
628 list = g_list_last(cd->list);
630 if (list) return list->data;
635 void collection_set_sort_method(CollectionData *cd, SortType method)
639 if (cd->sort_method == method) return;
641 cd->sort_method = method;
642 cd->list = collection_list_sort(cd->list, cd->sort_method);
643 if (cd->list) cd->changed = TRUE;
645 collection_window_refresh(collection_window_find(cd));
648 void collection_randomize(CollectionData *cd)
652 cd->list = collection_list_randomize(cd->list);
653 cd->sort_method = SORT_NONE;
654 if (cd->list) cd->changed = TRUE;
656 collection_window_refresh(collection_window_find(cd));
659 void collection_set_update_info_func(CollectionData *cd,
660 void (*func)(CollectionData *, CollectInfo *, gpointer), gpointer data)
662 cd->info_updated_func = func;
663 cd->info_updated_data = data;
666 static CollectInfo *collection_info_new_if_not_exists(CollectionData *cd, struct stat *st, FileData *fd)
670 if (g_hash_table_lookup(cd->existence, fd->path)) return NULL;
672 ci = collection_info_new(fd, st, NULL);
673 if (ci) g_hash_table_insert(cd->existence, fd->path, "");
677 gboolean collection_add_check(CollectionData *cd, FileData *fd, gboolean sorted, gboolean must_exist)
682 if (!fd) return FALSE;
684 g_assert(fd->magick == FD_MAGICK);
688 valid = (stat_utf8(fd->path, &st) && !S_ISDIR(st.st_mode));
701 ci = collection_info_new_if_not_exists(cd, &st, fd);
702 if (!ci) return FALSE;
703 DEBUG_3("add to collection: %s", fd->path);
705 cd->list = collection_list_add(cd->list, ci, sorted ? cd->sort_method : SORT_NONE);
708 if (!sorted || cd->sort_method == SORT_NONE)
710 collection_window_add(collection_window_find(cd), ci);
714 collection_window_insert(collection_window_find(cd), ci);
721 gboolean collection_add(CollectionData *cd, FileData *fd, gboolean sorted)
723 return collection_add_check(cd, fd, sorted, TRUE);
726 gboolean collection_insert(CollectionData *cd, FileData *fd, CollectInfo *insert_ci, gboolean sorted)
730 if (!insert_ci) return collection_add(cd, fd, sorted);
732 if (stat_utf8(fd->path, &st) >= 0 && !S_ISDIR(st.st_mode))
736 ci = collection_info_new_if_not_exists(cd, &st, fd);
737 if (!ci) return FALSE;
739 DEBUG_3("insert in collection: %s", fd->path);
741 cd->list = collection_list_insert(cd->list, ci, insert_ci, sorted ? cd->sort_method : SORT_NONE);
744 collection_window_insert(collection_window_find(cd), ci);
752 gboolean collection_remove(CollectionData *cd, FileData *fd)
756 ci = collection_list_find_fd(cd->list, fd);
758 if (!ci) return FALSE;
760 g_hash_table_remove(cd->existence, fd->path);
762 cd->list = g_list_remove(cd->list, ci);
765 collection_window_remove(collection_window_find(cd), ci);
766 collection_info_free(ci);
771 static void collection_remove_by_info(CollectionData *cd, CollectInfo *info)
773 if (!info || !g_list_find(cd->list, info)) return;
775 cd->list = g_list_remove(cd->list, info);
776 cd->changed = (cd->list != NULL);
778 collection_window_remove(collection_window_find(cd), info);
779 collection_info_free(info);
782 void collection_remove_by_info_list(CollectionData *cd, GList *list)
790 /* more efficient (in collect-table) to remove a single item this way */
791 collection_remove_by_info(cd, (CollectInfo *)list->data);
798 cd->list = collection_list_remove(cd->list, work->data);
801 cd->changed = (cd->list != NULL);
803 collection_window_refresh(collection_window_find(cd));
806 gboolean collection_rename(CollectionData *cd, FileData *fd)
809 ci = collection_list_find_fd(cd->list, fd);
811 if (!ci) return FALSE;
815 collection_window_update(collection_window_find(cd), ci);
820 void collection_update_geometry(CollectionData *cd)
822 collection_window_get_geometry(collection_window_find(cd));
826 *-------------------------------------------------------------------
827 * simple maintenance for renaming, deleting
828 *-------------------------------------------------------------------
831 static void collection_notify_cb(FileData *fd, NotifyType type, gpointer data)
833 CollectionData *cd = data;
835 if (!(type & NOTIFY_CHANGE) || !fd->change) return;
837 DEBUG_1("Notify collection: %s %04x", fd->path, type);
839 switch (fd->change->type)
841 case FILEDATA_CHANGE_MOVE:
842 case FILEDATA_CHANGE_RENAME:
843 collection_rename(cd, fd);
845 case FILEDATA_CHANGE_COPY:
847 case FILEDATA_CHANGE_DELETE:
848 while (collection_remove(cd, fd));
850 case FILEDATA_CHANGE_UNSPECIFIED:
851 case FILEDATA_CHANGE_WRITE_METADATA:
859 *-------------------------------------------------------------------
861 *-------------------------------------------------------------------
864 static gboolean collection_window_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data)
866 CollectWindow *cw = data;
867 gboolean stop_signal = FALSE;
870 if (event->state & GDK_CONTROL_MASK)
873 switch (event->keyval)
887 if (event->state & GDK_SHIFT_MASK)
889 collection_table_unselect_all(cw->table);
893 collection_table_select_all(cw->table);
897 list = layout_list(NULL);
900 collection_table_add_filelist(cw->table, list);
905 file_util_copy(NULL, collection_table_selection_get_list(cw->table), NULL, cw->window);
908 file_util_move(NULL, collection_table_selection_get_list(cw->table), NULL, cw->window);
911 file_util_rename(NULL, collection_table_selection_get_list(cw->table), cw->window);
914 file_util_delete(NULL, collection_table_selection_get_list(cw->table), cw->window);
917 collection_dialog_save_as(NULL, cw->cd);
920 collection_window_close(cw);
930 switch (event->keyval)
932 case GDK_KEY_Return: case GDK_KEY_KP_Enter:
933 layout_image_set_collection(NULL, cw->cd,
934 collection_table_get_focus_info(cw->table));
937 view_window_new_from_collection(cw->cd,
938 collection_table_get_focus_info(cw->table));
943 collection_dialog_save_as(NULL, cw->cd);
945 else if (!collection_save(cw->cd, cw->cd->path))
947 log_printf("failed saving to collection path: %s\n", cw->cd->path);
951 collection_dialog_append(NULL, cw->cd);
954 collection_set_sort_method(cw->cd, SORT_NAME);
956 #ifdef HAVE_STRVERSCMP
958 collection_set_sort_method(cw->cd, SORT_NUMBER);
962 collection_set_sort_method(cw->cd, SORT_TIME);
965 collection_set_sort_method(cw->cd, SORT_SIZE);
968 if (event->state & GDK_SHIFT_MASK)
972 info = collection_table_get_focus_info(cw->table);
974 print_window_new(info->fd, collection_table_selection_get_list(cw->table),
975 collection_list_to_filelist(cw->cd->list), cw->window);
979 collection_set_sort_method(cw->cd, SORT_PATH);
983 if (event->state & GDK_MOD1_MASK)
985 options->collections.rectangular_selection = !(options->collections.rectangular_selection);
988 case GDK_KEY_Delete: case GDK_KEY_KP_Delete:
989 list = g_list_copy(cw->table->selection);
992 collection_remove_by_info_list(cw->cd, list);
997 collection_remove_by_info(cw->cd, collection_table_get_focus_info(cw->table));
1001 stop_signal = FALSE;
1005 if (!stop_signal && is_help_key(event))
1007 help_window_show("GuideCollections.html");
1015 *-------------------------------------------------------------------
1017 *-------------------------------------------------------------------
1019 static void collection_window_get_geometry(CollectWindow *cw)
1027 window = gtk_widget_get_window(cw->window);
1028 gdk_window_get_position(window, &cd->window_x, &cd->window_y);
1029 cd->window_w = gdk_window_get_width(window);
1030 cd->window_h = gdk_window_get_height(window);
1031 cd->window_read = TRUE;
1034 static void collection_window_refresh(CollectWindow *cw)
1038 collection_table_refresh(cw->table);
1041 static void collection_window_update_title(CollectWindow *cw)
1043 gboolean free_name = FALSE;
1049 if (file_extension_match(cw->cd->name, GQ_COLLECTION_EXT))
1051 name = remove_extension_from_path(cw->cd->name);
1056 name = cw->cd->name;
1059 buf = g_strdup_printf(_("%s - Collection - %s"), name, GQ_APPNAME);
1060 if (free_name) g_free(name);
1061 gtk_window_set_title(GTK_WINDOW(cw->window), buf);
1065 static void collection_window_update_info(CollectionData *cd, CollectInfo *ci, gpointer data)
1067 CollectWindow *cw = data;
1069 collection_table_file_update(cw->table, ci);
1072 static void collection_window_add(CollectWindow *cw, CollectInfo *ci)
1076 if (!ci->pixbuf) collection_load_thumb_idle(cw->cd);
1077 collection_table_file_add(cw->table, ci);
1080 static void collection_window_insert(CollectWindow *cw, CollectInfo *ci)
1084 if (!ci->pixbuf) collection_load_thumb_idle(cw->cd);
1085 collection_table_file_insert(cw->table, ci);
1089 static void collection_window_remove(CollectWindow *cw, CollectInfo *ci)
1093 collection_table_file_remove(cw->table, ci);
1096 static void collection_window_update(CollectWindow *cw, CollectInfo *ci)
1100 collection_table_file_update(cw->table, ci);
1101 collection_table_file_update(cw->table, NULL);
1104 static void collection_window_close_final(CollectWindow *cw)
1106 if (cw->close_dialog) return;
1108 collection_window_list = g_list_remove(collection_window_list, cw);
1109 collection_window_get_geometry(cw);
1111 gtk_widget_destroy(cw->window);
1113 collection_set_update_info_func(cw->cd, NULL, NULL);
1114 collection_unref(cw->cd);
1119 static void collection_close_save_cb(GenericDialog *gd, gpointer data)
1121 CollectWindow *cw = data;
1123 cw->close_dialog = NULL;
1124 generic_dialog_close(gd);
1128 collection_dialog_save_close(NULL, cw->cd);
1131 else if (!collection_save(cw->cd, cw->cd->path))
1134 buf = g_strdup_printf(_("Failed to save the collection:\n%s"), cw->cd->path);
1135 warning_dialog(_("Save Failed"), buf, GTK_STOCK_DIALOG_ERROR, cw->window);
1140 collection_window_close_final(cw);
1143 static void collection_close_close_cb(GenericDialog *gd, gpointer data)
1145 CollectWindow *cw = data;
1147 cw->close_dialog = NULL;
1148 generic_dialog_close(gd);
1150 collection_window_close_final(cw);
1153 static void collection_close_cancel_cb(GenericDialog *gd, gpointer data)
1155 CollectWindow *cw = data;
1157 cw->close_dialog = NULL;
1158 generic_dialog_close(gd);
1161 static void collection_close_dlg_show(CollectWindow *cw)
1165 if (cw->close_dialog)
1167 gtk_window_present(GTK_WINDOW(cw->close_dialog));
1171 gd = generic_dialog_new(_("Close collection"),
1172 "close_collection", cw->window, FALSE,
1173 collection_close_cancel_cb, cw);
1174 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION,
1175 _("Close collection"),
1176 _("Collection has been modified.\nSave first?"), TRUE);
1178 generic_dialog_add_button(gd, GTK_STOCK_SAVE, NULL, collection_close_save_cb, TRUE);
1179 generic_dialog_add_button(gd, GTK_STOCK_DELETE, _("_Discard"), collection_close_close_cb, FALSE);
1181 cw->close_dialog = gd->dialog;
1183 gtk_widget_show(gd->dialog);
1186 static void collection_window_close(CollectWindow *cw)
1188 if (!cw->cd->changed && !cw->close_dialog)
1190 collection_window_close_final(cw);
1194 collection_close_dlg_show(cw);
1197 void collection_window_close_by_collection(CollectionData *cd)
1201 cw = collection_window_find(cd);
1202 if (cw) collection_window_close_final(cw);
1206 * @brief Check if any Collection windows have unsaved data
1207 * @returns TRUE if unsaved data exists
1209 * Also saves window geometry for Collection windows that have
1212 gboolean collection_window_modified_exists(void)
1219 work = collection_window_list;
1222 CollectWindow *cw = work->data;
1223 if (cw->cd->changed)
1229 if (!collection_save(cw->table->cd, cw->table->cd->path))
1231 log_printf("failed saving to collection path: %s\n", cw->table->cd->path);
1240 static gboolean collection_window_delete(GtkWidget *widget, GdkEvent *event, gpointer data)
1242 CollectWindow *cw = data;
1243 collection_window_close(cw);
1248 CollectWindow *collection_window_new(const gchar *path)
1253 GtkWidget *status_label;
1254 GtkWidget *extra_label;
1255 GdkGeometry geometry;
1257 /* If the collection is already opened in another window, return that one */
1258 cw = collection_window_find_by_path(path);
1264 cw = g_new0(CollectWindow, 1);
1266 collection_window_list = g_list_append(collection_window_list, cw);
1268 cw->cd = collection_new(path);
1270 cw->window = window_new(GTK_WINDOW_TOPLEVEL, "collection", PIXBUF_INLINE_ICON_BOOK, NULL, NULL);
1272 geometry.min_width = DEFAULT_MINIMAL_WINDOW_SIZE;
1273 geometry.min_height = DEFAULT_MINIMAL_WINDOW_SIZE;
1274 geometry.base_width = COLLECT_DEF_WIDTH;
1275 geometry.base_height = COLLECT_DEF_HEIGHT;
1276 gtk_window_set_geometry_hints(GTK_WINDOW(cw->window), NULL, &geometry,
1277 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
1280 if (options->save_window_positions && path && collection_load_only_geometry(cw->cd, path))
1282 gtk_window_set_default_size(GTK_WINDOW(cw->window), cw->cd->window_w, cw->cd->window_h);
1283 gtk_window_move(GTK_WINDOW(cw->window), cw->cd->window_x, cw->cd->window_y);
1287 gtk_window_set_default_size(GTK_WINDOW(cw->window), COLLECT_DEF_WIDTH, COLLECT_DEF_HEIGHT);
1290 gtk_window_set_resizable(GTK_WINDOW(cw->window), TRUE);
1291 collection_window_update_title(cw);
1292 gtk_container_set_border_width(GTK_CONTAINER(cw->window), 0);
1294 g_signal_connect(G_OBJECT(cw->window), "delete_event",
1295 G_CALLBACK(collection_window_delete), cw);
1297 g_signal_connect(G_OBJECT(cw->window), "key_press_event",
1298 G_CALLBACK(collection_window_keypress), cw);
1300 vbox = gtk_vbox_new(FALSE, 0);
1301 gtk_container_add(GTK_CONTAINER(cw->window), vbox);
1302 gtk_widget_show(vbox);
1304 cw->table = collection_table_new(cw->cd);
1305 gtk_box_pack_start(GTK_BOX(vbox), cw->table->scrolled, TRUE, TRUE, 0);
1306 gtk_widget_show(cw->table->scrolled);
1308 cw->status_box = gtk_hbox_new(TRUE, 0);
1309 gtk_box_pack_start(GTK_BOX(vbox), cw->status_box, FALSE, FALSE, 0);
1310 gtk_widget_show(cw->status_box);
1312 frame = gtk_frame_new(NULL);
1313 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
1314 gtk_box_pack_start(GTK_BOX(cw->status_box), frame, TRUE, TRUE, 0);
1315 gtk_widget_show(frame);
1317 status_label = gtk_label_new("");
1318 gtk_container_add(GTK_CONTAINER(frame), status_label);
1319 gtk_widget_show(status_label);
1321 extra_label = gtk_progress_bar_new();
1322 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(extra_label), 0.0);
1323 #if GTK_CHECK_VERSION(3,0,0)
1324 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(extra_label), "");
1325 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(extra_label), TRUE);
1327 gtk_box_pack_start(GTK_BOX(cw->status_box), extra_label, TRUE, TRUE, 0);
1328 gtk_widget_show(extra_label);
1330 collection_table_set_labels(cw->table, status_label, extra_label);
1332 gtk_widget_show(cw->window);
1333 gtk_widget_grab_focus(cw->table->listview);
1335 collection_set_update_info_func(cw->cd, collection_window_update_info, cw);
1337 if (path && *path == G_DIR_SEPARATOR) collection_load_begin(cw->cd, NULL, COLLECTION_LOAD_NONE);
1341 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */