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