|
Blender
V2.59
|
00001 /* 00002 * $Id: filelist.c 37552 2011-06-16 15:01:22Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2007 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 /* global includes */ 00036 00037 #include <stdlib.h> 00038 #include <math.h> 00039 #include <string.h> 00040 00041 #ifndef WIN32 00042 #include <unistd.h> 00043 #else 00044 #include <io.h> 00045 #include <direct.h> 00046 #endif 00047 #include "MEM_guardedalloc.h" 00048 00049 #include "BLI_blenlib.h" 00050 #include "BLI_linklist.h" 00051 #include "BLI_storage_types.h" 00052 #include "BLI_threads.h" 00053 #include "BLI_utildefines.h" 00054 00055 #ifdef WIN32 00056 #include "BLI_winstuff.h" 00057 #endif 00058 00059 #include "BKE_context.h" 00060 #include "BKE_global.h" 00061 #include "BKE_library.h" 00062 #include "BKE_icons.h" 00063 #include "BKE_main.h" 00064 #include "BKE_report.h" 00065 #include "BLO_readfile.h" 00066 #include "BKE_idcode.h" 00067 00068 #include "DNA_space_types.h" 00069 00070 #include "ED_fileselect.h" 00071 #include "ED_datafiles.h" 00072 00073 #include "IMB_imbuf.h" 00074 #include "IMB_imbuf_types.h" 00075 #include "IMB_thumbs.h" 00076 00077 #include "PIL_time.h" 00078 00079 #include "WM_api.h" 00080 #include "WM_types.h" 00081 00082 #include "UI_resources.h" 00083 00084 #include "filelist.h" 00085 00086 /* max length of library group name within filesel */ 00087 #define GROUP_MAX 32 00088 00089 struct FileList; 00090 00091 typedef struct FileImage { 00092 struct FileImage *next, *prev; 00093 char path[FILE_MAX]; 00094 unsigned int flags; 00095 int index; 00096 short done; 00097 ImBuf *img; 00098 } FileImage; 00099 00100 typedef struct ThumbnailJob { 00101 ListBase loadimages; 00102 short *stop; 00103 short *do_update; 00104 struct FileList* filelist; 00105 ReportList reports; 00106 } ThumbnailJob; 00107 00108 typedef struct FileList 00109 { 00110 struct direntry *filelist; 00111 int *fidx; 00112 int numfiles; 00113 int numfiltered; 00114 char dir[FILE_MAX]; 00115 short prv_w; 00116 short prv_h; 00117 short hide_dot; 00118 unsigned int filter; 00119 char filter_glob[64]; 00120 short changed; 00121 00122 struct BlendHandle *libfiledata; 00123 short hide_parent; 00124 00125 void (*readf)(struct FileList *); 00126 int (*filterf)(struct direntry* file, const char* dir, unsigned int filter, short hide_dot); 00127 00128 } FileList; 00129 00130 typedef struct FolderList 00131 { 00132 struct FolderList *next, *prev; 00133 char *foldername; 00134 } FolderList; 00135 00136 #define SPECIAL_IMG_SIZE 48 00137 #define SPECIAL_IMG_ROWS 4 00138 #define SPECIAL_IMG_COLS 4 00139 00140 #define SPECIAL_IMG_FOLDER 0 00141 #define SPECIAL_IMG_PARENT 1 00142 #define SPECIAL_IMG_REFRESH 2 00143 #define SPECIAL_IMG_BLENDFILE 3 00144 #define SPECIAL_IMG_SOUNDFILE 4 00145 #define SPECIAL_IMG_MOVIEFILE 5 00146 #define SPECIAL_IMG_PYTHONFILE 6 00147 #define SPECIAL_IMG_TEXTFILE 7 00148 #define SPECIAL_IMG_FONTFILE 8 00149 #define SPECIAL_IMG_UNKNOWNFILE 9 00150 #define SPECIAL_IMG_LOADING 10 00151 #define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1 00152 00153 static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX]; 00154 00155 00156 /* ******************* SORT ******************* */ 00157 00158 static int compare_name(const void *a1, const void *a2) 00159 { 00160 const struct direntry *entry1=a1, *entry2=a2; 00161 00162 /* type is equal to stat.st_mode */ 00163 00164 if (S_ISDIR(entry1->type)){ 00165 if (S_ISDIR(entry2->type)==0) return (-1); 00166 } else{ 00167 if (S_ISDIR(entry2->type)) return (1); 00168 } 00169 if (S_ISREG(entry1->type)){ 00170 if (S_ISREG(entry2->type)==0) return (-1); 00171 } else{ 00172 if (S_ISREG(entry2->type)) return (1); 00173 } 00174 if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); 00175 if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); 00176 00177 /* make sure "." and ".." are always first */ 00178 if( strcmp(entry1->relname, ".")==0 ) return (-1); 00179 if( strcmp(entry2->relname, ".")==0 ) return (1); 00180 if( strcmp(entry1->relname, "..")==0 ) return (-1); 00181 if( strcmp(entry2->relname, "..")==0 ) return (1); 00182 00183 return (BLI_natstrcmp(entry1->relname,entry2->relname)); 00184 } 00185 00186 static int compare_date(const void *a1, const void *a2) 00187 { 00188 const struct direntry *entry1=a1, *entry2=a2; 00189 00190 /* type is equal to stat.st_mode */ 00191 00192 if (S_ISDIR(entry1->type)){ 00193 if (S_ISDIR(entry2->type)==0) return (-1); 00194 } else{ 00195 if (S_ISDIR(entry2->type)) return (1); 00196 } 00197 if (S_ISREG(entry1->type)){ 00198 if (S_ISREG(entry2->type)==0) return (-1); 00199 } else{ 00200 if (S_ISREG(entry2->type)) return (1); 00201 } 00202 if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); 00203 if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); 00204 00205 /* make sure "." and ".." are always first */ 00206 if( strcmp(entry1->relname, ".")==0 ) return (-1); 00207 if( strcmp(entry2->relname, ".")==0 ) return (1); 00208 if( strcmp(entry1->relname, "..")==0 ) return (-1); 00209 if( strcmp(entry2->relname, "..")==0 ) return (1); 00210 00211 if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1; 00212 if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1; 00213 00214 else return BLI_natstrcmp(entry1->relname,entry2->relname); 00215 } 00216 00217 static int compare_size(const void *a1, const void *a2) 00218 { 00219 const struct direntry *entry1=a1, *entry2=a2; 00220 00221 /* type is equal to stat.st_mode */ 00222 00223 if (S_ISDIR(entry1->type)){ 00224 if (S_ISDIR(entry2->type)==0) return (-1); 00225 } else{ 00226 if (S_ISDIR(entry2->type)) return (1); 00227 } 00228 if (S_ISREG(entry1->type)){ 00229 if (S_ISREG(entry2->type)==0) return (-1); 00230 } else{ 00231 if (S_ISREG(entry2->type)) return (1); 00232 } 00233 if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); 00234 if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); 00235 00236 /* make sure "." and ".." are always first */ 00237 if( strcmp(entry1->relname, ".")==0 ) return (-1); 00238 if( strcmp(entry2->relname, ".")==0 ) return (1); 00239 if( strcmp(entry1->relname, "..")==0 ) return (-1); 00240 if( strcmp(entry2->relname, "..")==0 ) return (1); 00241 00242 if ( entry1->s.st_size < entry2->s.st_size) return 1; 00243 if ( entry1->s.st_size > entry2->s.st_size) return -1; 00244 else return BLI_natstrcmp(entry1->relname,entry2->relname); 00245 } 00246 00247 static int compare_extension(const void *a1, const void *a2) { 00248 const struct direntry *entry1=a1, *entry2=a2; 00249 const char *sufix1, *sufix2; 00250 const char *nil=""; 00251 00252 if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 00253 sufix1= strrchr (entry1->relname, '.'); 00254 if (!(sufix2= strstr (entry2->relname, ".blend.gz"))) 00255 sufix2= strrchr (entry2->relname, '.'); 00256 if (!sufix1) sufix1= nil; 00257 if (!sufix2) sufix2= nil; 00258 00259 /* type is equal to stat.st_mode */ 00260 00261 if (S_ISDIR(entry1->type)){ 00262 if (S_ISDIR(entry2->type)==0) return (-1); 00263 } else{ 00264 if (S_ISDIR(entry2->type)) return (1); 00265 } 00266 if (S_ISREG(entry1->type)){ 00267 if (S_ISREG(entry2->type)==0) return (-1); 00268 } else{ 00269 if (S_ISREG(entry2->type)) return (1); 00270 } 00271 if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); 00272 if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); 00273 00274 /* make sure "." and ".." are always first */ 00275 if( strcmp(entry1->relname, ".")==0 ) return (-1); 00276 if( strcmp(entry2->relname, ".")==0 ) return (1); 00277 if( strcmp(entry1->relname, "..")==0 ) return (-1); 00278 if( strcmp(entry2->relname, "..")==0 ) return (1); 00279 00280 return (BLI_strcasecmp(sufix1, sufix2)); 00281 } 00282 00283 static int is_hidden_file(const char* filename, short hide_dot) 00284 { 00285 int is_hidden=0; 00286 00287 if (hide_dot) { 00288 if(filename[0]=='.' && filename[1]!='.' && filename[1]!=0) { 00289 is_hidden=1; /* ignore .file */ 00290 } else if (((filename[0] == '.') && (filename[1] == 0) )) { 00291 is_hidden=1; /* ignore . */ 00292 } else { 00293 int len=strlen(filename); 00294 if( (len>0) && (filename[len-1]=='~') ) { 00295 is_hidden=1; /* ignore file~ */ 00296 } 00297 } 00298 } else { 00299 if (((filename[0] == '.') && (filename[1] == 0) )) { 00300 is_hidden=1; /* ignore . */ 00301 } 00302 } 00303 return is_hidden; 00304 } 00305 00306 static int is_filtered_file(struct direntry* file, const char* UNUSED(dir), unsigned int filter, short hide_dot) 00307 { 00308 int is_filtered=0; 00309 if (filter) { 00310 if (file->flags & filter) { 00311 is_filtered=1; 00312 } else if (file->type & S_IFDIR) { 00313 if (filter & FOLDERFILE) { 00314 is_filtered = 1; 00315 } 00316 } 00317 } else { 00318 is_filtered = 1; 00319 } 00320 return is_filtered && !is_hidden_file(file->relname, hide_dot); 00321 } 00322 00323 static int is_filtered_lib(struct direntry* file, const char* dir, unsigned int filter, short hide_dot) 00324 { 00325 int is_filtered=0; 00326 char tdir[FILE_MAX], tgroup[GROUP_MAX]; 00327 if (BLO_is_a_library(dir, tdir, tgroup)) { 00328 is_filtered = !is_hidden_file(file->relname, hide_dot); 00329 } else { 00330 is_filtered = is_filtered_file(file, dir, filter, hide_dot); 00331 } 00332 return is_filtered; 00333 } 00334 00335 static int is_filtered_main(struct direntry* file, const char* UNUSED(dir), unsigned int UNUSED(filter), short hide_dot) 00336 { 00337 return !is_hidden_file(file->relname, hide_dot); 00338 } 00339 00340 void filelist_filter(FileList* filelist) 00341 { 00342 int num_filtered = 0; 00343 int i, j; 00344 00345 if (!filelist->filelist) 00346 return; 00347 00348 // How many files are left after filter ? 00349 for (i = 0; i < filelist->numfiles; ++i) { 00350 struct direntry *file = &filelist->filelist[i]; 00351 if ( filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot) ) { 00352 num_filtered++; 00353 } 00354 } 00355 00356 if (filelist->fidx) { 00357 MEM_freeN(filelist->fidx); 00358 filelist->fidx = NULL; 00359 } 00360 filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx"); 00361 filelist->numfiltered = num_filtered; 00362 00363 for (i = 0, j=0; i < filelist->numfiles; ++i) { 00364 struct direntry *file = &filelist->filelist[i]; 00365 if ( filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot) ) { 00366 filelist->fidx[j++] = i; 00367 } 00368 } 00369 } 00370 00371 void filelist_init_icons(void) 00372 { 00373 short x, y, k; 00374 ImBuf *bbuf; 00375 ImBuf *ibuf; 00376 #ifdef WITH_HEADLESS 00377 bbuf = NULL; 00378 #else 00379 bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_prvicons, datatoc_prvicons_size, IB_rect); 00380 #endif 00381 if (bbuf) { 00382 for (y=0; y<SPECIAL_IMG_ROWS; y++) { 00383 for (x=0; x<SPECIAL_IMG_COLS; x++) { 00384 int tile = SPECIAL_IMG_COLS*y + x; 00385 if (tile < SPECIAL_IMG_MAX) { 00386 ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect); 00387 for (k=0; k<SPECIAL_IMG_SIZE; k++) { 00388 memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int)); 00389 } 00390 gSpecialFileImages[tile] = ibuf; 00391 } 00392 } 00393 } 00394 IMB_freeImBuf(bbuf); 00395 } 00396 } 00397 00398 void filelist_free_icons(void) 00399 { 00400 int i; 00401 for (i=0; i < SPECIAL_IMG_MAX; ++i) { 00402 IMB_freeImBuf(gSpecialFileImages[i]); 00403 gSpecialFileImages[i] = NULL; 00404 } 00405 } 00406 00407 //-----------------FOLDERLIST (previous/next) --------------// 00408 struct ListBase* folderlist_new(void) 00409 { 00410 ListBase* p = MEM_callocN( sizeof(ListBase), "folderlist" ); 00411 return p; 00412 } 00413 00414 void folderlist_popdir(struct ListBase* folderlist, char *dir) 00415 { 00416 const char *prev_dir; 00417 struct FolderList *folder; 00418 folder = folderlist->last; 00419 00420 if(folder){ 00421 // remove the current directory 00422 MEM_freeN(folder->foldername); 00423 BLI_freelinkN(folderlist, folder); 00424 00425 folder = folderlist->last; 00426 if(folder){ 00427 prev_dir = folder->foldername; 00428 BLI_strncpy(dir, prev_dir, FILE_MAXDIR); 00429 } 00430 } 00431 // delete the folder next or use setdir directly before PREVIOUS OP 00432 } 00433 00434 void folderlist_pushdir(ListBase* folderlist, const char *dir) 00435 { 00436 struct FolderList *folder, *previous_folder; 00437 previous_folder = folderlist->last; 00438 00439 // check if already exists 00440 if(previous_folder && previous_folder->foldername){ 00441 if(BLI_path_cmp(previous_folder->foldername, dir)==0){ 00442 return; 00443 } 00444 } 00445 00446 // create next folder element 00447 folder = (FolderList*)MEM_mallocN(sizeof(FolderList),"FolderList"); 00448 folder->foldername = (char*)MEM_mallocN(sizeof(char)*(strlen(dir)+1), "foldername"); 00449 folder->foldername[0] = '\0'; 00450 00451 BLI_strncpy(folder->foldername, dir, FILE_MAXDIR); 00452 00453 // add it to the end of the list 00454 BLI_addtail(folderlist, folder); 00455 } 00456 00457 int folderlist_clear_next(struct SpaceFile *sfile) 00458 { 00459 struct FolderList *folder; 00460 00461 // if there is no folder_next there is nothing we can clear 00462 if (!sfile->folders_next) 00463 return 0; 00464 00465 // if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next 00466 folder = sfile->folders_prev->last; 00467 if ((!folder) ||(BLI_path_cmp(folder->foldername, sfile->params->dir) == 0)) 00468 return 0; 00469 00470 // eventually clear flist->folders_next 00471 return 1; 00472 } 00473 00474 /* not listbase itself */ 00475 void folderlist_free(ListBase* folderlist) 00476 { 00477 if (folderlist){ 00478 FolderList *folder; 00479 for(folder= folderlist->first; folder; folder= folder->next) 00480 MEM_freeN(folder->foldername); 00481 BLI_freelistN(folderlist); 00482 } 00483 } 00484 00485 ListBase *folderlist_duplicate(ListBase* folderlist) 00486 { 00487 00488 if (folderlist) { 00489 ListBase *folderlistn= MEM_callocN(sizeof(ListBase), "copy folderlist"); 00490 FolderList *folder; 00491 00492 BLI_duplicatelist(folderlistn, folderlist); 00493 00494 for(folder= folderlistn->first; folder; folder= folder->next) { 00495 folder->foldername= MEM_dupallocN(folder->foldername); 00496 } 00497 return folderlistn; 00498 } 00499 return NULL; 00500 } 00501 00502 00503 static void filelist_read_main(struct FileList* filelist); 00504 static void filelist_read_library(struct FileList* filelist); 00505 static void filelist_read_dir(struct FileList* filelist); 00506 00507 //------------------FILELIST------------------------// 00508 struct FileList* filelist_new(short type) 00509 { 00510 FileList* p = MEM_callocN( sizeof(FileList), "filelist" ); 00511 switch(type) { 00512 case FILE_MAIN: 00513 p->readf = filelist_read_main; 00514 p->filterf = is_filtered_main; 00515 break; 00516 case FILE_LOADLIB: 00517 p->readf = filelist_read_library; 00518 p->filterf = is_filtered_lib; 00519 break; 00520 default: 00521 p->readf = filelist_read_dir; 00522 p->filterf = is_filtered_file; 00523 00524 } 00525 return p; 00526 } 00527 00528 00529 void filelist_free(struct FileList* filelist) 00530 { 00531 int i; 00532 00533 if (!filelist) { 00534 printf("Attempting to delete empty filelist.\n"); 00535 return; 00536 } 00537 00538 if (filelist->fidx) { 00539 MEM_freeN(filelist->fidx); 00540 filelist->fidx = NULL; 00541 } 00542 00543 for (i = 0; i < filelist->numfiles; ++i) { 00544 if (filelist->filelist[i].image) { 00545 IMB_freeImBuf(filelist->filelist[i].image); 00546 } 00547 filelist->filelist[i].image = NULL; 00548 if (filelist->filelist[i].relname) 00549 MEM_freeN(filelist->filelist[i].relname); 00550 if (filelist->filelist[i].path) 00551 MEM_freeN(filelist->filelist[i].path); 00552 filelist->filelist[i].relname = NULL; 00553 if (filelist->filelist[i].string) 00554 MEM_freeN(filelist->filelist[i].string); 00555 filelist->filelist[i].string = NULL; 00556 } 00557 00558 filelist->numfiles = 0; 00559 free(filelist->filelist); 00560 filelist->filelist = NULL; 00561 filelist->filter = 0; 00562 filelist->filter_glob[0] = '\0'; 00563 filelist->numfiltered =0; 00564 filelist->hide_dot =0; 00565 } 00566 00567 void filelist_freelib(struct FileList* filelist) 00568 { 00569 if(filelist->libfiledata) 00570 BLO_blendhandle_close(filelist->libfiledata); 00571 filelist->libfiledata= NULL; 00572 } 00573 00574 struct BlendHandle *filelist_lib(struct FileList* filelist) 00575 { 00576 return filelist->libfiledata; 00577 } 00578 00579 int filelist_numfiles(struct FileList* filelist) 00580 { 00581 return filelist->numfiltered; 00582 } 00583 00584 const char * filelist_dir(struct FileList* filelist) 00585 { 00586 return filelist->dir; 00587 } 00588 00589 void filelist_setdir(struct FileList* filelist, const char *dir) 00590 { 00591 BLI_strncpy(filelist->dir, dir, FILE_MAX); 00592 } 00593 00594 void filelist_imgsize(struct FileList* filelist, short w, short h) 00595 { 00596 filelist->prv_w = w; 00597 filelist->prv_h = h; 00598 } 00599 00600 short filelist_changed(struct FileList* filelist) 00601 { 00602 return filelist->changed; 00603 } 00604 00605 static struct ImBuf * filelist_loadimage(struct FileList* filelist, int index) 00606 { 00607 ImBuf *imb = NULL; 00608 int fidx = 0; 00609 00610 if ( (index < 0) || (index >= filelist->numfiltered) ) { 00611 return NULL; 00612 } 00613 fidx = filelist->fidx[index]; 00614 imb = filelist->filelist[fidx].image; 00615 if (!imb) 00616 { 00617 if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) { 00618 imb = IMB_thumb_read(filelist->filelist[fidx].path, THB_NORMAL); 00619 } 00620 if (imb) { 00621 filelist->filelist[fidx].image = imb; 00622 } 00623 } 00624 return imb; 00625 } 00626 00627 struct ImBuf * filelist_getimage(struct FileList* filelist, int index) 00628 { 00629 ImBuf* ibuf = NULL; 00630 int fidx = 0; 00631 if ( (index < 0) || (index >= filelist->numfiltered) ) { 00632 return NULL; 00633 } 00634 fidx = filelist->fidx[index]; 00635 ibuf = filelist->filelist[fidx].image; 00636 00637 return ibuf; 00638 } 00639 00640 struct ImBuf * filelist_geticon(struct FileList* filelist, int index) 00641 { 00642 ImBuf* ibuf= NULL; 00643 struct direntry *file= NULL; 00644 int fidx = 0; 00645 if ( (index < 0) || (index >= filelist->numfiltered) ) { 00646 return NULL; 00647 } 00648 fidx = filelist->fidx[index]; 00649 file = &filelist->filelist[fidx]; 00650 if (file->type & S_IFDIR) { 00651 if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) { 00652 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; 00653 } else if ( strcmp(filelist->filelist[fidx].relname, ".") == 0) { 00654 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH]; 00655 } else { 00656 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER]; 00657 } 00658 } else { 00659 ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE]; 00660 } 00661 00662 if (file->flags & BLENDERFILE) { 00663 ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE]; 00664 } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) { 00665 ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE]; 00666 } else if (file->flags & SOUNDFILE) { 00667 ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE]; 00668 } else if (file->flags & PYSCRIPTFILE) { 00669 ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE]; 00670 } else if (file->flags & FTFONTFILE) { 00671 ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE]; 00672 } else if (file->flags & TEXTFILE) { 00673 ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE]; 00674 } else if (file->flags & IMAGEFILE) { 00675 ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; 00676 } 00677 00678 return ibuf; 00679 } 00680 00681 struct direntry * filelist_file(struct FileList* filelist, int index) 00682 { 00683 int fidx = 0; 00684 00685 if ( (index < 0) || (index >= filelist->numfiltered) ) { 00686 return NULL; 00687 } 00688 fidx = filelist->fidx[index]; 00689 00690 return &filelist->filelist[fidx]; 00691 } 00692 00693 int filelist_find(struct FileList* filelist, char *file) 00694 { 00695 int index = -1; 00696 int i; 00697 int fidx = -1; 00698 00699 if (!filelist->fidx) 00700 return fidx; 00701 00702 00703 for (i = 0; i < filelist->numfiles; ++i) { 00704 if ( strcmp(filelist->filelist[i].relname, file) == 0) { /* not dealing with user input so dont need BLI_path_cmp */ 00705 index = i; 00706 break; 00707 } 00708 } 00709 00710 for (i = 0; i < filelist->numfiltered; ++i) { 00711 if (filelist->fidx[i] == index) { 00712 fidx = i; 00713 break; 00714 } 00715 } 00716 return fidx; 00717 } 00718 00719 void filelist_hidedot(struct FileList* filelist, short hide) 00720 { 00721 filelist->hide_dot = hide; 00722 } 00723 00724 void filelist_setfilter(struct FileList* filelist, unsigned int filter) 00725 { 00726 filelist->filter = filter; 00727 } 00728 00729 void filelist_setfilter_types(struct FileList* filelist, const char *filter_glob) 00730 { 00731 BLI_strncpy(filelist->filter_glob, filter_glob, sizeof(filelist->filter_glob)); 00732 } 00733 00734 static int file_is_blend_backup(const char *str) 00735 { 00736 short a, b; 00737 int retval= 0; 00738 00739 a= strlen(str); 00740 b= 7; 00741 00742 if(a==0 || b>=a); 00743 else { 00744 char *loc; 00745 00746 if(a > b+1) 00747 b++; 00748 00749 /* allow .blend1 .blend2 .blend32 */ 00750 loc= BLI_strcasestr(str+a-b, ".blend"); 00751 00752 if(loc) 00753 retval= 1; 00754 } 00755 00756 return (retval); 00757 } 00758 00759 00760 static int file_extension_type(char *relname) 00761 { 00762 if(BLO_has_bfile_extension(relname)) { 00763 return BLENDERFILE; 00764 } else if(file_is_blend_backup(relname)) { 00765 return BLENDERFILE_BACKUP; 00766 } else if(BLI_testextensie(relname, ".py")) { 00767 return PYSCRIPTFILE; 00768 } else if(BLI_testextensie(relname, ".txt") 00769 || BLI_testextensie(relname, ".glsl") 00770 || BLI_testextensie(relname, ".data")) { 00771 return TEXTFILE; 00772 } else if( BLI_testextensie(relname, ".ttf") 00773 || BLI_testextensie(relname, ".ttc") 00774 || BLI_testextensie(relname, ".pfb") 00775 || BLI_testextensie(relname, ".otf") 00776 || BLI_testextensie(relname, ".otc")) { 00777 return FTFONTFILE; 00778 } else if(BLI_testextensie(relname, ".btx")) { 00779 return BTXFILE; 00780 } else if(BLI_testextensie(relname, ".dae")) { 00781 return COLLADAFILE; 00782 } else if(BLI_testextensie_array(relname, imb_ext_image) 00783 || (G.have_quicktime && BLI_testextensie_array(relname, imb_ext_image_qt))) { 00784 return IMAGEFILE; 00785 } else if(BLI_testextensie_array(relname, imb_ext_movie)) { 00786 return MOVIEFILE; 00787 } else if(BLI_testextensie_array(relname, imb_ext_audio)) { 00788 return SOUNDFILE; 00789 } 00790 return 0; 00791 } 00792 00793 int ED_file_extension_icon(char *relname) 00794 { 00795 int type= file_extension_type(relname); 00796 00797 if (type == BLENDERFILE || type==BLENDERFILE_BACKUP) 00798 return ICON_FILE_BLEND; 00799 else if (type == IMAGEFILE) 00800 return ICON_FILE_IMAGE; 00801 else if (type == MOVIEFILE) 00802 return ICON_FILE_MOVIE; 00803 else if (type == PYSCRIPTFILE) 00804 return ICON_FILE_SCRIPT; 00805 else if (type == SOUNDFILE) 00806 return ICON_FILE_SOUND; 00807 else if (type == FTFONTFILE) 00808 return ICON_FILE_FONT; 00809 else if (type == BTXFILE) 00810 return ICON_FILE_BLANK; 00811 else if (type == COLLADAFILE) 00812 return ICON_FILE_BLANK; 00813 00814 return ICON_FILE_BLANK; 00815 } 00816 00817 static void filelist_setfiletypes(struct FileList* filelist) 00818 { 00819 struct direntry *file; 00820 int num; 00821 00822 file= filelist->filelist; 00823 00824 for(num=0; num<filelist->numfiles; num++, file++) { 00825 file->type= file->s.st_mode; /* restore the mess below */ 00826 00827 /* Don't check extensions for directories */ 00828 if (file->type & S_IFDIR) { 00829 continue; 00830 } 00831 file->flags = file_extension_type(file->relname); 00832 00833 if(filelist->filter_glob 00834 && BLI_testextensie_glob(file->relname, filelist->filter_glob)) { 00835 file->flags= OPERATORFILE; 00836 } 00837 00838 } 00839 } 00840 00841 static void filelist_read_dir(struct FileList* filelist) 00842 { 00843 char wdir[FILE_MAX]= ""; 00844 if (!filelist) return; 00845 00846 filelist->fidx = NULL; 00847 filelist->filelist = NULL; 00848 00849 BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */ 00850 00851 BLI_cleanup_dir(G.main->name, filelist->dir); 00852 filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist)); 00853 00854 if(!chdir(wdir)) {} /* fix warning about not checking return value */ 00855 filelist_setfiletypes(filelist); 00856 filelist_filter(filelist); 00857 } 00858 00859 static void filelist_read_main(struct FileList* filelist) 00860 { 00861 if (!filelist) return; 00862 filelist_from_main(filelist); 00863 } 00864 00865 static void filelist_read_library(struct FileList* filelist) 00866 { 00867 if (!filelist) return; 00868 BLI_cleanup_dir(G.main->name, filelist->dir); 00869 filelist_from_library(filelist); 00870 if(!filelist->libfiledata) { 00871 int num; 00872 struct direntry *file; 00873 00874 BLI_make_exist(filelist->dir); 00875 filelist_read_dir(filelist); 00876 file = filelist->filelist; 00877 for(num=0; num<filelist->numfiles; num++, file++) { 00878 if(BLO_has_bfile_extension(file->relname)) { 00879 char name[FILE_MAXDIR+FILE_MAXFILE]; 00880 00881 BLI_strncpy(name, filelist->dir, sizeof(name)); 00882 strcat(name, file->relname); 00883 00884 /* prevent current file being used as acceptable dir */ 00885 if (BLI_path_cmp(G.main->name, name) != 0) { 00886 file->type &= ~S_IFMT; 00887 file->type |= S_IFDIR; 00888 } 00889 } 00890 } 00891 } 00892 } 00893 00894 void filelist_readdir(struct FileList* filelist) 00895 { 00896 filelist->readf(filelist); 00897 } 00898 00899 int filelist_empty(struct FileList* filelist) 00900 { 00901 return filelist->filelist == NULL; 00902 } 00903 00904 void filelist_parent(struct FileList* filelist) 00905 { 00906 BLI_parent_dir(filelist->dir); 00907 BLI_make_exist(filelist->dir); 00908 filelist_readdir(filelist); 00909 } 00910 00911 void filelist_select_file(struct FileList* filelist, int index, FileSelType select, unsigned int flag, FileCheckType check) 00912 { 00913 struct direntry* file = filelist_file(filelist, index); 00914 if (file != NULL) { 00915 int check_ok = 0; 00916 switch (check) { 00917 case CHECK_DIRS: 00918 check_ok = S_ISDIR(file->type); 00919 break; 00920 case CHECK_ALL: 00921 check_ok = 1; 00922 break; 00923 case CHECK_FILES: 00924 default: 00925 check_ok = !S_ISDIR(file->type); 00926 break; 00927 } 00928 if (check_ok) { 00929 switch (select) { 00930 case FILE_SEL_REMOVE: 00931 file->selflag &= ~flag; 00932 break; 00933 case FILE_SEL_ADD: 00934 file->selflag |= flag; 00935 break; 00936 case FILE_SEL_TOGGLE: 00937 file->selflag ^= flag; 00938 break; 00939 } 00940 } 00941 } 00942 } 00943 00944 void filelist_select(struct FileList* filelist, FileSelection* sel, FileSelType select, unsigned int flag, FileCheckType check) 00945 { 00946 /* select all valid files between first and last indicated */ 00947 if ( (sel->first >= 0) && (sel->first < filelist->numfiltered) && (sel->last >= 0) && (sel->last < filelist->numfiltered) ) { 00948 int current_file; 00949 for (current_file = sel->first; current_file <= sel->last; current_file++) { 00950 filelist_select_file(filelist, current_file, select, flag, check); 00951 } 00952 } 00953 } 00954 00955 int filelist_is_selected(struct FileList* filelist, int index, FileCheckType check) 00956 { 00957 struct direntry* file = filelist_file(filelist, index); 00958 if (!file) { 00959 return 0; 00960 } 00961 switch (check) { 00962 case CHECK_DIRS: 00963 return S_ISDIR(file->type) && (file->selflag & SELECTED_FILE); 00964 case CHECK_FILES: 00965 return S_ISREG(file->type) && (file->selflag & SELECTED_FILE); 00966 case CHECK_ALL: 00967 default: 00968 return (file->selflag & SELECTED_FILE); 00969 } 00970 } 00971 00972 void filelist_sort(struct FileList* filelist, short sort) 00973 { 00974 switch(sort) { 00975 case FILE_SORT_ALPHA: 00976 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name); 00977 break; 00978 case FILE_SORT_TIME: 00979 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date); 00980 break; 00981 case FILE_SORT_SIZE: 00982 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size); 00983 break; 00984 case FILE_SORT_EXTENSION: 00985 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension); 00986 } 00987 00988 filelist_filter(filelist); 00989 } 00990 00991 00992 int filelist_islibrary(struct FileList* filelist, char* dir, char* group) 00993 { 00994 return BLO_is_a_library(filelist->dir, dir, group); 00995 } 00996 00997 static int groupname_to_code(char *group) 00998 { 00999 char buf[32]; 01000 char *lslash; 01001 01002 BLI_strncpy(buf, group, sizeof(buf)); 01003 lslash= BLI_last_slash(buf); 01004 if (lslash) 01005 lslash[0]= '\0'; 01006 01007 return BKE_idcode_from_name(buf); 01008 } 01009 01010 void filelist_from_library(struct FileList* filelist) 01011 { 01012 LinkNode *l, *names, *previews; 01013 struct ImBuf* ima; 01014 int ok, i, nprevs, nnames, idcode; 01015 char filename[FILE_MAXDIR+FILE_MAXFILE]; 01016 char dir[FILE_MAX], group[GROUP_MAX]; 01017 01018 /* name test */ 01019 ok= filelist_islibrary(filelist, dir, group); 01020 if (!ok) { 01021 /* free */ 01022 if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata); 01023 filelist->libfiledata= NULL; 01024 return; 01025 } 01026 01027 BLI_strncpy(filename, G.main->name, sizeof(filename)); 01028 01029 /* there we go */ 01030 /* for the time being only read filedata when libfiledata==0 */ 01031 if (filelist->libfiledata == NULL) { 01032 filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); 01033 if(filelist->libfiledata == NULL) return; 01034 } 01035 01036 idcode= groupname_to_code(group); 01037 01038 /* memory for strings is passed into filelist[i].relname 01039 * and free'd in freefilelist */ 01040 if (idcode) { 01041 previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode, &nprevs); 01042 names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode, &nnames); 01043 /* ugh, no rewind, need to reopen */ 01044 BLO_blendhandle_close(filelist->libfiledata); 01045 filelist->libfiledata= BLO_blendhandle_from_file(dir, NULL); 01046 01047 } else { 01048 previews= NULL; 01049 nprevs= 0; 01050 names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata); 01051 nnames= BLI_linklist_length(names); 01052 } 01053 01054 filelist->numfiles= nnames + 1; 01055 filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist)); 01056 memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist)); 01057 01058 filelist->filelist[0].relname= BLI_strdup(".."); 01059 filelist->filelist[0].type |= S_IFDIR; 01060 01061 for (i=0, l= names; i<nnames; i++, l= l->next) { 01062 char *blockname= l->link; 01063 01064 filelist->filelist[i + 1].relname= BLI_strdup(blockname); 01065 if (idcode) { 01066 filelist->filelist[i + 1].type |= S_IFREG; 01067 } else { 01068 filelist->filelist[i + 1].type |= S_IFDIR; 01069 } 01070 } 01071 01072 if(previews && (nnames != nprevs)) { 01073 printf("filelist_from_library: error, found %d items, %d previews\n", nnames, nprevs); 01074 } 01075 else if(previews) { 01076 for (i=0, l= previews; i<nnames; i++, l= l->next) { 01077 PreviewImage *img= l->link; 01078 01079 if (img) { 01080 unsigned int w = img->w[ICON_SIZE_PREVIEW]; 01081 unsigned int h = img->h[ICON_SIZE_PREVIEW]; 01082 unsigned int *rect = img->rect[ICON_SIZE_PREVIEW]; 01083 01084 /* first allocate imbuf for copying preview into it */ 01085 if (w > 0 && h > 0 && rect) { 01086 ima = IMB_allocImBuf(w, h, 32, IB_rect); 01087 memcpy(ima->rect, rect, w*h*sizeof(unsigned int)); 01088 filelist->filelist[i + 1].image = ima; 01089 filelist->filelist[i + 1].flags = IMAGEFILE; 01090 } 01091 } 01092 } 01093 } 01094 01095 BLI_linklist_free(names, free); 01096 if (previews) BLI_linklist_free(previews, BKE_previewimg_freefunc); 01097 01098 filelist_sort(filelist, FILE_SORT_ALPHA); 01099 01100 BLI_strncpy(G.main->name, filename, sizeof(filename)); // prevent G.main->name to change 01101 01102 filelist->filter = 0; 01103 filelist_filter(filelist); 01104 } 01105 01106 void filelist_hideparent(struct FileList* filelist, short hide) 01107 { 01108 filelist->hide_parent = hide; 01109 } 01110 01111 void filelist_from_main(struct FileList *filelist) 01112 { 01113 ID *id; 01114 struct direntry *files, *firstlib = NULL; 01115 ListBase *lb; 01116 int a, fake, idcode, ok, totlib, totbl; 01117 01118 // filelist->type = FILE_MAIN; // XXXXX TODO: add modes to filebrowser 01119 01120 if(filelist->dir[0]=='/') filelist->dir[0]= 0; 01121 01122 if(filelist->dir[0]) { 01123 idcode= groupname_to_code(filelist->dir); 01124 if(idcode==0) filelist->dir[0]= 0; 01125 } 01126 01127 if( filelist->dir[0]==0) { 01128 01129 /* make directories */ 01130 filelist->numfiles= 23; 01131 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); 01132 01133 for(a=0; a<filelist->numfiles; a++) { 01134 memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry)); 01135 filelist->filelist[a].type |= S_IFDIR; 01136 } 01137 01138 filelist->filelist[0].relname= BLI_strdup(".."); 01139 filelist->filelist[2].relname= BLI_strdup("Scene"); 01140 filelist->filelist[3].relname= BLI_strdup("Object"); 01141 filelist->filelist[4].relname= BLI_strdup("Mesh"); 01142 filelist->filelist[5].relname= BLI_strdup("Curve"); 01143 filelist->filelist[6].relname= BLI_strdup("Metaball"); 01144 filelist->filelist[7].relname= BLI_strdup("Material"); 01145 filelist->filelist[8].relname= BLI_strdup("Texture"); 01146 filelist->filelist[9].relname= BLI_strdup("Image"); 01147 filelist->filelist[10].relname= BLI_strdup("Ika"); 01148 filelist->filelist[11].relname= BLI_strdup("Wave"); 01149 filelist->filelist[12].relname= BLI_strdup("Lattice"); 01150 filelist->filelist[13].relname= BLI_strdup("Lamp"); 01151 filelist->filelist[14].relname= BLI_strdup("Camera"); 01152 filelist->filelist[15].relname= BLI_strdup("Ipo"); 01153 filelist->filelist[16].relname= BLI_strdup("World"); 01154 filelist->filelist[17].relname= BLI_strdup("Screen"); 01155 filelist->filelist[18].relname= BLI_strdup("VFont"); 01156 filelist->filelist[19].relname= BLI_strdup("Text"); 01157 filelist->filelist[20].relname= BLI_strdup("Armature"); 01158 filelist->filelist[21].relname= BLI_strdup("Action"); 01159 filelist->filelist[22].relname= BLI_strdup("NodeTree"); 01160 filelist_sort(filelist, FILE_SORT_ALPHA); 01161 } 01162 else { 01163 01164 /* make files */ 01165 idcode= groupname_to_code(filelist->dir); 01166 01167 lb= which_libbase(G.main, idcode ); 01168 if(lb == NULL) return; 01169 01170 id= lb->first; 01171 filelist->numfiles= 0; 01172 while(id) { 01173 if (!filelist->hide_dot || id->name[2] != '.') { 01174 filelist->numfiles++; 01175 } 01176 01177 id= id->next; 01178 } 01179 01180 /* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */ 01181 if (!filelist->hide_parent) filelist->numfiles+= 1; 01182 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry)); 01183 01184 files = filelist->filelist; 01185 01186 if (!filelist->hide_parent) { 01187 memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry)); 01188 filelist->filelist[0].relname= BLI_strdup(".."); 01189 filelist->filelist[0].type |= S_IFDIR; 01190 01191 files++; 01192 } 01193 01194 id= lb->first; 01195 totlib= totbl= 0; 01196 01197 while(id) { 01198 ok = 1; 01199 if(ok) { 01200 if (!filelist->hide_dot || id->name[2] != '.') { 01201 memset( files, 0 , sizeof(struct direntry)); 01202 if(id->lib==NULL) 01203 files->relname= BLI_strdup(id->name+2); 01204 else { 01205 files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib"); 01206 sprintf(files->relname, "%s | %s", id->lib->name, id->name+2); 01207 } 01208 files->type |= S_IFREG; 01209 #if 0 // XXXXX TODO show the selection status of the objects 01210 if(!filelist->has_func) { /* F4 DATA BROWSE */ 01211 if(idcode==ID_OB) { 01212 if( ((Object *)id)->flag & SELECT) files->selflag |= SELECTED_FILE; 01213 } 01214 else if(idcode==ID_SCE) { 01215 if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= SELECTED_FILE; 01216 } 01217 } 01218 #endif 01219 files->nr= totbl+1; 01220 files->poin= id; 01221 fake= id->flag & LIB_FAKEUSER; 01222 if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) { 01223 files->flags |= IMAGEFILE; 01224 } 01225 if(id->lib && fake) sprintf(files->extra, "LF %d", id->us); 01226 else if(id->lib) sprintf(files->extra, "L %d", id->us); 01227 else if(fake) sprintf(files->extra, "F %d", id->us); 01228 else sprintf(files->extra, " %d", id->us); 01229 01230 if(id->lib) { 01231 if(totlib==0) firstlib= files; 01232 totlib++; 01233 } 01234 01235 files++; 01236 } 01237 totbl++; 01238 } 01239 01240 id= id->next; 01241 } 01242 01243 /* only qsort of library blocks */ 01244 if(totlib>1) { 01245 qsort(firstlib, totlib, sizeof(struct direntry), compare_name); 01246 } 01247 } 01248 filelist->filter = 0; 01249 filelist_filter(filelist); 01250 } 01251 01252 static void thumbnail_joblist_free(ThumbnailJob *tj) 01253 { 01254 FileImage* limg = tj->loadimages.first; 01255 01256 /* free the images not yet copied to the filelist -> these will get freed with the filelist */ 01257 for( ; limg; limg= limg->next) { 01258 if ((limg->img) && (!limg->done)) { 01259 IMB_freeImBuf(limg->img); 01260 } 01261 } 01262 BLI_freelistN(&tj->loadimages); 01263 } 01264 01265 static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float *UNUSED(progress)) 01266 { 01267 ThumbnailJob *tj= tjv; 01268 FileImage* limg = tj->loadimages.first; 01269 01270 tj->stop= stop; 01271 tj->do_update= do_update; 01272 01273 while ( (*stop==0) && (limg) ) { 01274 if ( limg->flags & IMAGEFILE ) { 01275 limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE); 01276 } else if ( limg->flags & BLENDERFILE ) { 01277 limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND); 01278 } else if ( limg->flags & MOVIEFILE ) { 01279 limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_MOVIE); 01280 if (!limg->img) { 01281 /* remember that file can't be loaded via IMB_open_anim */ 01282 limg->flags &= ~MOVIEFILE; 01283 limg->flags |= MOVIEFILE_ICON; 01284 } 01285 } 01286 *do_update = 1; 01287 PIL_sleep_ms(10); 01288 limg = limg->next; 01289 } 01290 } 01291 01292 static void thumbnails_update(void *tjv) 01293 { 01294 ThumbnailJob *tj= tjv; 01295 01296 if (tj->filelist && tj->filelist->filelist) { 01297 FileImage* limg = tj->loadimages.first; 01298 while (limg) { 01299 if (!limg->done && limg->img) { 01300 tj->filelist->filelist[limg->index].image = limg->img; 01301 /* update flag for movie files where thumbnail can't be created */ 01302 if (limg->flags & MOVIEFILE_ICON) { 01303 tj->filelist->filelist[limg->index].flags &= ~MOVIEFILE; 01304 tj->filelist->filelist[limg->index].flags |= MOVIEFILE_ICON; 01305 } 01306 limg->done=1; 01307 } 01308 limg = limg->next; 01309 } 01310 } 01311 } 01312 01313 static void thumbnails_free(void *tjv) 01314 { 01315 ThumbnailJob *tj= tjv; 01316 thumbnail_joblist_free(tj); 01317 MEM_freeN(tj); 01318 } 01319 01320 01321 void thumbnails_start(struct FileList* filelist, const struct bContext* C) 01322 { 01323 wmJob *steve; 01324 ThumbnailJob *tj; 01325 int idx; 01326 01327 /* prepare job data */ 01328 tj= MEM_callocN(sizeof(ThumbnailJob), "thumbnails\n"); 01329 tj->filelist = filelist; 01330 for (idx = 0; idx < filelist->numfiles;idx++) { 01331 if (!filelist->filelist[idx].image) { 01332 if ( (filelist->filelist[idx].flags & (IMAGEFILE|MOVIEFILE|BLENDERFILE)) ) { 01333 FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage"); 01334 BLI_strncpy(limg->path, filelist->filelist[idx].path, FILE_MAX); 01335 limg->index= idx; 01336 limg->flags= filelist->filelist[idx].flags; 01337 BLI_addtail(&tj->loadimages, limg); 01338 } 01339 } 01340 } 01341 01342 BKE_reports_init(&tj->reports, RPT_PRINT); 01343 01344 /* setup job */ 01345 steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), filelist, "Thumbnails", 0); 01346 WM_jobs_customdata(steve, tj, thumbnails_free); 01347 WM_jobs_timer(steve, 0.5, NC_WINDOW, NC_WINDOW); 01348 WM_jobs_callbacks(steve, thumbnails_startjob, NULL, thumbnails_update, NULL); 01349 01350 /* start the job */ 01351 WM_jobs_start(CTX_wm_manager(C), steve); 01352 } 01353 01354 void thumbnails_stop(struct FileList* filelist, const struct bContext* C) 01355 { 01356 WM_jobs_kill(CTX_wm_manager(C), filelist, NULL); 01357 } 01358 01359 int thumbnails_running(struct FileList* filelist, const struct bContext* C) 01360 { 01361 return WM_jobs_test(CTX_wm_manager(C), filelist); 01362 }