701b0fc1de7355ec489c5460b0c08fe2ac5112b8
[blender.git] / source / blender / editors / space_info / info_ops.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/editors/space_info/info_ops.c
30  *  \ingroup spinfo
31  */
32
33
34 #include <string.h>
35 #include <stdio.h>
36
37 #include "DNA_packedFile_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_windowmanager_types.h"
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_math.h"
45 #include "BLI_bpath.h"
46 #include "BLI_utildefines.h"
47
48 #include "BKE_context.h"
49 #include "BKE_global.h"
50 #include "BKE_image.h"
51 #include "BKE_main.h"
52 #include "BKE_packedFile.h"
53 #include "BKE_report.h"
54
55
56 #include "WM_api.h"
57 #include "WM_types.h"
58
59
60 #include "UI_interface.h"
61 #include "UI_resources.h"
62
63 #include "IMB_imbuf_types.h"
64
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67
68
69 #include "info_intern.h"
70
71 /********************* pack all operator *********************/
72
73 static int pack_all_exec(bContext *C, wmOperator *op)
74 {
75         Main *bmain= CTX_data_main(C);
76
77         packAll(bmain, op->reports);
78         G.fileflags |= G_AUTOPACK;
79
80         return OPERATOR_FINISHED;
81 }
82
83 static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
84 {
85         Main *bmain= CTX_data_main(C);
86         Image *ima;
87         ImBuf *ibuf;
88
89         // first check for dirty images
90         for(ima=bmain->image.first; ima; ima=ima->id.next) {
91                 if(ima->ibufs.first) { /* XXX FIX */
92                         ibuf= BKE_image_get_ibuf(ima, NULL);
93                         
94                         if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
95                                 break;
96                 }
97         }
98
99         if(ima) {
100                 uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?");
101                 return OPERATOR_CANCELLED;
102         }
103
104         return pack_all_exec(C, op);
105 }
106
107 void FILE_OT_pack_all(wmOperatorType *ot)
108 {
109         /* identifiers */
110         ot->name= "Pack All";
111         ot->idname= "FILE_OT_pack_all";
112         
113         /* api callbacks */
114         ot->exec= pack_all_exec;
115         ot->invoke= pack_all_invoke;
116
117         /* flags */
118         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
119 }
120
121 /********************* unpack all operator *********************/
122
123 static const EnumPropertyItem unpack_all_method_items[] = {
124         {PF_USE_LOCAL, "USE_LOCAL", 0, "Use files in current directory (create when necessary)", ""},
125         {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write files to current directory (overwrite existing files)", ""},
126         {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use files in original location (create when necessary)", ""},
127         {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write files to original location (overwrite existing files)", ""},
128         {PF_KEEP, "KEEP", 0, "Disable AutoPack, keep all packed files", ""},
129         {PF_ASK, "ASK", 0, "Ask for each file", ""},
130         {0, NULL, 0, NULL, NULL}};
131
132 static int unpack_all_exec(bContext *C, wmOperator *op)
133 {
134         Main *bmain= CTX_data_main(C);
135         int method= RNA_enum_get(op->ptr, "method");
136
137         if(method != PF_KEEP) unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
138         G.fileflags &= ~G_AUTOPACK;
139
140         return OPERATOR_FINISHED;
141 }
142
143 static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
144 {
145         Main *bmain= CTX_data_main(C);
146         uiPopupMenu *pup;
147         uiLayout *layout;
148         char title[128];
149         int count = 0;
150         
151         count = countPackedFiles(bmain);
152         
153         if(!count) {
154                 BKE_report(op->reports, RPT_WARNING, "No packed files. Autopack disabled.");
155                 G.fileflags &= ~G_AUTOPACK;
156                 return OPERATOR_CANCELLED;
157         }
158
159         if(count == 1)
160                 sprintf(title, "Unpack 1 file");
161         else
162                 sprintf(title, "Unpack %d files", count);
163         
164         pup= uiPupMenuBegin(C, title, ICON_NONE);
165         layout= uiPupMenuLayout(pup);
166
167         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
168         uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
169
170         uiPupMenuEnd(C, pup);
171
172         return OPERATOR_CANCELLED;
173 }
174
175 void FILE_OT_unpack_all(wmOperatorType *ot)
176 {
177         /* identifiers */
178         ot->name= "Unpack All";
179         ot->idname= "FILE_OT_unpack_all";
180         
181         /* api callbacks */
182         ot->exec= unpack_all_exec;
183         ot->invoke= unpack_all_invoke;
184
185         /* flags */
186         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
187
188         /* properties */
189         RNA_def_enum(ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack.");
190 }
191
192 /********************* make paths relative operator *********************/
193
194 static int make_paths_relative_exec(bContext *C, wmOperator *op)
195 {
196         Main *bmain= CTX_data_main(C);
197
198         if(!G.relbase_valid) {
199                 BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file.");
200                 return OPERATOR_CANCELLED;
201         }
202
203         makeFilesRelative(bmain, bmain->name, op->reports);
204
205         /* redraw everything so any changed paths register */
206         WM_main_add_notifier(NC_WINDOW, NULL);
207
208         return OPERATOR_FINISHED;
209 }
210
211 void FILE_OT_make_paths_relative(wmOperatorType *ot)
212 {
213         /* identifiers */
214         ot->name= "Make All Paths Relative";
215         ot->idname= "FILE_OT_make_paths_relative";
216         
217         /* api callbacks */
218         ot->exec= make_paths_relative_exec;
219
220         /* flags */
221         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
222 }
223
224 /********************* make paths absolute operator *********************/
225
226 static int make_paths_absolute_exec(bContext *C, wmOperator *op)
227 {
228         Main *bmain= CTX_data_main(C);
229
230         if(!G.relbase_valid) {
231                 BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file.");
232                 return OPERATOR_CANCELLED;
233         }
234
235         makeFilesAbsolute(bmain, bmain->name, op->reports);
236
237         /* redraw everything so any changed paths register */
238         WM_main_add_notifier(NC_WINDOW, NULL);
239
240         return OPERATOR_FINISHED;
241 }
242
243 void FILE_OT_make_paths_absolute(wmOperatorType *ot)
244 {
245         /* identifiers */
246         ot->name= "Make All Paths Absolute";
247         ot->idname= "FILE_OT_make_paths_absolute";
248         
249         /* api callbacks */
250         ot->exec= make_paths_absolute_exec;
251
252         /* flags */
253         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
254 }
255
256 /********************* report missing files operator *********************/
257
258 static int report_missing_files_exec(bContext *UNUSED(C), wmOperator *op)
259 {
260         /* run the missing file check */
261         checkMissingFiles(G.main, op->reports);
262         
263         return OPERATOR_FINISHED;
264 }
265
266 void FILE_OT_report_missing_files(wmOperatorType *ot)
267 {
268         /* identifiers */
269         ot->name= "Report Missing Files";
270         ot->idname= "FILE_OT_report_missing_files";
271         
272         /* api callbacks */
273         ot->exec= report_missing_files_exec;
274
275         /* flags */
276         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
277 }
278
279 /********************* find missing files operator *********************/
280
281 static int find_missing_files_exec(bContext *UNUSED(C), wmOperator *op)
282 {
283         char *path;
284         
285         path= RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
286         findMissingFiles(G.main, path);
287         MEM_freeN(path);
288
289         return OPERATOR_FINISHED;
290 }
291
292 static int find_missing_files_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
293 {
294         /* XXX file open button text "Find Missing Files" */
295         WM_event_add_fileselect(C, op); 
296         return OPERATOR_RUNNING_MODAL;
297 }
298
299 void FILE_OT_find_missing_files(wmOperatorType *ot)
300 {
301         /* identifiers */
302         ot->name= "Find Missing Files";
303         ot->idname= "FILE_OT_find_missing_files";
304         
305         /* api callbacks */
306         ot->exec= find_missing_files_exec;
307         ot->invoke= find_missing_files_invoke;
308
309         /* flags */
310         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
311
312         /* properties */
313         WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH);
314 }
315
316 /********************* report box operator *********************/
317
318 /* Hard to decide whether to keep this as an operator, 
319  * or turn it into a hardcoded ui control feature, 
320  * handling TIMER events for all regions in interface_handlers.c
321  * Not sure how good that is to be accessing UI data from 
322  * inactive regions, so use this for now. --matt
323  */
324
325 #define INFO_TIMEOUT            5.0
326 #define INFO_COLOR_TIMEOUT      3.0
327 #define ERROR_TIMEOUT           10.0
328 #define ERROR_COLOR_TIMEOUT     6.0
329 #define COLLAPSE_TIMEOUT        0.25
330 static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
331 {
332         wmWindowManager *wm= CTX_wm_manager(C);
333         ReportList *reports= CTX_wm_reports(C);
334         Report *report;
335         ReportTimerInfo *rti;
336         float progress=0.0, color_progress=0.0;
337         float neutral_col[3] = {0.35, 0.35, 0.35};
338         float neutral_grey= 0.6;
339         float timeout=0.0, color_timeout=0.0;
340         int send_note= 0;
341         
342         /* escape if not our timer */
343         if(             (reports->reporttimer==NULL) ||
344                         (reports->reporttimer != event->customdata) ||
345                         ((report= BKE_reports_last_displayable(reports))==NULL) /* may have been deleted */
346         ) {
347                 return OPERATOR_PASS_THROUGH;
348         }
349
350         rti = (ReportTimerInfo *)reports->reporttimer->customdata;
351         
352         timeout = (report->type & RPT_ERROR_ALL)?ERROR_TIMEOUT:INFO_TIMEOUT;
353         color_timeout = (report->type & RPT_ERROR_ALL)?ERROR_COLOR_TIMEOUT:INFO_COLOR_TIMEOUT;
354         
355         /* clear the report display after timeout */
356         if (reports->reporttimer->duration > timeout) {
357                 WM_event_remove_timer(wm, NULL, reports->reporttimer);
358                 reports->reporttimer = NULL;
359                 
360                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_INFO, NULL);
361                 
362                 return (OPERATOR_FINISHED|OPERATOR_PASS_THROUGH);
363         }
364
365         if (rti->widthfac == 0.0f) {
366                 /* initialise colors based on report type */
367                 if(report->type & RPT_ERROR_ALL) {
368                         rti->col[0] = 1.0;
369                         rti->col[1] = 0.2;
370                         rti->col[2] = 0.0;
371                 } else if(report->type & RPT_WARNING_ALL) {
372                         rti->col[0] = 1.0;
373                         rti->col[1] = 1.0;
374                         rti->col[2] = 0.0;
375                 } else if(report->type & RPT_INFO_ALL) {
376                         rti->col[0] = 0.3;
377                         rti->col[1] = 0.45;
378                         rti->col[2] = 0.7;
379                 }
380                 rti->greyscale = 0.75;
381                 rti->widthfac=1.0;
382         }
383         
384         progress = reports->reporttimer->duration / timeout;
385         color_progress = reports->reporttimer->duration / color_timeout;
386         
387         /* save us from too many draws */
388         if(color_progress <= 1.0f) {
389                 send_note= 1;
390                 
391                 /* fade colors out sharply according to progress through fade-out duration */
392                 interp_v3_v3v3(rti->col, rti->col, neutral_col, color_progress);
393                 rti->greyscale = interpf(neutral_grey, rti->greyscale, color_progress);
394         }
395
396         /* collapse report at end of timeout */
397         if (progress*timeout > timeout - COLLAPSE_TIMEOUT) {
398                 rti->widthfac = (progress*timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT;
399                 rti->widthfac = 1.0f - rti->widthfac;
400                 send_note= 1;
401         }
402         
403         if(send_note) {
404                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_INFO, NULL);
405         }
406         
407         return (OPERATOR_FINISHED|OPERATOR_PASS_THROUGH);
408 }
409
410 void INFO_OT_reports_display_update(wmOperatorType *ot)
411 {
412         /* identifiers */
413         ot->name= "Update Reports Display";
414         ot->idname= "INFO_OT_reports_display_update";
415         
416         /* api callbacks */
417         ot->invoke= update_reports_display_invoke;
418         
419         /* flags */
420         ot->flag= 0;
421         
422         /* properties */
423 }
424
425 /* report operators */