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) 2008 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * 00022 * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include "BKE_context.h" 00033 #include "BKE_screen.h" 00034 #include "BKE_global.h" 00035 #include "BKE_report.h" 00036 #include "BKE_main.h" 00037 00038 #include "BLI_blenlib.h" 00039 #include "BLI_utildefines.h" 00040 #ifdef WIN32 00041 #include "BLI_winstuff.h" 00042 #endif 00043 00044 #include "ED_screen.h" 00045 #include "ED_fileselect.h" 00046 00047 #include "MEM_guardedalloc.h" 00048 00049 #include "RNA_access.h" 00050 #include "RNA_define.h" 00051 00052 #include "UI_view2d.h" 00053 00054 #include "WM_api.h" 00055 #include "WM_types.h" 00056 00057 #include "file_intern.h" 00058 #include "filelist.h" 00059 #include "fsmenu.h" 00060 00061 #include <stdlib.h> 00062 #include <string.h> 00063 #include <stdio.h> 00064 #include <ctype.h> 00065 00066 /* for events */ 00067 #define NOTACTIVEFILE 0 00068 #define ACTIVATE 1 00069 #define INACTIVATE 2 00070 00071 /* ---------- FILE SELECTION ------------ */ 00072 static FileSelection find_file_mouse_rect(SpaceFile *sfile, struct ARegion* ar, const rcti* rect) 00073 { 00074 FileSelection sel; 00075 float fxmin,fymin,fxmax, fymax; 00076 00077 View2D* v2d = &ar->v2d; 00078 rcti rect_view; 00079 00080 UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin, &fxmin, &fymin); 00081 UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax, &fxmax, &fymax); 00082 00083 BLI_init_rcti(&rect_view, (int)(v2d->tot.xmin + fxmin), (int)(v2d->tot.xmin + fxmax), (int)(v2d->tot.ymax - fymin), (int)(v2d->tot.ymax - fymax)); 00084 00085 sel = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view); 00086 00087 return sel; 00088 } 00089 00090 static void file_deselect_all(SpaceFile* sfile, unsigned int flag) 00091 { 00092 FileSelection sel; 00093 sel.first = 0; 00094 sel.last = filelist_numfiles(sfile->files)-1; 00095 00096 filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL); 00097 } 00098 00099 typedef enum FileSelect { 00100 FILE_SELECT_NOTHING = 0, 00101 FILE_SELECT_DIR = 1, 00102 FILE_SELECT_FILE = 2 00103 } FileSelect; 00104 00105 static void clamp_to_filelist(int numfiles, FileSelection* sel) 00106 { 00107 /* border select before the first file */ 00108 if ( (sel->first < 0) && (sel->last >=0 ) ) { 00109 sel->first = 0; 00110 } 00111 /* don't select if everything is outside filelist */ 00112 if ( (sel->first >= numfiles) && ((sel->last < 0) || (sel->last >= numfiles)) ) { 00113 sel->first = -1; 00114 sel->last = -1; 00115 } 00116 00117 /* fix if last file invalid */ 00118 if ( (sel->first > 0) && (sel->last < 0) ) 00119 sel->last = numfiles-1; 00120 00121 /* clamp */ 00122 if ( (sel->first >= numfiles) ) { 00123 sel->first = numfiles-1; 00124 } 00125 if ( (sel->last >= numfiles) ) { 00126 sel->last = numfiles-1; 00127 } 00128 } 00129 00130 static FileSelection file_selection_get(bContext* C, const rcti* rect, short fill) 00131 { 00132 ARegion *ar= CTX_wm_region(C); 00133 SpaceFile *sfile= CTX_wm_space_file(C); 00134 int numfiles = filelist_numfiles(sfile->files); 00135 FileSelection sel; 00136 00137 sel = find_file_mouse_rect(sfile, ar, rect); 00138 if ( !((sel.first == -1) && (sel.last == -1)) ) { 00139 clamp_to_filelist(numfiles, &sel); 00140 } 00141 00142 00143 /* if desired, fill the selection up from the last selected file to the current one */ 00144 if (fill && (sel.last >= 0) && (sel.last < numfiles) ) { 00145 int f= sel.last; 00146 while (f >= 0) { 00147 if ( filelist_is_selected(sfile->files, f, CHECK_ALL) ) 00148 break; 00149 f--; 00150 } 00151 if (f >= 0) { 00152 sel.first = f+1; 00153 } 00154 } 00155 return sel; 00156 } 00157 00158 static FileSelect file_select_do(bContext* C, int selected_idx) 00159 { 00160 FileSelect retval = FILE_SELECT_NOTHING; 00161 SpaceFile *sfile= CTX_wm_space_file(C); 00162 FileSelectParams *params = ED_fileselect_get_params(sfile); 00163 int numfiles = filelist_numfiles(sfile->files); 00164 struct direntry* file; 00165 00166 /* make the selected file active */ 00167 if ( (selected_idx >= 0) && 00168 (selected_idx < numfiles) && 00169 (file= filelist_file(sfile->files, selected_idx))) 00170 { 00171 params->active_file = selected_idx; 00172 00173 if(S_ISDIR(file->type)) { 00174 /* the path is too long and we are not going up! */ 00175 if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) { 00176 // XXX error("Path too long, cannot enter this directory"); 00177 } 00178 else { 00179 if (strcmp(file->relname, "..")==0) { 00180 /* avoids /../../ */ 00181 BLI_parent_dir(params->dir); 00182 } 00183 else { 00184 BLI_cleanup_dir(G.main->name, params->dir); 00185 strcat(params->dir, file->relname); 00186 BLI_add_slash(params->dir); 00187 } 00188 00189 file_change_dir(C, 0); 00190 retval = FILE_SELECT_DIR; 00191 } 00192 } 00193 else { 00194 if (file->relname) { 00195 BLI_strncpy(params->file, file->relname, FILE_MAXFILE); 00196 } 00197 retval = FILE_SELECT_FILE; 00198 } 00199 } 00200 return retval; 00201 } 00202 00203 00204 static FileSelect file_select(bContext* C, const rcti* rect, FileSelType select, short fill) 00205 { 00206 SpaceFile *sfile= CTX_wm_space_file(C); 00207 FileSelect retval = FILE_SELECT_NOTHING; 00208 FileSelection sel= file_selection_get(C, rect, fill); /* get the selection */ 00209 const FileCheckType check_type= (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL; 00210 00211 /* flag the files as selected in the filelist */ 00212 filelist_select(sfile->files, &sel, select, SELECTED_FILE, check_type); 00213 00214 /* Don't act on multiple selected files */ 00215 if (sel.first != sel.last) select = 0; 00216 00217 /* Do we have a valid selection and are we actually selecting */ 00218 if ( (sel.last >= 0) && ((select == FILE_SEL_ADD) || (select == FILE_SEL_TOGGLE)) ) 00219 { 00220 /* Check last selection, if selected, act on the file or dir */ 00221 if (filelist_is_selected(sfile->files, sel.last, check_type)) { 00222 retval = file_select_do(C, sel.last); 00223 } 00224 } 00225 00226 /* update operator for name change event */ 00227 file_draw_check_cb(C, NULL, NULL); 00228 00229 return retval; 00230 } 00231 00232 static int file_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) 00233 { 00234 ARegion *ar= CTX_wm_region(C); 00235 SpaceFile *sfile= CTX_wm_space_file(C); 00236 FileSelectParams *params = ED_fileselect_get_params(sfile); 00237 FileSelection sel; 00238 rcti rect; 00239 00240 int result; 00241 00242 result= WM_border_select_modal(C, op, event); 00243 00244 if(result==OPERATOR_RUNNING_MODAL) { 00245 00246 rect.xmin= RNA_int_get(op->ptr, "xmin"); 00247 rect.ymin= RNA_int_get(op->ptr, "ymin"); 00248 rect.xmax= RNA_int_get(op->ptr, "xmax"); 00249 rect.ymax= RNA_int_get(op->ptr, "ymax"); 00250 00251 BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect); 00252 00253 sel = file_selection_get(C, &rect, 0); 00254 if ( (sel.first != params->sel_first) || (sel.last != params->sel_last) ) { 00255 file_deselect_all(sfile, HILITED_FILE); 00256 filelist_select(sfile->files, &sel, FILE_SEL_ADD, HILITED_FILE, CHECK_ALL); 00257 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 00258 } 00259 params->sel_first = sel.first; params->sel_last = sel.last; 00260 00261 }else { 00262 params->active_file = -1; 00263 params->sel_first = params->sel_last = -1; 00264 file_deselect_all(sfile, HILITED_FILE); 00265 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 00266 } 00267 00268 return result; 00269 } 00270 00271 static int file_border_select_exec(bContext *C, wmOperator *op) 00272 { 00273 ARegion *ar= CTX_wm_region(C); 00274 rcti rect; 00275 FileSelect ret; 00276 int extend= RNA_boolean_get(op->ptr, "extend"); 00277 short select= (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT); 00278 00279 rect.xmin= RNA_int_get(op->ptr, "xmin"); 00280 rect.ymin= RNA_int_get(op->ptr, "ymin"); 00281 rect.xmax= RNA_int_get(op->ptr, "xmax"); 00282 rect.ymax= RNA_int_get(op->ptr, "ymax"); 00283 00284 if(!extend) { 00285 SpaceFile *sfile= CTX_wm_space_file(C); 00286 00287 file_deselect_all(sfile, SELECTED_FILE); 00288 } 00289 00290 BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect); 00291 00292 ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, 0); 00293 if (FILE_SELECT_DIR == ret) { 00294 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00295 } else if (FILE_SELECT_FILE == ret) { 00296 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 00297 } 00298 return OPERATOR_FINISHED; 00299 } 00300 00301 void FILE_OT_select_border(wmOperatorType *ot) 00302 { 00303 /* identifiers */ 00304 ot->name= "Activate/Select File"; 00305 ot->description= "Activate/select the file(s) contained in the border"; 00306 ot->idname= "FILE_OT_select_border"; 00307 00308 /* api callbacks */ 00309 ot->invoke= WM_border_select_invoke; 00310 ot->exec= file_border_select_exec; 00311 ot->modal= file_border_select_modal; 00312 ot->poll= ED_operator_file_active; 00313 ot->cancel= WM_border_select_cancel; 00314 00315 /* rna */ 00316 WM_operator_properties_gesture_border(ot, 1); 00317 } 00318 00319 static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) 00320 { 00321 ARegion *ar= CTX_wm_region(C); 00322 SpaceFile *sfile= CTX_wm_space_file(C); 00323 FileSelect ret; 00324 rcti rect; 00325 int extend = RNA_boolean_get(op->ptr, "extend"); 00326 int fill = RNA_boolean_get(op->ptr, "fill"); 00327 00328 if(ar->regiontype != RGN_TYPE_WINDOW) 00329 return OPERATOR_CANCELLED; 00330 00331 rect.xmin = rect.xmax = event->mval[0]; 00332 rect.ymin = rect.ymax = event->mval[1]; 00333 00334 if(!BLI_in_rcti(&ar->v2d.mask, rect.xmin, rect.ymin)) 00335 return OPERATOR_CANCELLED; 00336 00337 /* single select, deselect all selected first */ 00338 if (!extend) file_deselect_all(sfile, SELECTED_FILE); 00339 00340 ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill); 00341 if (FILE_SELECT_DIR == ret) 00342 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00343 else if (FILE_SELECT_FILE == ret) 00344 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 00345 00346 WM_event_add_mousemove(C); /* for directory changes */ 00347 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 00348 00349 return OPERATOR_FINISHED; 00350 } 00351 00352 void FILE_OT_select(wmOperatorType *ot) 00353 { 00354 /* identifiers */ 00355 ot->name= "Activate/Select File"; 00356 ot->description= "Activate/select file"; 00357 ot->idname= "FILE_OT_select"; 00358 00359 /* api callbacks */ 00360 ot->invoke= file_select_invoke; 00361 ot->poll= ED_operator_file_active; 00362 00363 /* rna */ 00364 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); 00365 RNA_def_boolean(ot->srna, "fill", 0, "Fill", "Select everything beginning with the last selection"); 00366 } 00367 00368 static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op)) 00369 { 00370 ScrArea *sa= CTX_wm_area(C); 00371 SpaceFile *sfile= CTX_wm_space_file(C); 00372 FileSelection sel; 00373 int numfiles = filelist_numfiles(sfile->files); 00374 int i; 00375 int is_selected = 0; 00376 00377 sel.first = 0; 00378 sel.last = numfiles-1; 00379 00380 /* Is any file selected ? */ 00381 for ( i=0; i < numfiles; ++i) { 00382 if (filelist_is_selected(sfile->files, i, CHECK_ALL)) { 00383 is_selected = 1; 00384 break; 00385 } 00386 } 00387 /* select all only if previously no file was selected */ 00388 if (is_selected) { 00389 filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, SELECTED_FILE, CHECK_ALL); 00390 } 00391 else { 00392 const FileCheckType check_type= (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES; 00393 filelist_select(sfile->files, &sel, FILE_SEL_ADD, SELECTED_FILE, check_type); 00394 } 00395 ED_area_tag_redraw(sa); 00396 return OPERATOR_FINISHED; 00397 } 00398 00399 void FILE_OT_select_all_toggle(wmOperatorType *ot) 00400 { 00401 /* identifiers */ 00402 ot->name= "Select/Deselect All Files"; 00403 ot->description= "Select/deselect all files"; 00404 ot->idname= "FILE_OT_select_all_toggle"; 00405 00406 /* api callbacks */ 00407 ot->exec= file_select_all_exec; 00408 ot->poll= ED_operator_file_active; 00409 00410 /* rna */ 00411 00412 00413 } 00414 00415 /* ---------- BOOKMARKS ----------- */ 00416 00417 static int bookmark_select_exec(bContext *C, wmOperator *op) 00418 { 00419 SpaceFile *sfile= CTX_wm_space_file(C); 00420 00421 if(RNA_struct_find_property(op->ptr, "dir")) { 00422 char entry[256]; 00423 FileSelectParams* params = sfile->params; 00424 00425 RNA_string_get(op->ptr, "dir", entry); 00426 BLI_strncpy(params->dir, entry, sizeof(params->dir)); 00427 BLI_cleanup_dir(G.main->name, params->dir); 00428 file_change_dir(C, 1); 00429 00430 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00431 } 00432 00433 return OPERATOR_FINISHED; 00434 } 00435 00436 void FILE_OT_select_bookmark(wmOperatorType *ot) 00437 { 00438 /* identifiers */ 00439 ot->name= "Select Directory"; 00440 ot->description= "Select a bookmarked directory"; 00441 ot->idname= "FILE_OT_select_bookmark"; 00442 00443 /* api callbacks */ 00444 ot->exec= bookmark_select_exec; 00445 ot->poll= ED_operator_file_active; 00446 00447 RNA_def_string(ot->srna, "dir", "", 256, "Dir", ""); 00448 } 00449 00450 static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) 00451 { 00452 ScrArea *sa= CTX_wm_area(C); 00453 SpaceFile *sfile= CTX_wm_space_file(C); 00454 struct FSMenu* fsmenu = fsmenu_get(); 00455 struct FileSelectParams* params= ED_fileselect_get_params(sfile); 00456 00457 if (params->dir[0] != '\0') { 00458 char name[FILE_MAX]; 00459 00460 fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1); 00461 BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); 00462 fsmenu_write_file(fsmenu, name); 00463 } 00464 00465 ED_area_tag_redraw(sa); 00466 return OPERATOR_FINISHED; 00467 } 00468 00469 void FILE_OT_bookmark_add(wmOperatorType *ot) 00470 { 00471 /* identifiers */ 00472 ot->name= "Add Bookmark"; 00473 ot->description= "Add a bookmark for the selected/active directory"; 00474 ot->idname= "FILE_OT_bookmark_add"; 00475 00476 /* api callbacks */ 00477 ot->exec= bookmark_add_exec; 00478 ot->poll= ED_operator_file_active; 00479 } 00480 00481 static int bookmark_delete_exec(bContext *C, wmOperator *op) 00482 { 00483 ScrArea *sa= CTX_wm_area(C); 00484 struct FSMenu* fsmenu = fsmenu_get(); 00485 int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS); 00486 00487 if(RNA_struct_find_property(op->ptr, "index")) { 00488 int index = RNA_int_get(op->ptr, "index"); 00489 if ( (index >-1) && (index < nentries)) { 00490 char name[FILE_MAX]; 00491 00492 fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index); 00493 BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); 00494 fsmenu_write_file(fsmenu, name); 00495 ED_area_tag_redraw(sa); 00496 } 00497 } 00498 00499 return OPERATOR_FINISHED; 00500 } 00501 00502 void FILE_OT_delete_bookmark(wmOperatorType *ot) 00503 { 00504 /* identifiers */ 00505 ot->name= "Delete Bookmark"; 00506 ot->description= "Delete selected bookmark"; 00507 ot->idname= "FILE_OT_delete_bookmark"; 00508 00509 /* api callbacks */ 00510 ot->exec= bookmark_delete_exec; 00511 ot->poll= ED_operator_file_active; 00512 00513 RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000); 00514 } 00515 00516 int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) 00517 { 00518 View2D* v2d = &ar->v2d; 00519 FileSelectParams* params; 00520 int numfiles, origfile; 00521 00522 if(sfile==NULL || sfile->files==NULL) return 0; 00523 00524 numfiles = filelist_numfiles(sfile->files); 00525 params = ED_fileselect_get_params(sfile); 00526 00527 origfile= params->active_file; 00528 00529 mx -= ar->winrct.xmin; 00530 my -= ar->winrct.ymin; 00531 00532 if(BLI_in_rcti(&ar->v2d.mask, mx, my)) { 00533 float fx, fy; 00534 int active_file; 00535 00536 UI_view2d_region_to_view(v2d, mx, my, &fx, &fy); 00537 00538 active_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy)); 00539 00540 if((active_file >= 0) && (active_file < numfiles)) 00541 params->active_file=active_file; 00542 else 00543 params->active_file= -1; 00544 } 00545 else 00546 params->active_file= -1; 00547 00548 return (params->active_file != origfile); 00549 } 00550 00551 static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 00552 { 00553 ARegion *ar= CTX_wm_region(C); 00554 SpaceFile *sfile= CTX_wm_space_file(C); 00555 00556 if(!file_hilight_set(sfile, ar, event->x, event->y)) 00557 return OPERATOR_CANCELLED; 00558 00559 ED_area_tag_redraw(CTX_wm_area(C)); 00560 00561 return OPERATOR_FINISHED; 00562 } 00563 00564 void FILE_OT_highlight(struct wmOperatorType *ot) 00565 { 00566 /* identifiers */ 00567 ot->name= "Highlight File"; 00568 ot->description= "Highlight selected file(s)"; 00569 ot->idname= "FILE_OT_highlight"; 00570 00571 /* api callbacks */ 00572 ot->invoke= file_highlight_invoke; 00573 ot->poll= ED_operator_file_active; 00574 } 00575 00576 int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) 00577 { 00578 SpaceFile *sfile= CTX_wm_space_file(C); 00579 wmOperator *op = sfile->op; 00580 00581 sfile->op = NULL; 00582 00583 WM_event_fileselect_event(C, op, EVT_FILESELECT_CANCEL); 00584 00585 return OPERATOR_FINISHED; 00586 } 00587 00588 static int file_operator_poll(bContext *C) 00589 { 00590 int poll = ED_operator_file_active(C); 00591 SpaceFile *sfile= CTX_wm_space_file(C); 00592 00593 if (!sfile || !sfile->op) poll= 0; 00594 00595 return poll; 00596 } 00597 00598 void FILE_OT_cancel(struct wmOperatorType *ot) 00599 { 00600 /* identifiers */ 00601 ot->name= "Cancel File Load"; 00602 ot->description= "Cancel loading of selected file"; 00603 ot->idname= "FILE_OT_cancel"; 00604 00605 /* api callbacks */ 00606 ot->exec= file_cancel_exec; 00607 ot->poll= file_operator_poll; 00608 } 00609 00610 00611 void file_sfile_to_operator(wmOperator *op, SpaceFile *sfile, char *filepath) 00612 { 00613 BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); /* XXX, not real length */ 00614 if(RNA_struct_find_property(op->ptr, "relative_path")) { 00615 if(RNA_boolean_get(op->ptr, "relative_path")) { 00616 BLI_path_rel(filepath, G.main->name); 00617 } 00618 } 00619 00620 if(RNA_struct_find_property(op->ptr, "filename")) { 00621 RNA_string_set(op->ptr, "filename", sfile->params->file); 00622 } 00623 if(RNA_struct_find_property(op->ptr, "directory")) { 00624 RNA_string_set(op->ptr, "directory", sfile->params->dir); 00625 } 00626 if(RNA_struct_find_property(op->ptr, "filepath")) { 00627 RNA_string_set(op->ptr, "filepath", filepath); 00628 } 00629 00630 /* some ops have multiple files to select */ 00631 /* this is called on operators check() so clear collections first since 00632 * they may be already set. */ 00633 { 00634 PointerRNA itemptr; 00635 PropertyRNA *prop_files= RNA_struct_find_property(op->ptr, "files"); 00636 PropertyRNA *prop_dirs= RNA_struct_find_property(op->ptr, "dirs"); 00637 int i, numfiles = filelist_numfiles(sfile->files); 00638 00639 if(prop_files) { 00640 RNA_property_collection_clear(op->ptr, prop_files); 00641 for (i=0; i<numfiles; i++) { 00642 if (filelist_is_selected(sfile->files, i, CHECK_FILES)) { 00643 struct direntry *file= filelist_file(sfile->files, i); 00644 RNA_property_collection_add(op->ptr, prop_files, &itemptr); 00645 RNA_string_set(&itemptr, "name", file->relname); 00646 } 00647 } 00648 } 00649 00650 if(prop_dirs) { 00651 RNA_property_collection_clear(op->ptr, prop_dirs); 00652 for (i=0; i<numfiles; i++) { 00653 if (filelist_is_selected(sfile->files, i, CHECK_DIRS)) { 00654 struct direntry *file= filelist_file(sfile->files, i); 00655 RNA_property_collection_add(op->ptr, prop_dirs, &itemptr); 00656 RNA_string_set(&itemptr, "name", file->relname); 00657 } 00658 } 00659 } 00660 00661 00662 } 00663 } 00664 00665 void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op) 00666 { 00667 PropertyRNA *prop; 00668 00669 /* If neither of the above are set, split the filepath back */ 00670 if((prop= RNA_struct_find_property(op->ptr, "filepath"))) { 00671 char filepath[FILE_MAX]; 00672 RNA_property_string_get(op->ptr, prop, filepath); 00673 BLI_split_dirfile(filepath, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); 00674 } 00675 else { 00676 if((prop= RNA_struct_find_property(op->ptr, "filename"))) { 00677 RNA_property_string_get(op->ptr, prop, sfile->params->file); 00678 } 00679 if((prop= RNA_struct_find_property(op->ptr, "directory"))) { 00680 RNA_property_string_get(op->ptr, prop, sfile->params->dir); 00681 } 00682 } 00683 00684 /* we could check for relative_path property which is used when converting 00685 * in the other direction but doesnt hurt to do this every time */ 00686 BLI_path_abs(sfile->params->dir, G.main->name); 00687 00688 /* XXX, files and dirs updates missing, not really so important though */ 00689 } 00690 00691 void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) 00692 { 00693 SpaceFile *sfile= CTX_wm_space_file(C); 00694 wmOperator *op= sfile->op; 00695 if(op) { /* fail on reload */ 00696 if(op->type->check) { 00697 char filepath[FILE_MAX]; 00698 file_sfile_to_operator(op, sfile, filepath); 00699 00700 /* redraw */ 00701 if(op->type->check(C, op)) { 00702 file_operator_to_sfile(sfile, op); 00703 00704 /* redraw, else the changed settings wont get updated */ 00705 ED_area_tag_redraw(CTX_wm_area(C)); 00706 } 00707 } 00708 } 00709 } 00710 00711 int file_draw_check_exists(SpaceFile *sfile) 00712 { 00713 if(sfile->op) { /* fails on reload */ 00714 if(RNA_struct_find_property(sfile->op->ptr, "check_existing")) { 00715 if(RNA_boolean_get(sfile->op->ptr, "check_existing")) { 00716 char filepath[FILE_MAX]; 00717 BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); 00718 if(BLI_is_file(filepath)) { 00719 return TRUE; 00720 } 00721 } 00722 } 00723 } 00724 00725 return FALSE; 00726 } 00727 00728 /* sends events now, so things get handled on windowqueue level */ 00729 int file_exec(bContext *C, wmOperator *exec_op) 00730 { 00731 SpaceFile *sfile= CTX_wm_space_file(C); 00732 char filepath[FILE_MAX]; 00733 00734 if(sfile->op) { 00735 wmOperator *op= sfile->op; 00736 00737 /* when used as a macro, for doubleclick, 00738 to prevent closing when doubleclicking on .. item */ 00739 if (RNA_boolean_get(exec_op->ptr, "need_active")) { 00740 int i, active=0; 00741 00742 for (i=0; i<filelist_numfiles(sfile->files); i++) { 00743 if(filelist_is_selected(sfile->files, i, CHECK_ALL)) { 00744 active=1; 00745 break; 00746 } 00747 } 00748 if (active == 0) 00749 return OPERATOR_CANCELLED; 00750 } 00751 00752 sfile->op = NULL; 00753 00754 file_sfile_to_operator(op, sfile, filepath); 00755 00756 if (BLI_exists(sfile->params->dir)) 00757 fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, 0, 1); 00758 00759 BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); 00760 fsmenu_write_file(fsmenu_get(), filepath); 00761 WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC); 00762 00763 } 00764 00765 return OPERATOR_FINISHED; 00766 } 00767 00768 void FILE_OT_execute(struct wmOperatorType *ot) 00769 { 00770 /* identifiers */ 00771 ot->name= "Execute File Window"; 00772 ot->description= "Execute selected file"; 00773 ot->idname= "FILE_OT_execute"; 00774 00775 /* api callbacks */ 00776 ot->exec= file_exec; 00777 ot->poll= file_operator_poll; 00778 00779 RNA_def_boolean(ot->srna, "need_active", 0, "Need Active", "Only execute if there's an active selected file in the file list"); 00780 } 00781 00782 00783 int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) 00784 { 00785 SpaceFile *sfile= CTX_wm_space_file(C); 00786 00787 if(sfile->params) { 00788 if (BLI_has_parent(sfile->params->dir)) { 00789 BLI_parent_dir(sfile->params->dir); 00790 BLI_cleanup_dir(G.main->name, sfile->params->dir); 00791 file_change_dir(C, 0); 00792 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00793 } 00794 } 00795 00796 return OPERATOR_FINISHED; 00797 00798 } 00799 00800 00801 void FILE_OT_parent(struct wmOperatorType *ot) 00802 { 00803 /* identifiers */ 00804 ot->name= "Parent File"; 00805 ot->description= "Move to parent directory"; 00806 ot->idname= "FILE_OT_parent"; 00807 00808 /* api callbacks */ 00809 ot->exec= file_parent_exec; 00810 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 00811 } 00812 00813 00814 static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) 00815 { 00816 SpaceFile *sfile= CTX_wm_space_file(C); 00817 00818 ED_fileselect_clear(C, sfile); 00819 00820 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00821 00822 return OPERATOR_FINISHED; 00823 00824 } 00825 00826 void FILE_OT_previous(struct wmOperatorType *ot) 00827 { 00828 /* identifiers */ 00829 ot->name= "Previous Folder"; 00830 ot->description= "Move to previous folder"; 00831 ot->idname= "FILE_OT_previous"; 00832 00833 /* api callbacks */ 00834 ot->exec= file_previous_exec; 00835 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 00836 } 00837 00838 int file_previous_exec(bContext *C, wmOperator *UNUSED(unused)) 00839 { 00840 SpaceFile *sfile= CTX_wm_space_file(C); 00841 00842 if(sfile->params) { 00843 if (!sfile->folders_next) 00844 sfile->folders_next = folderlist_new(); 00845 00846 folderlist_pushdir(sfile->folders_next, sfile->params->dir); 00847 folderlist_popdir(sfile->folders_prev, sfile->params->dir); 00848 folderlist_pushdir(sfile->folders_next, sfile->params->dir); 00849 00850 file_change_dir(C, 1); 00851 } 00852 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00853 00854 return OPERATOR_FINISHED; 00855 } 00856 00857 void FILE_OT_next(struct wmOperatorType *ot) 00858 { 00859 /* identifiers */ 00860 ot->name= "Next Folder"; 00861 ot->description= "Move to next folder"; 00862 ot->idname= "FILE_OT_next"; 00863 00864 /* api callbacks */ 00865 ot->exec= file_next_exec; 00866 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 00867 } 00868 00869 int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) 00870 { 00871 SpaceFile *sfile= CTX_wm_space_file(C); 00872 if(sfile->params) { 00873 if (!sfile->folders_next) 00874 sfile->folders_next = folderlist_new(); 00875 00876 folderlist_pushdir(sfile->folders_prev, sfile->params->dir); 00877 folderlist_popdir(sfile->folders_next, sfile->params->dir); 00878 00879 // update folders_prev so we can check for it in folderlist_clear_next() 00880 folderlist_pushdir(sfile->folders_prev, sfile->params->dir); 00881 00882 file_change_dir(C, 1); 00883 } 00884 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 00885 00886 return OPERATOR_FINISHED; 00887 } 00888 00889 00890 /* only meant for timer usage */ 00891 static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 00892 { 00893 ScrArea *sa = CTX_wm_area(C); 00894 SpaceFile *sfile= CTX_wm_space_file(C); 00895 ARegion *ar, *oldar= CTX_wm_region(C); 00896 int offset; 00897 int numfiles, numfiles_layout; 00898 int edit_idx = 0; 00899 int i; 00900 00901 /* escape if not our timer */ 00902 if(sfile->smoothscroll_timer==NULL || sfile->smoothscroll_timer!=event->customdata) 00903 return OPERATOR_PASS_THROUGH; 00904 00905 numfiles = filelist_numfiles(sfile->files); 00906 00907 /* check if we are editing a name */ 00908 for (i=0; i < numfiles; ++i) 00909 { 00910 if (filelist_is_selected(sfile->files, i, CHECK_ALL) ) { 00911 edit_idx=i; 00912 break; 00913 } 00914 } 00915 00916 /* if we are not editing, we are done */ 00917 if (0==edit_idx) { 00918 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); 00919 sfile->smoothscroll_timer=NULL; 00920 return OPERATOR_PASS_THROUGH; 00921 } 00922 00923 /* we need the correct area for scrolling */ 00924 ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); 00925 if (!ar || ar->regiontype != RGN_TYPE_WINDOW) { 00926 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); 00927 sfile->smoothscroll_timer=NULL; 00928 return OPERATOR_PASS_THROUGH; 00929 } 00930 00931 offset = ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax); 00932 if (offset<0) offset=0; 00933 00934 /* scroll offset is the first file in the row/column we are editing in */ 00935 if (sfile->scroll_offset == 0) { 00936 if (sfile->layout->flag & FILE_LAYOUT_HOR) { 00937 sfile->scroll_offset = (edit_idx/sfile->layout->rows)*sfile->layout->rows; 00938 if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->rows; 00939 } else { 00940 sfile->scroll_offset = (edit_idx/sfile->layout->columns)*sfile->layout->columns; 00941 if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->columns; 00942 } 00943 } 00944 00945 numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar); 00946 00947 /* check if we have reached our final scroll position */ 00948 if ( (sfile->scroll_offset >= offset) && (sfile->scroll_offset < offset + numfiles_layout) ) { 00949 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); 00950 sfile->smoothscroll_timer=NULL; 00951 return OPERATOR_FINISHED; 00952 } 00953 00954 /* temporarily set context to the main window region, 00955 * so the scroll operators work */ 00956 CTX_wm_region_set(C, ar); 00957 00958 /* scroll one step in the desired direction */ 00959 if (sfile->scroll_offset < offset) { 00960 if (sfile->layout->flag & FILE_LAYOUT_HOR) { 00961 WM_operator_name_call(C, "VIEW2D_OT_scroll_left", 0, NULL); 00962 } else { 00963 WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL); 00964 } 00965 00966 } else { 00967 if (sfile->layout->flag & FILE_LAYOUT_HOR) { 00968 WM_operator_name_call(C, "VIEW2D_OT_scroll_right", 0, NULL); 00969 } else { 00970 WM_operator_name_call(C, "VIEW2D_OT_scroll_down", 0, NULL); 00971 } 00972 } 00973 00974 ED_region_tag_redraw(CTX_wm_region(C)); 00975 00976 /* and restore context */ 00977 CTX_wm_region_set(C, oldar); 00978 00979 return OPERATOR_FINISHED; 00980 } 00981 00982 00983 void FILE_OT_smoothscroll(wmOperatorType *ot) 00984 { 00985 00986 /* identifiers */ 00987 ot->name= "Smooth Scroll"; 00988 ot->idname= "FILE_OT_smoothscroll"; 00989 ot->description="Smooth scroll to make editable file visible"; 00990 00991 /* api callbacks */ 00992 ot->invoke= file_smoothscroll_invoke; 00993 00994 ot->poll= ED_operator_file_active; 00995 } 00996 00997 00998 /* create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created. 00999 The actual name is returned in 'name', 'folder' contains the complete path, including the new folder name. 01000 */ 01001 static int new_folder_path(const char* parent, char *folder, char *name) 01002 { 01003 int i = 1; 01004 int len = 0; 01005 01006 BLI_strncpy(name, "New Folder", FILE_MAXFILE); 01007 BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */ 01008 /* check whether folder with the name already exists, in this case 01009 add number to the name. Check length of generated name to avoid 01010 crazy case of huge number of folders each named 'New Folder (x)' */ 01011 while (BLI_exists(folder) && (len<FILE_MAXFILE)) { 01012 len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i); 01013 BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */ 01014 i++; 01015 } 01016 01017 return (len<FILE_MAXFILE); 01018 } 01019 01020 int file_directory_new_exec(bContext *C, wmOperator *op) 01021 { 01022 char name[FILE_MAXFILE]; 01023 char path[FILE_MAX]; 01024 int generate_name= 1; 01025 01026 SpaceFile *sfile= CTX_wm_space_file(C); 01027 01028 if(!sfile->params) { 01029 BKE_report(op->reports,RPT_WARNING, "No parent directory given"); 01030 return OPERATOR_CANCELLED; 01031 } 01032 01033 path[0] = '\0'; 01034 01035 if(RNA_struct_find_property(op->ptr, "directory")) { 01036 RNA_string_get(op->ptr, "directory", path); 01037 if (path[0] != '\0') generate_name= 0; 01038 } 01039 01040 if (generate_name) { 01041 /* create a new, non-existing folder name */ 01042 if (!new_folder_path(sfile->params->dir, path, name)) { 01043 BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder name"); 01044 return OPERATOR_CANCELLED; 01045 } 01046 } 01047 01048 /* create the file */ 01049 BLI_dir_create_recursive(path); 01050 01051 if (!BLI_exists(path)) { 01052 BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder"); 01053 return OPERATOR_CANCELLED; 01054 } 01055 01056 /* now remember file to jump into editing */ 01057 BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE); 01058 01059 /* set timer to smoothly view newly generated file */ 01060 sfile->smoothscroll_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/1000.0); /* max 30 frs/sec */ 01061 sfile->scroll_offset=0; 01062 01063 /* reload dir to make sure we're seeing what's in the directory */ 01064 ED_fileselect_clear(C, sfile); 01065 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 01066 01067 return OPERATOR_FINISHED; 01068 } 01069 01070 01071 void FILE_OT_directory_new(struct wmOperatorType *ot) 01072 { 01073 /* identifiers */ 01074 ot->name= "Create New Directory"; 01075 ot->description= "Create a new directory"; 01076 ot->idname= "FILE_OT_directory_new"; 01077 01078 /* api callbacks */ 01079 ot->invoke= WM_operator_confirm; 01080 ot->exec= file_directory_new_exec; 01081 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 01082 01083 RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory"); 01084 01085 } 01086 01087 01088 static void file_expand_directory(bContext *C) 01089 { 01090 SpaceFile *sfile= CTX_wm_space_file(C); 01091 01092 if(sfile->params) { 01093 if ( sfile->params->dir[0] == '~' ) { 01094 char tmpstr[sizeof(sfile->params->dir)-1]; 01095 BLI_strncpy(tmpstr, sfile->params->dir+1, sizeof(tmpstr)); 01096 BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BLI_getDefaultDocumentFolder(), tmpstr); 01097 } 01098 01099 #ifdef WIN32 01100 if (sfile->params->dir[0] == '\0') { 01101 get_default_root(sfile->params->dir); 01102 } 01103 /* change "C:" --> "C:\", [#28102] */ 01104 else if ( (isalpha(sfile->params->dir[0]) && 01105 (sfile->params->dir[1] == ':')) && 01106 (sfile->params->dir[2] == '\0') 01107 01108 ) { 01109 sfile->params->dir[2]= '\\'; 01110 sfile->params->dir[3]= '\0'; 01111 } 01112 #endif 01113 } 01114 } 01115 01116 static int file_directory_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 01117 { 01118 SpaceFile *sfile= CTX_wm_space_file(C); 01119 01120 if(sfile->params) { 01121 file_expand_directory(C); 01122 01123 if (!BLI_exists(sfile->params->dir)) { 01124 return WM_operator_confirm_message(C, op, "Create new directory?"); 01125 } 01126 01127 return file_directory_exec(C, op); 01128 } 01129 01130 return OPERATOR_CANCELLED; 01131 } 01132 01133 01134 01135 int file_directory_exec(bContext *C, wmOperator *UNUSED(unused)) 01136 { 01137 SpaceFile *sfile= CTX_wm_space_file(C); 01138 01139 if(sfile->params) { 01140 file_expand_directory(C); 01141 01142 if (!BLI_exists(sfile->params->dir)) { 01143 BLI_dir_create_recursive(sfile->params->dir); 01144 } 01145 01146 /* special case, user may have pasted a filepath into the directory */ 01147 if(BLI_is_file(sfile->params->dir)) { 01148 char path[sizeof(sfile->params->dir)]; 01149 BLI_strncpy(path, sfile->params->dir, sizeof(path)); 01150 BLI_split_dirfile(path, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); 01151 } 01152 01153 BLI_cleanup_dir(G.main->name, sfile->params->dir); 01154 BLI_add_slash(sfile->params->dir); 01155 file_change_dir(C, 1); 01156 01157 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 01158 } 01159 01160 01161 return OPERATOR_FINISHED; 01162 } 01163 01164 int file_filename_exec(bContext *C, wmOperator *UNUSED(unused)) 01165 { 01166 SpaceFile *sfile= CTX_wm_space_file(C); 01167 01168 if(sfile->params) { 01169 if (file_select_match(sfile, sfile->params->file)) 01170 { 01171 sfile->params->file[0] = '\0'; 01172 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL); 01173 } 01174 } 01175 01176 return OPERATOR_FINISHED; 01177 } 01178 01179 /* TODO, directory operator is non-functional while a library is loaded 01180 * until this is properly supported just disable it. */ 01181 static int file_directory_poll(bContext *C) 01182 { 01183 /* sfile->files can be NULL on file load */ 01184 SpaceFile *sfile= CTX_wm_space_file(C); 01185 return ED_operator_file_active(C) && (sfile->files==NULL || filelist_lib(sfile->files)==NULL); 01186 } 01187 01188 void FILE_OT_directory(struct wmOperatorType *ot) 01189 { 01190 /* identifiers */ 01191 ot->name= "Enter Directory Name"; 01192 ot->description= "Enter a directory name"; 01193 ot->idname= "FILE_OT_directory"; 01194 01195 /* api callbacks */ 01196 ot->invoke= file_directory_invoke; 01197 ot->exec= file_directory_exec; 01198 ot->poll= file_directory_poll; /* <- important, handler is on window level */ 01199 } 01200 01201 void FILE_OT_refresh(struct wmOperatorType *ot) 01202 { 01203 /* identifiers */ 01204 ot->name= "Refresh Filelist"; 01205 ot->description= "Refresh the file list"; 01206 ot->idname= "FILE_OT_refresh"; 01207 01208 /* api callbacks */ 01209 ot->exec= file_refresh_exec; 01210 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 01211 } 01212 01213 static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) 01214 { 01215 SpaceFile *sfile= CTX_wm_space_file(C); 01216 01217 if(sfile->params) { 01218 sfile->params->flag ^= FILE_HIDE_DOT; 01219 ED_fileselect_clear(C, sfile); 01220 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 01221 } 01222 01223 return OPERATOR_FINISHED; 01224 } 01225 01226 01227 void FILE_OT_hidedot(struct wmOperatorType *ot) 01228 { 01229 /* identifiers */ 01230 ot->name= "Toggle Hide Dot Files"; 01231 ot->description= "Toggle hide hidden dot files"; 01232 ot->idname= "FILE_OT_hidedot"; 01233 01234 /* api callbacks */ 01235 ot->exec= file_hidedot_exec; 01236 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 01237 } 01238 01239 struct ARegion *file_buttons_region(struct ScrArea *sa) 01240 { 01241 ARegion *ar, *arnew; 01242 01243 for(ar= sa->regionbase.first; ar; ar= ar->next) 01244 if(ar->regiontype==RGN_TYPE_CHANNELS) 01245 return ar; 01246 01247 /* add subdiv level; after header */ 01248 for(ar= sa->regionbase.first; ar; ar= ar->next) 01249 if(ar->regiontype==RGN_TYPE_HEADER) 01250 break; 01251 01252 /* is error! */ 01253 if(ar==NULL) return NULL; 01254 01255 arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels"); 01256 01257 BLI_insertlinkafter(&sa->regionbase, ar, arnew); 01258 arnew->regiontype= RGN_TYPE_CHANNELS; 01259 arnew->alignment= RGN_ALIGN_LEFT; 01260 01261 arnew->flag = RGN_FLAG_HIDDEN; 01262 01263 return arnew; 01264 } 01265 01266 static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused)) 01267 { 01268 ScrArea *sa= CTX_wm_area(C); 01269 ARegion *ar= file_buttons_region(sa); 01270 01271 if(ar) 01272 ED_region_toggle_hidden(C, ar); 01273 01274 return OPERATOR_FINISHED; 01275 } 01276 01277 void FILE_OT_bookmark_toggle(struct wmOperatorType *ot) 01278 { 01279 /* identifiers */ 01280 ot->name= "Toggle Bookmarks"; 01281 ot->description= "Toggle bookmarks display"; 01282 ot->idname= "FILE_OT_bookmark_toggle"; 01283 01284 /* api callbacks */ 01285 ot->exec= file_bookmark_toggle_exec; 01286 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 01287 } 01288 01289 01290 static int file_filenum_exec(bContext *C, wmOperator *op) 01291 { 01292 SpaceFile *sfile= CTX_wm_space_file(C); 01293 ScrArea *sa= CTX_wm_area(C); 01294 01295 int inc = RNA_int_get(op->ptr, "increment"); 01296 if(sfile->params && (inc != 0)) { 01297 BLI_newname(sfile->params->file, inc); 01298 ED_area_tag_redraw(sa); 01299 file_draw_check_cb(C, NULL, NULL); 01300 // WM_event_add_notifier(C, NC_WINDOW, NULL); 01301 } 01302 01303 return OPERATOR_FINISHED; 01304 01305 } 01306 01307 void FILE_OT_filenum(struct wmOperatorType *ot) 01308 { 01309 /* identifiers */ 01310 ot->name= "Increment Number in Filename"; 01311 ot->description= "Increment number in filename"; 01312 ot->idname= "FILE_OT_filenum"; 01313 01314 /* api callbacks */ 01315 ot->exec= file_filenum_exec; 01316 ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ 01317 01318 /* props */ 01319 RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100,100); 01320 } 01321 01322 static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) 01323 { 01324 ScrArea *sa= CTX_wm_area(C); 01325 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); 01326 01327 if(sfile->params) { 01328 int idx = sfile->params->active_file; 01329 int numfiles = filelist_numfiles(sfile->files); 01330 if ( (0<=idx) && (idx<numfiles) ) { 01331 struct direntry *file= filelist_file(sfile->files, idx); 01332 filelist_select_file(sfile->files, idx, FILE_SEL_ADD, EDITING_FILE, CHECK_ALL); 01333 BLI_strncpy(sfile->params->renameedit, file->relname, FILE_MAXFILE); 01334 sfile->params->renamefile[0]= '\0'; 01335 } 01336 ED_area_tag_redraw(sa); 01337 } 01338 01339 return OPERATOR_FINISHED; 01340 01341 } 01342 01343 static int file_rename_poll(bContext *C) 01344 { 01345 int poll = ED_operator_file_active(C); 01346 SpaceFile *sfile= CTX_wm_space_file(C); 01347 01348 if (sfile && sfile->params) { 01349 if (sfile->params->active_file < 0) { 01350 poll= 0; 01351 } else { 01352 char dir[FILE_MAX], group[FILE_MAX]; 01353 if (filelist_islibrary(sfile->files, dir, group)) poll= 0; 01354 } 01355 } 01356 else 01357 poll= 0; 01358 return poll; 01359 } 01360 01361 void FILE_OT_rename(struct wmOperatorType *ot) 01362 { 01363 /* identifiers */ 01364 ot->name= "Rename File or Directory"; 01365 ot->description= "Rename file or file directory"; 01366 ot->idname= "FILE_OT_rename"; 01367 01368 /* api callbacks */ 01369 ot->exec= file_rename_exec; 01370 ot->poll= file_rename_poll; 01371 01372 } 01373 01374 static int file_delete_poll(bContext *C) 01375 { 01376 int poll = ED_operator_file_active(C); 01377 SpaceFile *sfile= CTX_wm_space_file(C); 01378 struct direntry* file; 01379 01380 if (sfile && sfile->params) { 01381 if (sfile->params->active_file < 0) { 01382 poll= 0; 01383 } else { 01384 char dir[FILE_MAX], group[FILE_MAX]; 01385 if (filelist_islibrary(sfile->files, dir, group)) poll= 0; 01386 file = filelist_file(sfile->files, sfile->params->active_file); 01387 if (file && S_ISDIR(file->type)) poll= 0; 01388 } 01389 } 01390 else 01391 poll= 0; 01392 01393 return poll; 01394 } 01395 01396 int file_delete_exec(bContext *C, wmOperator *UNUSED(op)) 01397 { 01398 char str[FILE_MAX]; 01399 SpaceFile *sfile= CTX_wm_space_file(C); 01400 struct direntry* file; 01401 01402 01403 file = filelist_file(sfile->files, sfile->params->active_file); 01404 BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname); 01405 BLI_delete(str, 0, 0); 01406 ED_fileselect_clear(C, sfile); 01407 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); 01408 01409 return OPERATOR_FINISHED; 01410 01411 } 01412 01413 void FILE_OT_delete(struct wmOperatorType *ot) 01414 { 01415 /* identifiers */ 01416 ot->name= "Delete File"; 01417 ot->description= "Delete selected file"; 01418 ot->idname= "FILE_OT_delete"; 01419 01420 /* api callbacks */ 01421 ot->invoke= WM_operator_confirm; 01422 ot->exec= file_delete_exec; 01423 ot->poll= file_delete_poll; /* <- important, handler is on window level */ 01424 } 01425 01426 01427 void ED_operatormacros_file(void) 01428 { 01429 // wmOperatorType *ot; 01430 // wmOperatorTypeMacro *otmacro; 01431 01432 /* future macros */ 01433 }