/[gnustep]/gnustep/usr-apps/gworkspace/GWorkspace/FileOperations/FileOperation.m
ViewVC logotype

Contents of /gnustep/usr-apps/gworkspace/GWorkspace/FileOperations/FileOperation.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (show annotations) (download)
Sat Oct 4 14:45:18 2003 UTC (20 years, 6 months ago) by esersale
Branch: MAIN
Changes since 1.4: +76 -17 lines

2003-10-03 Enrico Sersale  <enrico@imago.ro>

  * GWorkspace/FileOperations/FileOperation.m
    -calculateNumFiles doesn't block anymore.
    the stop button now works.

  * Viewers/SmallIconsViewer/SmallIconsPanel.m
    in -selectIconWithPath: now the view scroll to show the icon.
-

1 /* FileOperation.m
2 *
3 * Copyright (C) 2003 Free Software Foundation, Inc.
4 *
5 * Author: Enrico Sersale <enrico@imago.ro>
6 * Date: August 2001
7 *
8 * This file is part of the GNUstep GWorkspace application
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25 #include <Foundation/Foundation.h>
26 #include <AppKit/AppKit.h>
27 #ifdef GNUSTEP
28 #include "GWFunctions.h"
29 #include "GWLib.h"
30 #include "GWNotifications.h"
31 #else
32 #include <GWorkspace/GWFunctions.h>
33 #include <GWorkspace/GWLib.h>
34 #include <GWorkspace/GWNotifications.h>
35 #endif
36 #include "FileOperation.h"
37 #include "GWorkspace.h"
38 #include "GNUstep.h"
39
40 #ifndef LONG_DELAY
41 #define LONG_DELAY 86400.0
42 #endif
43
44 static NSString *nibName = @"FileOperationWin";
45
46 @implementation GWorkspace (FileOperations)
47
48 - (int)fileOperationRef
49 {
50 oprefnum++;
51 if (oprefnum == 1000) {
52 oprefnum = 0;
53 }
54 return oprefnum;
55 }
56
57 - (FileOperation *)fileOpWithRef:(int)ref
58 {
59 int i;
60
61 for (i = 0; i < [operations count]; i++) {
62 FileOperation *op = [operations objectAtIndex: i];
63
64 if ([op fileOperationRef] == ref) {
65 return op;
66 }
67 }
68
69 return nil;
70 }
71
72 - (void)endOfFileOperation:(FileOperation *)op
73 {
74 [operations removeObject: op];
75 }
76
77 @end
78
79
80 @implementation FileOperation
81
82 - (void)dealloc
83 {
84 [[NSNotificationCenter defaultCenter] removeObserver: self];
85
86 if (timer && [timer isValid]) {
87 [timer invalidate];
88 }
89
90 RELEASE (operationDict);
91 RELEASE (operation);
92 TEST_RELEASE (source);
93 TEST_RELEASE (destination);
94 TEST_RELEASE (files);
95 TEST_RELEASE (notifNames);
96 TEST_RELEASE (win);
97
98 DESTROY (executor);
99
100 [super dealloc];
101 }
102
103 - (id)initWithOperation:(NSString *)opr
104 source:(NSString *)src
105 destination:(NSString *)dest
106 files:(NSArray *)fls
107 useConfirmation:(BOOL)conf
108 showWindow:(BOOL)showw
109 windowRect:(NSRect)wrect
110 {
111 self = [super init];
112
113 if (self) {
114 if ([NSBundle loadNibNamed: nibName owner: self] == NO) {
115 NSLog(@"failed to load %@!", nibName);
116 } else {
117 int i;
118
119 /* Internationalization */
120 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
121 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
122 [pauseButt setTitle: NSLocalizedString(@"Pause", @"")];
123 [stopButt setTitle: NSLocalizedString(@"Stop", @"")];
124
125 if (NSEqualRects(wrect, NSZeroRect) == NO) {
126 [win setFrame: wrect display: NO];
127 } else if ([win setFrameUsingName: @"fileopprogress"] == NO) {
128 [win setFrame: NSMakeRect(300, 300, 282, 102) display: NO];
129 }
130 [win setDelegate: self];
131
132 gw = [GWorkspace gworkspace];
133 fm = [NSFileManager defaultManager];
134 dnc = [NSDistributedNotificationCenter defaultCenter];
135
136 fileOperationRef = [gw fileOperationRef];
137
138 operation = RETAIN (opr);
139 operationDict = [[NSMutableDictionary alloc] initWithCapacity: 1];
140 [operationDict setObject: operation forKey: @"operation"];
141
142 if (src != nil) {
143 source = [[NSString alloc] initWithString: src];
144 [operationDict setObject: source forKey: @"source"];
145 }
146 if (dest != nil) {
147 destination = [[NSString alloc] initWithString: dest];
148 [operationDict setObject: destination forKey: @"destination"];
149 }
150 if (fls != nil) {
151 files = [[NSMutableArray alloc] initWithCapacity: 1];
152 for(i = 0; i < [fls count]; i++) {
153 [files addObject: [fls objectAtIndex: i]];
154 }
155 [operationDict setObject: files forKey: @"files"];
156 }
157
158 confirm = conf;
159 showwin = showw;
160 executor = nil;
161 opdone = NO;
162
163 if([self showFileOperationAlert] == NO) {
164 [self endOperation];
165 return self;
166 } else {
167 NSMessagePort *port[2];
168 NSArray *ports;
169
170 port[0] = (NSMessagePort *)[NSMessagePort port];
171 port[1] = (NSMessagePort *)[NSMessagePort port];
172 ports = [NSArray arrayWithObjects: port[1], port[0], nil];
173
174 execconn = [[NSConnection alloc] initWithReceivePort: port[0]
175 sendPort: port[1]];
176 [execconn setRootObject: self];
177 [execconn setDelegate: self];
178 [execconn setRequestTimeout: LONG_DELAY];
179 [execconn setReplyTimeout: LONG_DELAY];
180
181 [[NSNotificationCenter defaultCenter] addObserver: self
182 selector: @selector(connectionDidDie:)
183 name: NSConnectionDidDieNotification
184 object: execconn];
185
186 NS_DURING
187 {
188 [NSThread detachNewThreadSelector: @selector(setPorts:)
189 toTarget: [FileOpExecutor class]
190 withObject: ports];
191 }
192 NS_HANDLER
193 {
194 NSLog(@"Error! A fatal error occured while detaching the thread.");
195 }
196 NS_ENDHANDLER
197
198 timer = [NSTimer scheduledTimerWithTimeInterval: 5.0 target: self
199 selector: @selector(checkExecutor:)
200 userInfo: nil repeats: NO];
201 }
202 }
203 }
204
205 return self;
206 }
207
208 - (void)checkExecutor:(id)sender
209 {
210 if ((executor == nil) && (opdone == NO)) {
211 NSString *msg = NSLocalizedString(@"A fatal error occured while detaching the thread!", @"");
212 NSString *buttstr = NSLocalizedString(@"Continue", @"");
213
214 NSRunAlertPanel(nil, msg, buttstr, nil, nil);
215 [self sendDidChangeNotification];
216 [self endOperation];
217 }
218 }
219
220 - (BOOL)showFileOperationAlert
221 {
222 NSString *title;
223 NSString *msg, *msg1, *msg2;
224 int result;
225
226 if(confirm == NO) {
227 return YES;
228 }
229
230 if ([operation isEqual: @"NSWorkspaceMoveOperation"]) {
231 title = NSLocalizedString(@"Move", @"");
232 msg1 = NSLocalizedString(@"Move from: ", @"");
233 msg2 = NSLocalizedString(@"\nto: ", @"");
234 msg = [NSString stringWithFormat: @"%@%@%@%@?", msg1, source, msg2, destination];
235 } else if ([operation isEqual: @"NSWorkspaceCopyOperation"]) {
236 title = NSLocalizedString(@"Copy", @"");
237 msg1 = NSLocalizedString(@"Copy from: ", @"");
238 msg2 = NSLocalizedString(@"\nto: ", @"");
239 msg = [NSString stringWithFormat: @"%@%@%@%@?", msg1, source, msg2, destination];
240 } else if ([operation isEqual: @"NSWorkspaceLinkOperation"]) {
241 title = NSLocalizedString(@"Link", @"");
242 msg1 = NSLocalizedString(@"Link ", @"");
243 msg2 = NSLocalizedString(@"\nto: ", @"");
244 msg = [NSString stringWithFormat: @"%@%@%@%@?", msg1, source, msg2, destination];
245 } else if ([operation isEqual: @"NSWorkspaceRecycleOperation"]) {
246 title = NSLocalizedString(@"Recycler", @"");
247 msg1 = NSLocalizedString(@"Move from: ", @"");
248 msg2 = NSLocalizedString(@"\nto the Recycler", @"");
249 msg = [NSString stringWithFormat: @"%@%@%@?", msg1, source, msg2];
250 } else if ([operation isEqual: @"GWorkspaceRecycleOutOperation"]) {
251 title = NSLocalizedString(@"Recycler", @"");
252 msg1 = NSLocalizedString(@"Move from the Recycler ", @"");
253 msg2 = NSLocalizedString(@"\nto: ", @"");
254 msg = [NSString stringWithFormat: @"%@%@%@?", msg1, msg2, destination];
255 } else if ([operation isEqual: @"GWorkspaceEmptyRecyclerOperation"]) {
256 title = NSLocalizedString(@"Recycler", @"");
257 msg = NSLocalizedString(@"Empty the Recycler?", @"");
258 } else if ([operation isEqual: @"NSWorkspaceDestroyOperation"]) {
259 title = NSLocalizedString(@"Delete", @"");
260 msg = NSLocalizedString(@"Delete the selected objects?", @"");
261 } else if ([operation isEqual: @"NSWorkspaceDuplicateOperation"]) {
262 title = NSLocalizedString(@"Duplicate", @"");
263 msg = NSLocalizedString(@"Duplicate the selected objects?", @"");
264 }
265
266 result = NSRunAlertPanel(title, msg, NSLocalizedString(@"OK", @""),
267 NSLocalizedString(@"Cancel", @""), NULL);
268 if (result != NSAlertDefaultReturn) {
269 return NO;
270 }
271
272 return YES;
273 }
274
275 - (void)registerExecutor:(id)anObject
276 {
277 BOOL result;
278
279 [anObject setProtocolForProxy: @protocol(FileOpExecutorProtocol)];
280 executor = (id <FileOpExecutorProtocol>)[anObject retain];
281
282 result = [executor setOperation: operationDict];
283 result = [executor checkSameName];
284
285 if (result == YES) {
286 NSString *msg, *title;
287
288 if ([operation isEqual: @"NSWorkspaceMoveOperation"]) {
289 msg = @"Some items have the same name;\ndo you want to replace them?";
290 title = @"Move";
291
292 } else if ([operation isEqual: @"NSWorkspaceCopyOperation"]) {
293 msg = @"Some items have the same name;\ndo you want to replace them?";
294 title = @"Copy";
295
296 } else if([operation isEqual: @"NSWorkspaceLinkOperation"]) {
297 msg = @"Some items have the same name;\ndo you want to replace them?";
298 title = @"Link";
299
300 } else if([operation isEqual: @"NSWorkspaceRecycleOperation"]) {
301 msg = @"Some items have the same name;\ndo you want to replace them?";
302 title = @"Recycle";
303
304 } else if([operation isEqual: @"GWorkspaceRecycleOutOperation"]) {
305 msg = @"Some items have the same name;\ndo you want to replace them?";
306 title = @"Recycle";
307 }
308
309 result = NSRunAlertPanel(NSLocalizedString(title, @""),
310 NSLocalizedString(msg, @""),
311 NSLocalizedString(@"OK", @""),
312 NSLocalizedString(@"Cancel", @""), NULL);
313
314 if (result != NSAlertDefaultReturn) {
315 [gw endOfFileOperation: self];
316 return;
317 }
318 }
319
320 filescount = -1;
321 [executor calculateNumFiles];
322 while (filescount == -1) {
323 [[NSRunLoop currentRunLoop]
324 runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
325 }
326
327 if (showwin) {
328 [self showProgressWin];
329 }
330 [self sendWillChangeNotification];
331 [executor performOperation];
332 }
333
334 - (int)requestUserConfirmationWithMessage:(NSString *)message
335 title:(NSString *)title
336 {
337 return NSRunAlertPanel(NSLocalizedString(title, @""),
338 NSLocalizedString(message, @""),
339 NSLocalizedString(@"OK", @""),
340 NSLocalizedString(@"Cancel", @""), NULL);
341 }
342
343 - (void)showProgressWin
344 {
345 if ([win isVisible] == NO) {
346 if ([operation isEqual: @"NSWorkspaceMoveOperation"]) {
347 [win setTitle: NSLocalizedString(@"Move", @"")];
348 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
349 [fromField setStringValue: relativePathFittingInContainer(fromField, source)];
350 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
351 [toField setStringValue: relativePathFittingInContainer(fromField, destination)];
352
353 } else if ([operation isEqual: @"NSWorkspaceCopyOperation"]) {
354 [win setTitle: NSLocalizedString(@"Copy", @"")];
355 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
356 [fromField setStringValue: relativePathFittingInContainer(fromField, source)];
357 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
358 [toField setStringValue: relativePathFittingInContainer(fromField, destination)];
359
360 } else if ([operation isEqual: @"NSWorkspaceLinkOperation"]) {
361 [win setTitle: NSLocalizedString(@"Link", @"")];
362 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
363 [fromField setStringValue: relativePathFittingInContainer(fromField, source)];
364 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
365 [toField setStringValue: relativePathFittingInContainer(fromField, destination)];
366
367 } else if ([operation isEqual: @"NSWorkspaceDuplicateOperation"]) {
368 [win setTitle: NSLocalizedString(@"Duplicate", @"")];
369 [fromLabel setStringValue: NSLocalizedString(@"In:", @"")];
370 [fromField setStringValue: relativePathFittingInContainer(fromField, destination)];
371 [toLabel setStringValue: @""];
372 [toField setStringValue: @""];
373
374 } else if ([operation isEqual: @"NSWorkspaceDestroyOperation"]) {
375 [win setTitle: NSLocalizedString(@"Destroy", @"")];
376 [fromLabel setStringValue: NSLocalizedString(@"In:", @"")];
377 [fromField setStringValue: relativePathFittingInContainer(fromField, destination)];
378 [toLabel setStringValue: @""];
379 [toField setStringValue: @""];
380
381 } else if ([operation isEqual: @"NSWorkspaceRecycleOperation"]) {
382 [win setTitle: NSLocalizedString(@"Move", @"")];
383 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
384 [fromField setStringValue: relativePathFittingInContainer(fromField, source)];
385 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
386 [toField setStringValue: NSLocalizedString(@"the Recycler", @"")];
387
388 } else if ([operation isEqual: @"GWorkspaceRecycleOutOperation"]) {
389 [win setTitle: NSLocalizedString(@"Move", @"")];
390 [fromLabel setStringValue: NSLocalizedString(@"From:", @"")];
391 [fromField setStringValue: NSLocalizedString(@"the Recycler", @"")];
392 [toLabel setStringValue: NSLocalizedString(@"To:", @"")];
393 [toField setStringValue: relativePathFittingInContainer(fromField, destination)];
394
395 } else if ([operation isEqual: @"GWorkspaceEmptyRecyclerOperation"]) {
396 [win setTitle: NSLocalizedString(@"Destroy", @"")];
397 [fromLabel setStringValue: NSLocalizedString(@"In:", @"")];
398 [fromField setStringValue: NSLocalizedString(@"the Recycler", @"")];
399 [toLabel setStringValue: @""];
400 [toField setStringValue: @""];
401 }
402
403 [progInd setMinValue: 0];
404 [progInd setMaxValue: filescount];
405 }
406
407 [win makeKeyAndOrderFront: nil];
408 showwin = YES;
409 }
410
411 - (int)showErrorAlertWithMessage:(NSString *)message
412 {
413 return NSRunAlertPanel(nil, NSLocalizedString(message, @""),
414 NSLocalizedString(@"Continue", @""), nil, nil);
415 }
416
417 - (void)setNumFiles:(int)n
418 {
419 filescount = n;
420 }
421
422 - (void)updateProgressIndicator
423 {
424 [progInd incrementBy: 1.0];
425 }
426
427 - (void)endOperation
428 {
429 DESTROY (executor);
430 if (showwin) {
431 [win saveFrameUsingName: @"fileopprogress"];
432 [win close];
433 }
434 [gw endOfFileOperation: self];
435 }
436
437 - (void)sendWillChangeNotification
438 {
439 NSString *fulldestpath;
440 NSMutableDictionary *dict;
441 int i;
442
443 notifNames = [NSMutableArray new];
444
445 if ([operation isEqual: @"NSWorkspaceDuplicateOperation"]) {
446 for(i = 0; i < [files count]; i++) {
447 NSString *name = [NSString stringWithString: [files objectAtIndex: i]];
448 while(1) {
449 name = [name stringByAppendingString: @"_copy"];
450 fulldestpath = [destination stringByAppendingPathComponent: name];
451 if (![fm fileExistsAtPath: fulldestpath]) {
452 [notifNames addObject: name];
453 break;
454 }
455 }
456 }
457 } else {
458 [notifNames addObjectsFromArray: files];
459 }
460
461 dict = [NSMutableDictionary dictionaryWithCapacity: 1];
462 [dict setObject: operation forKey: @"operation"];
463 [dict setObject: source forKey: @"source"];
464 [dict setObject: destination forKey: @"destination"];
465 [dict setObject: notifNames forKey: @"files"];
466
467 [dnc postNotificationName: GWFileSystemWillChangeNotification
468 object: nil
469 userInfo: dict];
470 }
471
472 - (int)sendDidChangeNotification
473 {
474 NSMutableDictionary *notifObj = [NSMutableDictionary dictionary];
475
476 [notifObj setObject: operation forKey: @"operation"];
477 [notifObj setObject: source forKey: @"source"];
478 [notifObj setObject: destination forKey: @"destination"];
479
480 if (executor) {
481 NSString *procFilesStr = [executor processedFiles];
482
483 if (procFilesStr) {
484 [notifObj setObject: [procFilesStr propertyList] forKey: @"files"];
485 [notifObj setObject: notifNames forKey: @"origfiles"];
486 }
487 } else {
488 [notifObj setObject: notifNames forKey: @"files"];
489 [notifObj setObject: notifNames forKey: @"origfiles"];
490 }
491
492 opdone = YES;
493
494 [dnc postNotificationName: GWFileSystemDidChangeNotification
495 object: nil
496 userInfo: notifObj];
497
498 return 0;
499 }
500
501 - (IBAction)pause:(id)sender
502 {
503 if (executor) {
504 if ([executor isPaused] == NO) {
505 [pauseButt setTitle: NSLocalizedString(@"Continue", @"")];
506 [stopButt setEnabled: NO];
507 [executor Pause];
508 } else {
509 [pauseButt setTitle: NSLocalizedString(@"Pause", @"")];
510 [stopButt setEnabled: YES];
511 [executor performOperation];
512 }
513 }
514 }
515
516 - (IBAction)stop:(id)sender
517 {
518 if (executor) {
519 [executor Stop];
520 }
521 }
522
523 - (int)fileOperationRef
524 {
525 return fileOperationRef;
526 }
527
528 - (NSRect)winRect
529 {
530 if (win && [win isVisible]) {
531 return [win frame];
532 }
533 return NSZeroRect;
534 }
535
536 - (BOOL)showsWindow
537 {
538 return showwin;
539 }
540
541 - (BOOL)connection:(NSConnection*)ancestor
542 shouldMakeNewConnection:(NSConnection*)newConn
543 {
544 if (ancestor == execconn) {
545 [[NSNotificationCenter defaultCenter] addObserver: self
546 selector: @selector(connectionDidDie:)
547 name: NSConnectionDidDieNotification object: newConn];
548 [newConn setDelegate: self];
549 return YES;
550 }
551
552 return NO;
553 }
554
555 - (void)connectionDidDie:(NSNotification *)notification
556 {
557 id conn = [notification object];
558
559 [[NSNotificationCenter defaultCenter] removeObserver: self
560 name: NSConnectionDidDieNotification object: conn];
561
562 if (opdone == NO) {
563 NSString *msg = NSLocalizedString(@"thread connection died!", @"");
564 NSString *buttstr = NSLocalizedString(@"Continue", @"");
565
566 NSRunAlertPanel(nil, msg, buttstr, nil, nil);
567 [self sendDidChangeNotification];
568 [self endOperation];
569 }
570 }
571
572 - (BOOL)windowShouldClose:(id)sender
573 {
574 [win saveFrameUsingName: @"fileopprogress"];
575 return YES;
576 }
577
578 @end
579
580
581 @implementation FileOpExecutor
582
583 + (void)setPorts:(NSArray *)thePorts
584 {
585 NSAutoreleasePool *pool;
586 NSMessagePort *port[2];
587 NSConnection *conn;
588 FileOpExecutor *executor;
589
590 pool = [[NSAutoreleasePool alloc] init];
591
592 port[0] = [thePorts objectAtIndex: 0];
593 port[1] = [thePorts objectAtIndex: 1];
594
595 conn = [NSConnection connectionWithReceivePort: (NSMessagePort *)port[0]
596 sendPort: (NSMessagePort *)port[1]];
597
598 executor = [[self alloc] init];
599 [executor setFileop: thePorts];
600 [(id)[conn rootProxy] registerExecutor: executor];
601 RELEASE (executor);
602
603 [[NSRunLoop currentRunLoop] run];
604 RELEASE (pool);
605 }
606
607 - (void)dealloc
608 {
609 TEST_RELEASE (operation);
610 TEST_RELEASE (source);
611 TEST_RELEASE (destination);
612 TEST_RELEASE (files);
613 TEST_RELEASE (procfiles);
614 [super dealloc];
615 }
616
617 - (id)init
618 {
619 self = [super init];
620
621 if (self) {
622 fm = [NSFileManager defaultManager];
623 stopped = NO;
624 paused = NO;
625 samename = NO;
626 }
627
628 return self;
629 }
630
631 - (void)setFileop:(NSArray *)thePorts
632 {
633 NSMessagePort *port[2];
634 NSConnection *conn;
635 id anObject;
636
637 port[0] = [thePorts objectAtIndex: 0];
638 port[1] = [thePorts objectAtIndex: 1];
639
640 conn = [NSConnection connectionWithReceivePort: (NSMessagePort *)port[0]
641 sendPort: (NSMessagePort *)port[1]];
642
643 anObject = (id)[conn rootProxy];
644 [anObject setProtocolForProxy: @protocol(FileOpProtocol)];
645 fileOp = (id <FileOpProtocol>)anObject;
646 }
647
648 - (BOOL)setOperation:(NSDictionary *)opDict
649 {
650 id dictEntry;
651 int i;
652
653 dictEntry = [opDict objectForKey: @"operation"];
654 if (dictEntry != nil) {
655 ASSIGN (operation, dictEntry);
656 }
657
658 dictEntry = [opDict objectForKey: @"source"];
659 if (dictEntry != nil) {
660 ASSIGN (source, dictEntry);
661 }
662
663 dictEntry = [opDict objectForKey: @"destination"];
664 if (dictEntry != nil) {
665 ASSIGN (destination, dictEntry);
666 }
667
668 files = [NSMutableArray new];
669 dictEntry = [opDict objectForKey: @"files"];
670 if (dictEntry != nil) {
671 for (i = 0; i < [dictEntry count]; i++) {
672 [files addObject: [dictEntry objectAtIndex: i]];
673 }
674 }
675
676 procfiles = [NSMutableArray new];
677
678 return YES;
679 }
680
681 - (BOOL)checkSameName
682 {
683 NSArray *dirContents;
684 int i;
685
686 samename = NO;
687
688 if (destination && [files count]) {
689 dirContents = [fm directoryContentsAtPath: destination];
690 for (i = 0; i < [files count]; i++) {
691 if ([dirContents containsObject: [files objectAtIndex: i]]) {
692 samename = YES;
693 break;
694 }
695 }
696 }
697
698 if (samename) {
699 if (([operation isEqual: NSWorkspaceMoveOperation])
700 || ([operation isEqual: NSWorkspaceCopyOperation])
701 || ([operation isEqual: NSWorkspaceLinkOperation])
702 || ([operation isEqual: NSWorkspaceRecycleOperation])
703 || ([operation isEqual: GWorkspaceRecycleOutOperation])) {
704
705 return YES;
706
707 } else if (([operation isEqual: NSWorkspaceDestroyOperation])
708 || ([operation isEqual: NSWorkspaceDuplicateOperation])
709 || ([operation isEqual: GWorkspaceEmptyRecyclerOperation])) {
710
711 return NO;
712 }
713 }
714
715 return NO;
716 }
717
718 - (oneway void)calculateNumFiles
719 {
720 BOOL isDir;
721 NSDirectoryEnumerator *enumerator;
722 NSString *dirEntry;
723 int i;
724
725 for(i = 0; i < [files count]; i++) {
726 NSString *path = [source stringByAppendingPathComponent: [files objectAtIndex: i]];
727
728 isDir = NO;
729 [fm fileExistsAtPath: path isDirectory: &isDir];
730 if (isDir) {
731 enumerator = [fm enumeratorAtPath: path];
732 while ((dirEntry = [enumerator nextObject])) {
733 fcount++;
734 }
735 } else {
736 fcount++;
737 }
738 }
739
740 [fileOp setNumFiles: fcount];
741 }
742
743 - (oneway void)performOperation
744 {
745 canupdate = YES;
746 stopped = NO;
747 paused = NO;
748 fcount = [files count];
749
750 if ([operation isEqual: NSWorkspaceMoveOperation]
751 || [operation isEqual: NSWorkspaceRecycleOperation]
752 || [operation isEqual: GWorkspaceRecycleOutOperation]) {
753 [self doMove];
754 } else if ([operation isEqual: NSWorkspaceCopyOperation]) {
755 [self doCopy];
756 } else if([operation isEqual: NSWorkspaceLinkOperation]) {
757 [self doLink];
758 } else if([operation isEqual: NSWorkspaceDestroyOperation]
759 || [operation isEqual: GWorkspaceEmptyRecyclerOperation]) {
760 [self doRemove];
761 } else if([operation isEqual: NSWorkspaceDuplicateOperation]) {
762 [self doDuplicate];
763 }
764 }
765
766 - (NSString *)processedFiles
767 {
768 return [procfiles description];
769 }
770
771 #define CHECK_DONE \
772 if (([files count] == 0) || stopped || paused) break
773
774 #define GET_FILENAME filename = [files objectAtIndex: 0]
775
776 #define CHECK_SAME_NAME \
777 if (samename) [self removeExisting: filename]
778
779 #define WAIT \
780 [[NSRunLoop currentRunLoop] \
781 runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]
782
783 - (void)doMove
784 {
785 while (1) {
786 GET_FILENAME;
787 CHECK_SAME_NAME;
788
789 [fm movePath: [source stringByAppendingPathComponent: filename]
790 toPath: [destination stringByAppendingPathComponent: filename]
791 handler: self];
792
793 [procfiles addObject: filename];
794 [files removeObject: filename];
795
796 CHECK_DONE;
797 WAIT;
798 }
799
800 if (([files count] == 0) || stopped) {
801 [self done];
802 }
803 }
804
805 - (void)doCopy
806 {
807 while (1) {
808 GET_FILENAME;
809 CHECK_SAME_NAME;
810
811 [fm copyPath: [source stringByAppendingPathComponent: filename]
812 toPath: [destination stringByAppendingPathComponent: filename]
813 handler: self];
814
815 [procfiles addObject: filename];
816 [files removeObject: filename];
817
818 CHECK_DONE;
819 WAIT;
820 }
821
822 if (([files count] == 0) || stopped) {
823 [self done];
824 }
825 }
826
827 - (void)doLink
828 {
829 while (1) {
830 GET_FILENAME;
831 CHECK_SAME_NAME;
832
833 [fm linkPath: [source stringByAppendingPathComponent: filename]
834 toPath: [destination stringByAppendingPathComponent: filename]
835 handler: self];
836
837 [procfiles addObject: filename];
838 [files removeObject: filename];
839
840 CHECK_DONE;
841 WAIT;
842 }
843
844 if (([files count] == 0) || stopped) {
845 [self done];
846 }
847 }
848
849 - (void)doRemove
850 {
851 while (1) {
852 GET_FILENAME;
853
854 [fm removeFileAtPath: [destination stringByAppendingPathComponent: filename]
855 handler: self];
856
857 [procfiles addObject: filename];
858 [files removeObject: filename];
859
860 CHECK_DONE;
861 WAIT;
862 }
863
864 if (([files count] == 0) || stopped) {
865 [self done];
866 }
867 }
868
869 - (void)doDuplicate
870 {
871 NSString *fulldestpath;
872 NSString *newname;
873
874 while (1) {
875 GET_FILENAME;
876
877 newname = [NSString stringWithString: filename];
878
879 while (1) {
880 newname = [newname stringByAppendingString: @"_copy"];
881 fulldestpath = [destination stringByAppendingPathComponent: newname];
882
883 if (![fm fileExistsAtPath: fulldestpath]) {
884 break;
885 }
886 }
887
888 [fm copyPath: [destination stringByAppendingPathComponent: filename]
889 toPath: fulldestpath
890 handler: self];
891
892 [procfiles addObject: newname];
893 [files removeObject: filename];
894
895 CHECK_DONE;
896 WAIT;
897 }
898
899 if (([files count] == 0) || stopped) {
900 [self done];
901 }
902 }
903
904 - (void)removeExisting:(NSString *)fname
905 {
906 NSString *fulldestpath;
907
908 canupdate = NO;
909 fulldestpath = [destination stringByAppendingPathComponent: fname];
910
911 if ([fm fileExistsAtPath: fulldestpath]) {
912 [fm removeFileAtPath: fulldestpath handler: self];
913 }
914 canupdate = YES;
915 }
916
917 - (void)Pause
918 {
919 paused = YES;
920 }
921
922 - (void)Stop
923 {
924 stopped = YES;
925 }
926
927 - (BOOL)isPaused
928 {
929 return paused;
930 }
931
932 - (void)done
933 {
934 [fileOp sendDidChangeNotification];
935 [fileOp endOperation];
936 }
937
938 - (BOOL)fileManager:(NSFileManager *)manager
939 shouldProceedAfterError:(NSDictionary *)errorDict
940 {
941 NSString *path, *msg;
942 BOOL iserror = NO;
943 int result;
944
945 path = [errorDict objectForKey: @"Path"];
946
947 msg = [NSString stringWithFormat: @"%@ %@\n%@ %@\n",
948 NSLocalizedString(@"File operation error:", @""),
949 [errorDict objectForKey: @"Error"],
950 NSLocalizedString(@"with file:", @""),
951 path];
952
953 result = [fileOp requestUserConfirmationWithMessage: msg title: @"Error"];
954
955 if(result != NSAlertDefaultReturn) {
956 [fileOp sendDidChangeNotification];
957 [fileOp endOperation];
958
959 } else {
960 NSString *fname = [path lastPathComponent];
961 BOOL found = NO;
962
963 while (1) {
964 if ([path isEqualToString: source] == YES) {
965 break;
966 }
967
968 if ([files containsObject: fname] == YES) {
969 [files removeObject: fname];
970 found = YES;
971 break;
972 }
973
974 path = [path stringByDeletingLastPathComponent];
975 fname = [path lastPathComponent];
976 }
977
978 if (found == YES) {
979 [self performOperation];
980 } else {
981 result = [fileOp showErrorAlertWithMessage: @"File Operation Error!"];
982 [fileOp sendDidChangeNotification];
983 [fileOp endOperation];
984 return NO;
985 }
986 }
987
988 return !iserror;
989 }
990
991 - (void)fileManager:(NSFileManager *)manager willProcessPath:(NSString *)path
992 {
993 if (canupdate) {
994 [fileOp updateProgressIndicator];
995 }
996 }
997
998 @end

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26