Mercurial > geeqie
comparison src/filedata.c @ 590:2b7b966f61cf
started implementation of API for sidecar files
author | nadvornik |
---|---|
date | Mon, 05 May 2008 20:51:51 +0000 |
parents | 905688aa2317 |
children | f8c93e1d728d |
comparison
equal
deleted
inserted
replaced
589:46ddfaf13235 | 590:2b7b966f61cf |
---|---|
885 filelist_recursive_append(&list, d); | 885 filelist_recursive_append(&list, d); |
886 filelist_free(d); | 886 filelist_free(d); |
887 | 887 |
888 return list; | 888 return list; |
889 } | 889 } |
890 | |
891 | |
892 | |
893 /* | |
894 * file_data - operates on the given fd | |
895 * file_data_sc - operates on the given fd + sidecars - all fds linked via fd->sidecar_files or fd->parent | |
896 */ | |
897 | |
898 | |
899 /* return list of sidecar file extensions in a string */ | |
900 gchar *file_data_sc_list_to_string(FileData *fd); // now gchar *sidecar_file_data_list_to_string(FileData *fd) | |
901 | |
902 | |
903 /* disables / enables grouping for particular file, sends UPDATE notification */ | |
904 void file_data_disable_grouping(FileData *fd); // now file_data_disconnect_sidecar_file, broken | |
905 void file_data_disable_grouping(FileData *fd); | |
906 | |
907 /* runs stat on a file and sends UPDATE notification if it has been changed */ | |
908 void file_data_sc_update(FileData *fd); | |
909 | |
910 | |
911 | |
912 | |
913 /* | |
914 * add FileDataChangeInfo (see typedefs.h) for the given operation | |
915 * uses file_data_add_change_info | |
916 * | |
917 * fails if the fd->change already exists - change operations can't run in parallel | |
918 * fd->change_info works as a lock | |
919 * | |
920 * dest can be NULL - in this case the current name is used for now, it will | |
921 * be changed later | |
922 */ | |
923 | |
924 /* | |
925 FileDataChangeInfo types: | |
926 COPY | |
927 MOVE - patch is changed, name may be changed too | |
928 RENAME - path remains unchanged, name is changed | |
929 extension should remain (FIXME should we allow editing extension? it will make problems wth grouping) | |
930 sidecar names are changed too, extensions are not changed | |
931 DELETE | |
932 UPDATE - file size, date or grouping has been changed | |
933 */ | |
934 | |
935 gboolean file_data_add_ci(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest) | |
936 { | |
937 | |
938 FileDataChangeInfo *fdci; | |
939 | |
940 if (fd->change) return FALSE; | |
941 | |
942 fdci = g_new0(FileDataChangeInfo, 1); | |
943 | |
944 fdci->type = type; | |
945 | |
946 if (src) | |
947 fdci->source = g_strdup(src); | |
948 else | |
949 fdci->source = g_strdup(fd->path); | |
950 | |
951 if (dest) | |
952 fdci->dest = g_strdup(dest); | |
953 | |
954 fd->change = fdci; | |
955 | |
956 return TRUE; | |
957 } | |
958 | |
959 void file_data_free_ci(FileData *fd) | |
960 { | |
961 FileDataChangeInfo *fdci = fd->change; | |
962 | |
963 if (!fdci) | |
964 return; | |
965 | |
966 g_free(fdci->source); | |
967 g_free(fdci->dest); | |
968 | |
969 g_free(fdci); | |
970 | |
971 fd->change = NULL; | |
972 } | |
973 | |
974 | |
975 static gboolean file_data_sc_add_ci(FileData *fd, FileDataChangeType type) | |
976 { | |
977 GList *work; | |
978 if (fd->parent) fd = fd->parent; | |
979 | |
980 if (fd->change) return FALSE; | |
981 work = fd->sidecar_files; | |
982 while (work) | |
983 { | |
984 FileData *sfd = work->data; | |
985 if (sfd->change) return FALSE; | |
986 work = work->next; | |
987 } | |
988 | |
989 file_data_add_ci(fd, type, NULL, NULL); | |
990 | |
991 work = fd->sidecar_files; | |
992 while (work) | |
993 { | |
994 FileData *sfd = work->data; | |
995 file_data_add_ci(sfd, type, NULL, NULL); | |
996 work = work->next; | |
997 } | |
998 | |
999 return TRUE; | |
1000 } | |
1001 | |
1002 static gboolean file_data_sc_check_ci(FileData *fd, FileDataChangeType type) | |
1003 { | |
1004 GList *work; | |
1005 if (fd->parent) fd = fd->parent; | |
1006 | |
1007 if (!fd->change) return FALSE; | |
1008 if (fd->change->type != type) return FALSE; | |
1009 work = fd->sidecar_files; | |
1010 while (work) | |
1011 { | |
1012 FileData *sfd = work->data; | |
1013 if (!sfd->change) return FALSE; | |
1014 if (sfd->change->type != type) return FALSE; | |
1015 work = work->next; | |
1016 } | |
1017 return TRUE; | |
1018 } | |
1019 | |
1020 | |
1021 gboolean file_data_sc_add_ci_copy(FileData *fd, gchar *dest_path) | |
1022 { | |
1023 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE; | |
1024 file_data_sc_update_ci_copy(fd, dest_path); | |
1025 return TRUE; | |
1026 } | |
1027 | |
1028 gboolean file_data_sc_add_ci_move(FileData *fd, gchar *dest_path) | |
1029 { | |
1030 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE; | |
1031 file_data_sc_update_ci_move(fd, dest_path); | |
1032 return TRUE; | |
1033 } | |
1034 | |
1035 gboolean file_data_sc_add_ci_rename(FileData *fd, gchar *dest_path) | |
1036 { | |
1037 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE; | |
1038 file_data_sc_update_ci_rename(fd, dest_path); | |
1039 return TRUE; | |
1040 } | |
1041 | |
1042 gboolean file_data_sc_add_ci_delete(FileData *fd) | |
1043 { | |
1044 return file_data_sc_add_ci(fd, FILEDATA_CHANGE_DELETE); | |
1045 } | |
1046 | |
1047 gboolean file_data_sc_add_ci_update(FileData *fd) | |
1048 { | |
1049 return file_data_sc_add_ci(fd, FILEDATA_CHANGE_UPDATE); | |
1050 } | |
1051 | |
1052 void file_data_sc_free_ci(FileData *fd) | |
1053 { | |
1054 GList *work; | |
1055 if (fd->parent) fd = fd->parent; | |
1056 | |
1057 file_data_free_ci(fd); | |
1058 | |
1059 work = fd->sidecar_files; | |
1060 while (work) | |
1061 { | |
1062 FileData *sfd = work->data; | |
1063 file_data_free_ci(sfd); | |
1064 work = work->next; | |
1065 } | |
1066 } | |
1067 | |
1068 | |
1069 /* | |
1070 * update existing fd->change, it will be used from dialog callbacks for interactive editing | |
1071 * fails if fd->change does not exist or the change type does not match | |
1072 */ | |
1073 | |
1074 static void file_data_update_ci_dest(FileData *fd, gchar *dest_path) | |
1075 { | |
1076 g_free(fd->change->dest); | |
1077 fd->change->dest = g_strdup(dest_path); | |
1078 } | |
1079 | |
1080 static void file_data_update_ci_dest_preserve_ext(FileData *fd, gchar *dest_path) | |
1081 { | |
1082 const char *extension = extension_from_path(fd->change->source); | |
1083 g_free(fd->change->dest); | |
1084 fd->change->dest = g_strdup_printf("%*s%s", (int)(extension_from_path(dest_path) - dest_path), dest_path, extension); | |
1085 } | |
1086 | |
1087 static void file_data_sc_update_ci(FileData *fd, gchar *dest_path) | |
1088 { | |
1089 GList *work; | |
1090 if (fd->parent) fd = fd->parent; | |
1091 | |
1092 file_data_update_ci_dest(fd, dest_path); | |
1093 work = fd->sidecar_files; | |
1094 while (work) | |
1095 { | |
1096 FileData *sfd = work->data; | |
1097 file_data_update_ci_dest_preserve_ext(sfd, dest_path); | |
1098 work = work->next; | |
1099 } | |
1100 } | |
1101 | |
1102 gint file_data_sc_update_ci_copy(FileData *fd, gchar *dest_path) | |
1103 { | |
1104 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE; | |
1105 file_data_sc_update_ci(fd, dest_path); | |
1106 return TRUE; | |
1107 } | |
1108 | |
1109 gint file_data_sc_update_ci_move(FileData *fd, gchar *dest_path) | |
1110 { | |
1111 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE; | |
1112 file_data_sc_update_ci(fd, dest_path); | |
1113 return TRUE; | |
1114 } | |
1115 | |
1116 gint file_data_sc_update_ci_rename(FileData *fd, gchar *dest_path) | |
1117 { | |
1118 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE; | |
1119 file_data_sc_update_ci(fd, dest_path); | |
1120 return TRUE; | |
1121 } | |
1122 | |
1123 | |
1124 | |
1125 /* | |
1126 * check dest paths - dest image exists, etc. | |
1127 * returns FIXME | |
1128 * it should detect all possible problems with the planned operation | |
1129 */ | |
1130 | |
1131 gint file_data_sc_check_ci_dest(FileData *fd) | |
1132 { | |
1133 } | |
1134 | |
1135 | |
1136 | |
1137 | |
1138 /* | |
1139 * perform the change described by FileFataChangeInfo | |
1140 * it is used for internal operations, | |
1141 * this function actually operates with files on the filesystem | |
1142 * it should implement safe delete | |
1143 */ | |
1144 | |
1145 static gboolean file_data_perform_move(FileData *fd) | |
1146 { | |
1147 g_assert(!strcmp(fd->change->source, fd->path)); | |
1148 return move_file(fd->change->source, fd->change->dest); | |
1149 } | |
1150 | |
1151 static gboolean file_data_perform_copy(FileData *fd) | |
1152 { | |
1153 g_assert(!strcmp(fd->change->source, fd->path)); | |
1154 return copy_file(fd->change->source, fd->change->dest); | |
1155 } | |
1156 | |
1157 static gboolean file_data_perform_delete(FileData *fd) | |
1158 { | |
1159 return unlink_file(fd->path); | |
1160 } | |
1161 | |
1162 static gboolean file_data_perform_ci(FileData *fd) | |
1163 { | |
1164 FileDataChangeType type = fd->change->type; | |
1165 switch (type) | |
1166 { | |
1167 case FILEDATA_CHANGE_MOVE: | |
1168 return file_data_perform_move(fd); | |
1169 case FILEDATA_CHANGE_COPY: | |
1170 return file_data_perform_copy(fd); | |
1171 case FILEDATA_CHANGE_RENAME: | |
1172 return file_data_perform_move(fd); /* the same as move */ | |
1173 case FILEDATA_CHANGE_DELETE: | |
1174 return file_data_perform_delete(fd); | |
1175 case FILEDATA_CHANGE_UPDATE: | |
1176 /* notring to do here */ | |
1177 break; | |
1178 } | |
1179 return TRUE; | |
1180 } | |
1181 | |
1182 | |
1183 | |
1184 gboolean file_data_sc_perform_ci(FileData *fd) | |
1185 { | |
1186 GList *work; | |
1187 gboolean ret = TRUE; | |
1188 FileDataChangeType type = fd->change->type; | |
1189 if (!file_data_sc_check_ci(fd, type)) return FALSE; | |
1190 | |
1191 work = fd->sidecar_files; | |
1192 while (work) | |
1193 { | |
1194 FileData *sfd = work->data; | |
1195 if (!file_data_perform_ci(sfd)) ret = FALSE; | |
1196 work = work->next; | |
1197 } | |
1198 if (!file_data_perform_ci(fd)) ret = FALSE; | |
1199 return ret; | |
1200 } | |
1201 | |
1202 /* | |
1203 * updates FileData structure according to FileDataChangeInfo | |
1204 */ | |
1205 | |
1206 static void file_data_apply_ci(FileData *fd) | |
1207 { | |
1208 FileDataChangeType type = fd->change->type; | |
1209 /* FIXME delete ?*/ | |
1210 if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_COPY || type == FILEDATA_CHANGE_RENAME) | |
1211 { | |
1212 g_free(fd->path); | |
1213 g_hash_table_remove(file_data_pool, fd->original_path); | |
1214 g_free(fd->original_path); | |
1215 file_data_set_path(fd, fd->change->dest); | |
1216 fd->original_path = g_strdup(fd->change->dest); | |
1217 g_hash_table_insert(file_data_pool, fd->original_path, fd); | |
1218 } | |
1219 } | |
1220 | |
1221 gint file_data_sc_apply_ci(FileData *fd) // now file_data_do_change | |
1222 { | |
1223 GList *work; | |
1224 FileDataChangeType type = fd->change->type; | |
1225 if (!file_data_sc_check_ci(fd, type)) return FALSE; | |
1226 | |
1227 work = fd->sidecar_files; | |
1228 while (work) | |
1229 { | |
1230 FileData *sfd = work->data; | |
1231 file_data_apply_ci(sfd); | |
1232 work = work->next; | |
1233 } | |
1234 file_data_apply_ci(fd); | |
1235 return TRUE; | |
1236 } | |
1237 | |
1238 | |
1239 /* | |
1240 * notify other modules about the change described by FileFataChangeInfo | |
1241 */ | |
1242 | |
1243 /* might use file_maint_ functions for now, later it should be changed to a system of callbacks | |
1244 FIXME do we need the ignore_list? It looks like a workaround for ineffective | |
1245 implementation in view_file_list.c */ | |
1246 | |
1247 void file_data_sc_send_notification(FileData *fd) | |
1248 { | |
1249 } | |
1250 | |
1251 |