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