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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (show annotations) (download)
Mon Sep 29 13:20:29 2003 UTC (20 years, 6 months ago) by esersale
Branch: MAIN
Changes since 1.13: +126 -195 lines
*** empty log message ***

1 /* GWorkspace.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 #include <math.h>
28 #ifdef GNUSTEP
29 #include "GWLib.h"
30 #include "GWFunctions.h"
31 #include "GWNotifications.h"
32 #include "ViewersProtocol.h"
33 #else
34 #include <GWorkspace/GWLib.h>
35 #include <GWorkspace/GWFunctions.h>
36 #include <GWorkspace/GWNotifications.h>
37 #include <GWorkspace/ViewersProtocol.h>
38 #endif
39 #include "GWorkspace.h"
40 #include "Watchers/Watcher.h"
41 #include "FileOperations/FileOperation.h"
42 #include "Dialogs/Dialogs.h"
43 #include "Dialogs/OpenWithController.h"
44 #include "Dialogs/RunExternalController.h"
45 #include "Inspectors/InspectorsController.h"
46 #include "Apps/Apps.h"
47 #include "Finder/FinderController.h"
48 #include "Preferences/PrefController.h"
49 #include "Fiend/Fiend.h"
50 #include "ViewersWindow.h"
51 #include "Desktop/DesktopWindow.h"
52 #include "Desktop/DesktopView.h"
53 #include "TShelf/TShelfWin.h"
54 #include "Recycler/Recycler.h"
55 #include "History/History.h"
56 #include "GNUstep.h"
57
58 NSString *defaulteditor = @"nedit.app";
59 NSString *defaultxterm = @"xterm";
60
61 NSFileManager *fmanager = nil;
62
63 static GWorkspace *gworkspace = nil;
64
65 @implementation GWorkspace
66
67 #ifndef byname
68 #define byname 0
69 #define bykind 1
70 #define bydate 2
71 #define bysize 3
72 #define byowner 4
73 #endif
74
75 #ifndef CACHED_MAX
76 #define CACHED_MAX 20;
77 #endif
78
79 //
80 // GWProtocol
81 //
82 + (GWorkspace *)gworkspace
83 {
84 if (gworkspace == nil) {
85 gworkspace = [[GWorkspace alloc] init];
86 }
87 return gworkspace;
88 }
89
90 - (BOOL)performFileOperation:(NSString *)operation
91 source:(NSString *)source
92 destination:(NSString *)destination
93 files:(NSArray *)files
94 tag:(int *)tag
95 {
96 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
97 NSString *confirmString = [operation stringByAppendingString: @"Confirm"];
98 BOOL confirm = !([defaults boolForKey: confirmString]);
99 NSRect scr = [[NSScreen mainScreen] visibleFrame];
100 NSRect wrect = NSZeroRect;
101 FileOperation *op;
102 NSRect wr;
103 int i;
104
105 #define WMARGIN 50
106 #define WSHIFT 10
107
108 scr.origin.x += WMARGIN;
109 scr.origin.y += WMARGIN;
110 scr.size.width -= (WMARGIN * 2);
111 scr.size.height -= (WMARGIN * 2);
112
113 for (i = 0; i < [operations count]; i++) {
114 op = [operations objectAtIndex: i];
115 wr = [op winRect];
116
117 if (NSEqualRects(wr, NSZeroRect) == NO) {
118 wrect = NSMakeRect(wr.origin.x + WSHIFT,
119 wr.origin.y - wr.size.height - WSHIFT,
120 wr.size.width,
121 wr.size.height);
122
123 if (NSContainsRect(scr, wrect) == NO) {
124 wrect = NSMakeRect(scr.origin.x,
125 scr.size.height - wr.size.height,
126 wr.size.width,
127 wr.size.height);
128 break;
129 }
130 }
131 }
132
133 op = [[FileOperation alloc] initWithOperation: operation
134 source: source
135 destination: destination
136 files: files
137 useConfirmation: confirm
138 showWindow: showFileOpStatus
139 windowRect: wrect];
140 [operations addObject: op];
141 RELEASE (op);
142
143 return YES;
144 }
145
146 - (void)performFileOperationWithDictionary:(id)opdict
147 {
148 NSString *operation = [opdict objectForKey: @"operation"];
149 NSString *source = [opdict objectForKey: @"source"];
150 NSString *destination = [opdict objectForKey: @"destination"];
151 NSArray *files = [opdict objectForKey: @"files"];
152 int tag;
153
154 [self performFileOperation: operation source: source
155 destination: destination files: files tag: &tag];
156 }
157
158 - (BOOL)application:(NSApplication *)theApplication
159 openFile:(NSString *)filename
160 {
161 BOOL isDir;
162
163 if ([filename isAbsolutePath]
164 && [fm fileExistsAtPath: filename isDirectory: &isDir]) {
165 if (isDir) {
166 id viewer = [self newViewerAtPath: filename
167 canViewApps: [self isPakageAtPath: filename]];
168 [viewer orderFrontRegardless];
169 return YES;
170 } else {
171 [self selectFile: filename
172 inFileViewerRootedAtPath: [filename stringByDeletingLastPathComponent]];
173 [self openFile: filename];
174 return YES;
175 }
176 }
177
178 return NO;
179 }
180
181 - (BOOL)openFile:(NSString *)fullPath
182 {
183 NSPoint p = [currentViewer locationOfIconForPath: fullPath];
184 NSView *aview = [currentViewer viewer];
185 NSImage *image;
186 NSString *defApp;
187 NSString *type;
188
189 [ws getInfoForFile: fullPath application: &defApp type: &type];
190 image = [self iconForFile: fullPath ofType: type];
191
192 return [self openFile: fullPath fromImage: image at: p inView: aview];
193 }
194
195 - (BOOL)openFile:(NSString *)fullPath
196 fromImage:(NSImage *)anImage
197 at:(NSPoint)point
198 inView:(NSView *)aView
199 {
200 NSString *appName;
201 NSString *type;
202 id fiendLeaf;
203 id app;
204 NSPoint toPoint;
205 BOOL dissolved;
206
207 #define RETURN_OPEN \
208 return [ws openFile: fullPath withApplication: appName]
209
210 [ws getInfoForFile: fullPath application: &appName type: &type];
211
212 if (appName == nil) {
213 appName = defEditor;
214 }
215
216 if (animateLaunck == NO) RETURN_OPEN;
217
218 if ((fiend == nil) || ([[fiend myWin] isVisible] == NO)) RETURN_OPEN;
219
220 fiendLeaf = [fiend fiendLeafOfType: NSApplicationFileType withName: appName];
221 if (fiendLeaf == nil) RETURN_OPEN;
222
223 app = [self connectApplication: appName];
224 if (app == nil) {
225 dissolved = [fiend dissolveLeaf: fiendLeaf];
226 }
227
228 if (point.x <= 0 || point.y <= 0) RETURN_OPEN;
229
230 toPoint = [fiend positionOfLeaf: fiendLeaf];
231 if (toPoint.x <= 0 || toPoint.y <= 0) RETURN_OPEN;
232
233 point = [[aView window] convertBaseToScreen: point];
234 [self slideImage: anImage from: point to: toPoint];
235
236 RETURN_OPEN;
237 }
238
239 - (BOOL)selectFile:(NSString *)fullPath
240 inFileViewerRootedAtPath:(NSString *)rootFullpath
241 {
242 NSArray *paths;
243 int l1, l2;
244 BOOL isdirRoot, isdirFpath;
245 BOOL newViewer = YES;
246
247 if ([fm fileExistsAtPath: fullPath isDirectory: &isdirFpath] == NO) {
248 return NO;
249 }
250
251 if ((rootFullpath == nil) || ([rootFullpath length] == 0)) {
252 newViewer = NO;
253 } else if (([fm fileExistsAtPath: rootFullpath isDirectory: &isdirRoot] && isdirRoot) == NO) {
254 return NO;
255 }
256
257 l1 = [rootFullpath length];
258 l2 = [fullPath length];
259
260 if ((l1 > l2) || ((l1 == l2) && (isdirFpath == NO))) {
261 return NO;
262 }
263
264 if (newViewer) {
265 if ([[fullPath substringToIndex: l1] isEqualToString: rootFullpath] == NO) {
266 return NO;
267 }
268 }
269
270 paths = [NSArray arrayWithObject: fullPath];
271
272 if (newViewer) {
273 ViewersWindow *viewer = [self viewerRootedAtPath: rootFullpath];
274
275 if ((viewer == nil) || ([rootFullpath isEqual: fixPath(@"/", 0)])) {
276 NSString *app, *type;
277 [ws getInfoForFile: rootFullpath application: &app type: &type];
278 viewer = [self newViewerAtPath: rootFullpath canViewApps: (type == NSApplicationFileType)];
279 }
280
281 [viewer setViewerSelection: paths];
282 [viewer orderFrontRegardless];
283 } else {
284 [self setSelectedPaths: paths];
285 [rootViewer setViewerSelection: paths];
286 }
287
288 return YES;
289 }
290
291 - (void)rootViewerSelectFiles:(NSArray *)paths
292 {
293 [rootViewer makeKeyAndOrderFront: nil];
294 [self setSelectedPaths: paths];
295 [rootViewer setViewerSelection: paths];
296 }
297
298 - (void)slideImage:(NSImage *)image
299 from:(NSPoint)fromPoint
300 to:(NSPoint)toPoint
301 {
302 [[NSWorkspace sharedWorkspace] slideImage: image from: fromPoint to: toPoint];
303 }
304
305 - (void)noteFileSystemChanged
306 {
307
308 }
309
310 - (void)noteFileSystemChanged:(NSString *)path
311 {
312
313 }
314
315 - (BOOL)existsAndIsDirectoryFileAtPath:(NSString *)path
316 {
317 BOOL isDir;
318 return ([fm fileExistsAtPath: path isDirectory: &isDir] && isDir);
319 }
320
321 - (NSString *)typeOfFileAt:(NSString *)path
322 {
323 NSString *defApp, *type;
324 [ws getInfoForFile: path application: &defApp type: &type];
325 return type;
326 }
327
328 - (BOOL)isWritableFileAtPath:(NSString *)path
329 {
330 return [fm isWritableFileAtPath: path];
331 }
332
333 - (BOOL)isPakageAtPath:(NSString *)path
334 {
335 NSString *defApp, *type;
336 BOOL isdir;
337
338 [ws getInfoForFile: path application: &defApp type: &type];
339
340 if (type == NSApplicationFileType) {
341 return YES;
342 } else if (type == NSPlainFileType) {
343 if ((([fm fileExistsAtPath: path isDirectory: &isdir]) && isdir)) {
344 return YES;
345 }
346 }
347
348 return NO;
349 }
350
351 - (NSArray *)sortedDirectoryContentsAtPath:(NSString *)path
352 {
353 NSMutableDictionary *contentsDict = [self cachedRepresentationForPath: path];
354
355 if (contentsDict) {
356 return [contentsDict objectForKey: @"files"];
357
358 } else {
359 NSArray *files = [fm directoryContentsAtPath: path];
360 int stype = [self sortTypeForDirectoryAtPath: path];
361 int count = [files count];
362 NSMutableArray *paths = [NSMutableArray arrayWithCapacity: count];
363 NSMutableArray *sortfiles = [NSMutableArray arrayWithCapacity: count];
364 NSArray *sortPaths = nil;
365 NSDictionary *attributes = nil;
366 NSDate *date = nil;
367 SEL appendPathCompSel = @selector(stringByAppendingPathComponent:);
368 IMP appendPathComp = [[NSString class] instanceMethodForSelector: appendPathCompSel];
369 SEL lastPathCompSel = @selector(lastPathComponent);
370 IMP lastPathComp = [[NSString class] instanceMethodForSelector: lastPathCompSel];
371 int i;
372
373 for (i = 0; i < count; i++) {
374 NSString *s = (*appendPathComp)(path, appendPathCompSel, [files objectAtIndex: i]);
375 [paths addObject: s];
376 }
377
378 sortPaths = [paths sortedArrayUsingFunction: (int (*)(id, id, void*))comparePaths
379 context: (void *)stype];
380
381 for (i = 0; i < count; i++) {
382 NSString *s = (*lastPathComp)([sortPaths objectAtIndex: i], lastPathCompSel);
383 [sortfiles addObject: s];
384 }
385
386 contentsDict = [NSMutableDictionary dictionary];
387 [contentsDict setObject: [NSDate date] forKey: @"datestamp"];
388 attributes = [fm fileAttributesAtPath: path traverseLink: YES];
389 date = [attributes fileModificationDate];
390 [contentsDict setObject: date forKey: @"moddate"];
391 [contentsDict setObject: sortfiles forKey: @"files"];
392
393 if ([cachedContents count] >= cachedMax) {
394 [self removeOlderCache];
395 }
396
397 [self addCachedRepresentation: contentsDict ofDirectory: path];
398
399 return sortfiles;
400 }
401
402 return nil;
403 }
404
405 - (NSArray *)checkHiddenFiles:(NSArray *)files atPath:(NSString *)path
406 {
407 NSArray *checkedFiles;
408 NSArray *hiddenFiles;
409 NSString *h;
410
411 h = [path stringByAppendingPathComponent: @".hidden"];
412 if ([fm fileExistsAtPath: h]) {
413 h = [NSString stringWithContentsOfFile: h];
414 hiddenFiles = [h componentsSeparatedByString: @"\n"];
415 } else {
416 hiddenFiles = nil;
417 }
418
419 if (hiddenFiles != nil || hideSysFiles) {
420 NSMutableArray *mutableFiles = AUTORELEASE ([files mutableCopy]);
421
422 if (hiddenFiles != nil) {
423 [mutableFiles removeObjectsInArray: hiddenFiles];
424 }
425
426 if (hideSysFiles) {
427 int j = [mutableFiles count] - 1;
428
429 while (j >= 0) {
430 NSString *file = (NSString *)[mutableFiles objectAtIndex: j];
431
432 if ([file hasPrefix: @"."]) {
433 [mutableFiles removeObjectAtIndex: j];
434 }
435 j--;
436 }
437 }
438
439 checkedFiles = mutableFiles;
440
441 } else {
442 checkedFiles = files;
443 }
444
445 return checkedFiles;
446 }
447
448 - (int)sortTypeForDirectoryAtPath:(NSString *)aPath
449 {
450 if ([fm isWritableFileAtPath: aPath]) {
451 NSString *dictPath = [aPath stringByAppendingPathComponent: @".gwsort"];
452
453 if ([fm fileExistsAtPath: dictPath]) {
454 NSDictionary *sortDict = [NSDictionary dictionaryWithContentsOfFile: dictPath];
455
456 if (sortDict) {
457 return [[sortDict objectForKey: @"sort"] intValue];
458 }
459 }
460 }
461
462 return defSortType;
463 }
464
465 - (void)setSortType:(int)type forDirectoryAtPath:(NSString *)aPath
466 {
467 if ([fm isWritableFileAtPath: aPath]) {
468 NSString *sortstr = [NSString stringWithFormat: @"%i", type];
469 NSDictionary *dict = [NSDictionary dictionaryWithObject: sortstr
470 forKey: @"sort"];
471 [dict writeToFile: [aPath stringByAppendingPathComponent: @".gwsort"]
472 atomically: YES];
473 }
474
475 [self removeCachedRepresentationForPath: aPath];
476
477 [[NSNotificationCenter defaultCenter]
478 postNotificationName: GWSortTypeDidChangeNotification
479 object: (id)aPath];
480 }
481
482 - (void)openSelectedPaths:(NSArray *)paths newViewer:(BOOL)newv
483 {
484 NSString *apath;
485 NSString *defApp, *type;
486 int i;
487
488 [self setSelectedPaths: paths];
489
490 for (i = 0; i < [paths count]; i++) {
491 apath = [paths objectAtIndex: i];
492
493 [ws getInfoForFile: apath application: &defApp type: &type];
494
495 if ((type == NSDirectoryFileType) || (type == NSFilesystemFileType)) {
496 if (newv) {
497 [self newViewerAtPath: apath canViewApps: NO];
498 }
499 } else if ((type == NSPlainFileType)
500 || ([type isEqual: NSShellCommandFileType])) {
501 if ([self isPakageAtPath: apath]) {
502 if (newv) {
503 [self newViewerAtPath: apath canViewApps: YES];
504 } else {
505 [self openFile: apath];
506 }
507 } else {
508 [self openFile: apath];
509 }
510 } else if (type == NSApplicationFileType) {
511 if (newv) {
512 [self newViewerAtPath: apath canViewApps: YES];
513 } else {
514 [ws launchApplication: apath];
515 }
516 }
517 }
518 }
519
520 - (void)openSelectedPathsWith
521 {
522 BOOL found = NO;
523 int i;
524
525 for (i = 0; i < [selectedPaths count]; i++) {
526 NSString *spath = [selectedPaths objectAtIndex: i];
527 NSDictionary *attributes = [fm fileAttributesAtPath: spath traverseLink: YES];
528
529 if ([attributes objectForKey: NSFileType] != NSFileTypeDirectory) {
530 NSString *defApp, *fileType;
531
532 [ws getInfoForFile: spath application: &defApp type: &fileType];
533
534 if((fileType != NSPlainFileType) && (fileType != NSShellCommandFileType)) {
535 found = YES;
536 }
537
538 } else {
539 found = YES;
540 }
541
542 if (found) {
543 break;
544 }
545 }
546
547 if (found == NO) {
548 [openWithController activate];
549 }
550 }
551
552 - (ViewersWindow *)newViewerAtPath:(NSString *)path canViewApps:(BOOL)viewapps
553 {
554 ViewersWindow *viewer = [[ViewersWindow alloc] initWithViewerTemplates: viewersTemplates
555 forPath: path viewPakages: viewapps
556 isRootViewer: NO onStart: starting];
557 [viewer activate];
558 [viewers addObject: viewer];
559 RELEASE (viewer);
560
561 return [viewers objectAtIndex: [viewers count] -1];
562 }
563
564 - (NSImage *)iconForFile:(NSString *)fullPath ofType:(NSString *)type
565 {
566 NSImage *icon;
567 NSSize size;
568
569 if (usesThumbnails) {
570 icon = [self thumbnailForPath: fullPath];
571
572 if (icon) {
573 return icon;
574 }
575 }
576
577 icon = [ws iconForFile: fullPath];
578 size = [icon size];
579
580 if ((size.width > ICNMAX) || (size.height > ICNMAX)) {
581 NSSize newsize;
582
583 if (size.width >= size.height) {
584 newsize.width = ICNMAX;
585 newsize.height = floor(ICNMAX * size.height / size.width + 0.5);
586 } else {
587 newsize.height = ICNMAX;
588 newsize.width = floor(ICNMAX * size.width / size.height + 0.5);
589 }
590
591 [icon setScalesWhenResized: YES];
592 [icon setSize: newsize];
593 }
594
595 return icon;
596 }
597
598 - (NSImage *)smallIconForFile:(NSString*)aPath
599 {
600 NSImage *icon = [[self iconForFile: aPath ofType: nil] copy];
601 NSSize size = [icon size];
602 [icon setScalesWhenResized: YES];
603 [icon setSize: NSMakeSize(size.width / 2, size.height / 2)];
604
605 return AUTORELEASE (icon);
606 }
607
608 - (NSImage *)smallIconForFiles:(NSArray*)pathArray
609 {
610 NSImage *icon = [NSImage imageNamed: @"MultipleSelection.tiff"];
611 NSSize size = [icon size];
612 [icon setScalesWhenResized: YES];
613 [icon setSize: NSMakeSize(size.width / 2, size.height / 2)];
614
615 return icon;
616 }
617
618 - (NSImage *)smallHighlightIcon
619 {
620 return [NSImage imageNamed: @"SmallCellHighlightSmall.tiff"];
621 }
622
623 - (NSArray *)getSelectedPaths
624 {
625 return selectedPaths;
626 }
627
628 - (NSString *)trashPath
629 {
630 return trashPath;
631 }
632
633 - (NSArray *)viewersSearchPaths
634 {
635 return viewersSearchPaths;
636 }
637
638 - (NSArray *)imageExtensions
639 {
640 return [NSArray arrayWithObjects: @"tiff", @"tif", @"TIFF", @"TIF",
641 @"png", @"PNG", @"jpeg", @"jpg",
642 @"JPEG", @"JPG", @"gif", @"GIF",
643 @"xpm", nil];
644 }
645
646 - (void)lockFiles:(NSArray *)files inDirectoryAtPath:(NSString *)path
647 {
648 int i;
649
650 for (i = 0; i < [files count]; i++) {
651 NSString *file = [files objectAtIndex: i];
652 NSString *fpath = [path stringByAppendingPathComponent: file];
653
654 if ([lockedPaths containsObject: fpath] == NO) {
655 [lockedPaths addObject: fpath];
656 }
657 }
658 }
659
660 - (void)unLockFiles:(NSArray *)files inDirectoryAtPath:(NSString *)path
661 {
662 int i;
663
664 for (i = 0; i < [files count]; i++) {
665 NSString *file = [files objectAtIndex: i];
666 NSString *fpath = [path stringByAppendingPathComponent: file];
667
668 if ([lockedPaths containsObject: fpath]) {
669 [lockedPaths removeObject: fpath];
670 }
671 }
672 }
673
674 - (BOOL)isLockedPath:(NSString *)path
675 {
676 int i;
677
678 if ([lockedPaths containsObject: path]) {
679 return YES;
680 }
681
682 for (i = 0; i < [lockedPaths count]; i++) {
683 NSString *lpath = [lockedPaths objectAtIndex: i];
684
685 if (subPathOfPath(lpath, path)) {
686 return YES;
687 }
688 }
689
690 return NO;
691 }
692
693 - (void)addWatcherForPath:(NSString *)path
694 {
695 Watcher *watcher = [self watcherForPath: path];
696
697 if ((watcher != nil) && ([watcher isOld] == NO)) {
698 [watcher addListener];
699 return;
700 } else {
701 BOOL isdir;
702
703 if ([fm fileExistsAtPath: path isDirectory: &isdir] && isdir) {
704 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
705 target: self selector: @selector(watcherTimeOut:)
706 userInfo: path repeats: YES];
707 [watchTimers addObject: timer];
708
709 watcher = [[Watcher alloc] initForWatchAtPath: path];
710 [watchers addObject: watcher];
711 RELEASE (watcher);
712 }
713 }
714 }
715
716 - (void)removeWatcherForPath:(NSString *)path
717 {
718 Watcher *watcher = [self watcherForPath: path];
719
720 if ((watcher != nil) && ([watcher isOld] == NO)) {
721 [watcher removeListener];
722 }
723 }
724
725 - (BOOL)hideSysFiles
726 {
727 return hideSysFiles;
728 }
729
730 - (BOOL)animateChdir
731 {
732 return animateChdir;
733 }
734
735 - (BOOL)animateLaunck
736 {
737 return animateLaunck;
738 }
739
740 - (BOOL)animateSlideBack
741 {
742 return animateSlideBack;
743 }
744
745 - (BOOL)usesContestualMenu
746 {
747 return contestualMenu;
748 }
749 //
750 // end of GWProtocol
751 //
752
753 + (void)initialize
754 {
755 static BOOL initialized = NO;
756
757 if (initialized == YES) {
758 return;
759 }
760
761 initialized = YES;
762 }
763
764 + (void)registerForServices
765 {
766 NSArray *sendTypes = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
767 NSArray *returnTypes = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
768 [NSApp registerServicesMenuSendTypes: sendTypes returnTypes: returnTypes];
769 }
770
771 - (void)dealloc
772 {
773 [[NSDistributedNotificationCenter defaultCenter] removeObserver: self];
774 [[NSNotificationCenter defaultCenter] removeObserver: self];
775 RELEASE (defEditor);
776 RELEASE (defXterm);
777 RELEASE (defXtermArgs);
778 RELEASE (selectedPaths);
779 TEST_RELEASE (rootViewer);
780 RELEASE (viewers);
781 TEST_RELEASE (viewersTemplates);
782 TEST_RELEASE (viewersSearchPaths);
783 TEST_RELEASE (inspController);
784 TEST_RELEASE (appsViewer);
785 TEST_RELEASE (finder);
786 TEST_RELEASE (fiend);
787 TEST_RELEASE (history);
788 TEST_RELEASE (recycler);
789 RELEASE (openWithController);
790 RELEASE (runExtController);
791 RELEASE (trashPath);
792 RELEASE (lockedPaths);
793 RELEASE (watchers);
794 RELEASE (watchTimers);
795 RELEASE (watchedPaths);
796 RELEASE (thumbnailDir);
797 TEST_RELEASE (tumbsCache);
798 RELEASE (cachedContents);
799 RELEASE (operations);
800 TEST_RELEASE (desktopWindow);
801 TEST_RELEASE (tshelfWin);
802 TEST_RELEASE (tshelfBackground);
803 [super dealloc];
804 }
805
806 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
807 {
808 NSUserDefaults *defaults;
809 NSString *processName;
810 NSMutableArray *viewersPaths;
811 NSString *path;
812 id result;
813 NSArray *keys;
814 NSMutableDictionary *viewersPrefs;
815 BOOL isdir;
816 int i, count;
817
818 [isa registerForServices];
819
820 fmanager = [NSFileManager defaultManager];
821 fm = [NSFileManager defaultManager];
822 ws = [NSWorkspace sharedWorkspace];
823
824 defaults = [NSUserDefaults standardUserDefaults];
825 processName = [[NSProcessInfo processInfo] processName];
826 [defaults setObject: processName forKey: @"GSWorkspaceApplication"];
827
828 result = [defaults stringForKey: @"defaulteditor"];
829 if (result == nil) {
830 defEditor = [[NSString alloc] initWithString: defaulteditor];
831 } else {
832 ASSIGN (defEditor, result);
833 }
834
835 result = [defaults stringForKey: @"defxterm"];
836 if (result == nil) {
837 defXterm = [[NSString alloc] initWithString: defaultxterm];
838 } else {
839 ASSIGN (defXterm, result);
840 }
841
842 result = [defaults stringForKey: @"defaultxtermargs"];
843 if (result == nil) {
844 defXtermArgs = nil;
845 } else {
846 ASSIGN (defXtermArgs, result);
847 }
848
849 result = [defaults objectForKey: @"shelfcellswidth"];
850 if (result == nil) {
851 shelfCellsWidth = 90;
852 } else {
853 shelfCellsWidth = [result intValue];
854 }
855
856 result = [defaults objectForKey: @"defaultsorttype"];
857 if (result == nil) {
858 [defaults setObject: @"0" forKey: @"defaultsorttype"];
859 defSortType = byname;
860 } else {
861 defSortType = [result intValue];
862 }
863
864 showFileOpStatus = [defaults boolForKey: @"showfopstatus"];
865
866 result = [defaults objectForKey: @"GSFileBrowserHideDotFiles"];
867 if (result) {
868 hideSysFiles = [result boolValue];
869 } else {
870 NSDictionary *domain = [defaults persistentDomainForName: NSGlobalDomain];
871
872 result = [domain objectForKey: @"GSFileBrowserHideDotFiles"];
873 if (result) {
874 hideSysFiles = [result boolValue];
875 } else {
876 hideSysFiles = NO;
877 }
878 }
879
880 animateChdir = ![defaults boolForKey: @"nochdiranim"];
881 animateLaunck = ![defaults boolForKey: @"nolaunchanim"];
882 animateSlideBack = ![defaults boolForKey: @"noslidebackanim"];
883
884 contestualMenu = [defaults boolForKey: @"UsesContestualMenu"];
885
886 thumbnailDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
887 thumbnailDir = [thumbnailDir stringByAppendingPathComponent: @"Thumbnails"];
888 RETAIN (thumbnailDir);
889
890 if (([fm fileExistsAtPath: thumbnailDir isDirectory: &isdir] && isdir) == NO) {
891 [fm createDirectoryAtPath: thumbnailDir attributes: nil];
892 }
893
894 usesThumbnails = [defaults boolForKey: @"usesthumbnails"];
895 if (usesThumbnails) {
896 [self prepareThumbnailsCache];
897 }
898
899 result = [defaults dictionaryForKey: @"viewersprefs"];
900 if (result) {
901 viewersPrefs = [result mutableCopy];
902 } else {
903 viewersPrefs = [[NSMutableDictionary alloc] initWithCapacity: 1];
904 }
905 keys = [viewersPrefs allKeys];
906 for (i = 0; i < [keys count]; i++) {
907 BOOL exists, isdir;
908 NSString *key = [keys objectAtIndex: i];
909
910 if ([key isEqual: @"rootViewer"] == NO) {
911 exists = [fm fileExistsAtPath: key isDirectory: &isdir];
912 if((exists == NO) || (isdir == NO)) {
913 [viewersPrefs removeObjectForKey: key];
914 }
915 }
916 }
917 [defaults setObject: viewersPrefs forKey: @"viewersprefs"];
918 RELEASE (viewersPrefs);
919
920 result = [defaults objectForKey: @"viewerspaths"];
921 if (result == nil) {
922 viewersPaths = [NSMutableArray new];
923 } else {
924 viewersPaths = [result mutableCopy];
925 }
926 count = [viewersPaths count];
927 for (i = 0; i < count; i++) {
928 BOOL exists, isdir;
929 NSString *path = [viewersPaths objectAtIndex: i];
930 exists = [fm fileExistsAtPath: path isDirectory: &isdir];
931 if((exists == NO) || (isdir == NO)) {
932 [viewersPaths removeObjectAtIndex: i];
933 i--;
934 count--;
935 }
936 }
937 [defaults setObject: viewersPaths forKey: @"viewerspaths"];
938 RELEASE (viewersPaths);
939
940 watchers = [[NSMutableArray alloc] initWithCapacity: 1];
941 watchTimers = [[NSMutableArray alloc] initWithCapacity: 1];
942 watchedPaths = [NSMutableArray new];
943 selectedPaths = [[NSArray alloc] initWithObjects: NSHomeDirectory(), nil];
944
945 operations = [NSMutableArray new];
946 oprefnum = 0;
947
948 appsViewer = [[AppsViewer alloc] init];
949 history = [[History alloc] init];
950 prefController = [[PrefController alloc] init];
951 inspController = nil;
952 finder = nil;
953 fiend = nil;
954
955 tshelfBackground = nil;
956 [self showHideDesktop: [defaults boolForKey: @"desktop"]];
957
958 if ([defaults boolForKey: @"usefiend"]) {
959 [self showFiend: nil];
960 } else {
961 [self hideFiend: nil];
962 }
963
964 if ([defaults boolForKey: @"tshelf"]) {
965 [self showTShelf: nil];
966 } else {
967 [self hideTShelf: nil];
968 }
969
970 [self createRecycler];
971
972 openWithController = [[OpenWithController alloc] init];
973 runExtController = [[RunExternalController alloc] init];
974
975 lockedPaths = [[NSMutableArray alloc] initWithCapacity: 1];
976
977 starting = YES;
978 viewers = [[NSMutableArray alloc] initWithCapacity: 1];
979 viewersSearchPaths = [[NSMutableArray alloc] initWithCapacity: 1];
980 [self makeViewersTemplates];
981
982 rootViewer = nil;
983 [self showViewer: nil];
984
985 viewersPaths = [defaults objectForKey: @"viewerspaths"];
986 for (i = 0; i < [viewersPaths count]; i++) {
987 path = [viewersPaths objectAtIndex: i];
988 [self newViewerAtPath: path
989 canViewApps: ([self isPakageAtPath: path] ? YES : NO)];
990 }
991
992 cachedContents = [NSMutableDictionary new];
993
994 result = [defaults objectForKey: @"cachedmax"];
995 if (result) {
996 cachedMax = [result intValue];
997 } else {
998 cachedMax = CACHED_MAX;
999 [defaults setObject: [NSNumber numberWithInt: cachedMax] forKey: @"cachedmax"];
1000 }
1001
1002 starting = NO;
1003
1004 [defaults synchronize];
1005
1006 [[NSDistributedNotificationCenter defaultCenter] addObserver: self
1007 selector: @selector(fileSystemWillChangeNotification:)
1008 name: GWFileSystemWillChangeNotification
1009 object: nil];
1010
1011 [[NSDistributedNotificationCenter defaultCenter] addObserver: self
1012 selector: @selector(fileSystemDidChangeNotification:)
1013 name: GWFileSystemDidChangeNotification
1014 object: nil];
1015
1016 [[NSNotificationCenter defaultCenter] addObserver: self
1017 selector: @selector(iconAnimationChanged:)
1018 name: GWIconAnimationChangedNotification
1019 object: nil];
1020
1021 [[NSDistributedNotificationCenter defaultCenter] addObserver: self
1022 selector: @selector(setHideDotFiles:)
1023 name: GSHideDotFilesDidChangeNotification
1024 object: nil];
1025
1026 [[NSDistributedNotificationCenter defaultCenter] addObserver: self
1027 selector: @selector(thumbnailsDidChange:)
1028 name: GWThumbnailsDidChangeNotification
1029 object: nil];
1030 }
1031
1032 - (BOOL)applicationShouldTerminate:(NSApplication *)app
1033 {
1034 int i;
1035
1036 #define TEST_CLOSE(o, w) if ((o) && ([w isVisible])) [w close]
1037
1038 [self updateDefaults];
1039
1040 TEST_CLOSE (rootViewer, rootViewer);
1041 for (i = 0; i < [viewers count]; i++) {
1042 id vwr = [viewers objectAtIndex: i];
1043 TEST_CLOSE (vwr, vwr);
1044 }
1045 TEST_CLOSE (appsViewer, [appsViewer myWin]);
1046 TEST_CLOSE (inspController, [inspController myWin]);
1047 TEST_CLOSE (finder, [finder myWin]);
1048 TEST_CLOSE (prefController, [prefController myWin]);
1049 TEST_CLOSE (fiend, [fiend myWin]);
1050 TEST_CLOSE (recycler, [recycler myWin]);
1051 TEST_CLOSE (recycler, [recycler recyclerWin]);
1052 TEST_CLOSE (history, [history myWin]);
1053 TEST_CLOSE (desktopWindow, desktopWindow);
1054 TEST_CLOSE (tshelfWin, tshelfWin);
1055
1056 return YES;
1057 }
1058
1059 - (NSString *)defEditor
1060 {
1061 return defEditor;
1062 }
1063
1064 - (NSString *)defXterm
1065 {
1066 return defXterm;
1067 }
1068
1069 - (NSString *)defXtermArgs
1070 {
1071 return defXtermArgs;
1072 }
1073
1074 - (History *)historyWindow
1075 {
1076 return history;
1077 }
1078
1079 - (id)rootViewer
1080 {
1081 return rootViewer;
1082 }
1083
1084 - (ViewersWindow *)viewerRootedAtPath:(NSString *)vpath
1085 {
1086 int i;
1087
1088 for (i = 0; i < [viewers count]; i++) {
1089 ViewersWindow *viewer = [viewers objectAtIndex: i];
1090
1091 if ([[viewer rootPath] isEqual: vpath]) {
1092 return viewer;
1093 }
1094 }
1095
1096 return nil;
1097 }
1098
1099 - (id)desktopView
1100 {
1101 if (desktopWindow != nil) {
1102 return [desktopWindow desktopView];
1103 }
1104 return nil;
1105 }
1106
1107 - (void)showHideDesktop:(BOOL)active
1108 {
1109 if (active) {
1110 if (desktopWindow == nil) {
1111 desktopWindow = [[DesktopWindow alloc] init];
1112 [desktopWindow activate];
1113 } else if ([desktopWindow isVisible] == NO) {
1114 [desktopWindow activate];
1115 }
1116 [self makeTshelfBackground];
1117 } else {
1118 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
1119 [[desktopWindow desktopView] saveDefaults];
1120 [desktopWindow deactivate];
1121 }
1122 }
1123 }
1124
1125 - (NSImage *)tshelfBackground
1126 {
1127 return tshelfBackground;
1128 }
1129
1130 - (void)makeTshelfBackground
1131 {
1132 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
1133 ASSIGN (tshelfBackground, [[desktopWindow desktopView] shelfBackground]);
1134 }
1135 }
1136
1137 - (NSColor *)tshelfBackColor
1138 {
1139 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
1140 return [[desktopWindow desktopView] backColor];
1141 }
1142 return nil;
1143 }
1144
1145 - (void)changeDefaultEditor:(NSString *)editor
1146 {
1147 ASSIGN (defEditor, editor);
1148 }
1149
1150 - (void)changeDefaultXTerm:(NSString *)xterm arguments:(NSString *)args
1151 {
1152 ASSIGN (defXterm, xterm);
1153 ASSIGN (defXtermArgs, args);
1154 }
1155
1156 - (void)updateDefaults
1157 {
1158 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1159 NSMutableArray *viewersPaths;
1160 int i;
1161
1162 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
1163 [[desktopWindow desktopView] saveDefaults];
1164 [defaults setBool: YES forKey: @"desktop"];
1165 } else {
1166 [defaults setBool: NO forKey: @"desktop"];
1167 }
1168
1169 if ((tshelfWin != nil) && ([tshelfWin isVisible])) {
1170 [tshelfWin saveDefaults];
1171 [defaults setBool: YES forKey: @"tshelf"];
1172 } else {
1173 [defaults setBool: NO forKey: @"tshelf"];
1174 }
1175
1176 if ((inspController != nil) && ([[inspController myWin] isVisible])) {
1177 [inspController updateDefaults];
1178 }
1179
1180 if ([[appsViewer myWin] isVisible]) {
1181 [appsViewer updateDefaults];
1182 }
1183
1184 if (finder != nil) {
1185 [finder updateDefaults];
1186 }
1187
1188 if ([[prefController myWin] isVisible]) {
1189 [prefController updateDefaults];
1190 }
1191
1192 if ((fiend != nil) && ([[fiend myWin] isVisible])) {
1193 [fiend updateDefaults];
1194 [defaults setBool: YES forKey: @"usefiend"];
1195 } else {
1196 [defaults setBool: NO forKey: @"usefiend"];
1197 }
1198
1199 [recycler updateDefaults];
1200 [history updateDefaults];
1201 [rootViewer updateDefaults];
1202
1203 viewersPaths = [NSMutableArray arrayWithCapacity: 1];
1204 for (i = 0; i < [viewers count]; i++) {
1205 ViewersWindow *viewer = [viewers objectAtIndex: i];
1206 [viewer updateDefaults];
1207 [viewersPaths addObject: [viewer rootPath]];
1208 }
1209
1210 [defaults setObject: viewersPaths forKey: @"viewerspaths"];
1211
1212 [defaults setObject: defEditor forKey: @"defaulteditor"];
1213 [defaults setObject: defXterm forKey: @"defxterm"];
1214 if (defXtermArgs != nil) {
1215 [defaults setObject: defXtermArgs forKey: @"defaultxtermargs"];
1216 }
1217
1218 [defaults setObject: [NSString stringWithFormat: @"%i", shelfCellsWidth]
1219 forKey: @"shelfcellswidth"];
1220
1221 [defaults setBool: !animateChdir forKey: @"nochdiranim"];
1222 [defaults setBool: !animateLaunck forKey: @"nolaunchanim"];
1223 [defaults setBool: !animateSlideBack forKey: @"noslidebackanim"];
1224
1225 [defaults setBool: usesThumbnails forKey: @"usesthumbnails"];
1226
1227 [defaults synchronize];
1228 }
1229
1230 - (void)startXTermOnDirectory:(NSString *)dirPath
1231 {
1232 NSTask *task = [NSTask new];
1233 AUTORELEASE (task);
1234 [task setCurrentDirectoryPath: dirPath];
1235 [task setLaunchPath: defXterm];
1236 if (defXtermArgs != nil) {
1237 NSArray *args = [defXtermArgs componentsSeparatedByString:@" "];
1238 [task setArguments: args];
1239 }
1240 [task launch];
1241 }
1242
1243 - (int)defaultSortType
1244 {
1245 return defSortType;
1246 }
1247
1248 - (void)setDefaultSortType:(int)type
1249 {
1250 if (defSortType == type) {
1251 return;
1252 } else {
1253 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1254 defSortType = type;
1255 [defaults setObject: [NSString stringWithFormat: @"%i", defSortType]
1256 forKey: @"defaultsorttype"];
1257 [defaults synchronize];
1258
1259 [self clearCache];
1260
1261 [[NSNotificationCenter defaultCenter]
1262 postNotificationName: GWSortTypeDidChangeNotification
1263 object: nil];
1264 }
1265 }
1266
1267 - (int)shelfCellsWidth
1268 {
1269 return shelfCellsWidth;
1270 }
1271
1272 - (int)defaultShelfCellsWidth
1273 {
1274 [self setShelfCellsWidth: 90];
1275 return 90;
1276 }
1277
1278 - (void)setShelfCellsWidth:(int)w
1279 {
1280 shelfCellsWidth = w;
1281
1282 [[NSNotificationCenter defaultCenter]
1283 postNotificationName: GWShelfCellsWidthChangedNotification
1284 object: nil];
1285 }
1286
1287 - (void)createRecycler
1288 {
1289 NSDictionary *env;
1290 NSString *basePath, *tpath;
1291 BOOL isdir;
1292
1293 env = [[NSProcessInfo processInfo] environment];
1294 basePath = [env objectForKey: @"GNUSTEP_USER_ROOT"];
1295 if (basePath == nil) {
1296 basePath = [NSHomeDirectory() stringByAppendingPathComponent: @"GNUstep"];
1297 NSLog (@"Warning - GNUSTEP_USER_ROOT is not set - using %@", basePath);
1298 }
1299
1300 tpath = [basePath stringByAppendingPathComponent: @".GWTrash"];
1301
1302 if ([fm fileExistsAtPath: tpath isDirectory: &isdir] == NO) {
1303 [fm createDirectoryAtPath: tpath attributes: nil];
1304
1305 } else {
1306 if (isdir == NO) {
1307 NSLog (@"Warning - %@ is not a directory - quitting now!", tpath);
1308 [[NSApplication sharedApplication] terminate: self];
1309 }
1310 }
1311
1312 ASSIGN (trashPath, tpath);
1313 recycler = [[Recycler alloc] initWithTrashPath: trashPath];
1314 [recycler activate];
1315 }
1316
1317 - (BOOL)validateMenuItem:(NSMenuItem *)anItem
1318 {
1319 NSString *title = [anItem title];
1320
1321 if ([title isEqual: NSLocalizedString(@"Empty Recycler", @"")]) {
1322 return [recycler isFull];
1323 } else if ([title isEqual: NSLocalizedString(@"Put Away", @"")]) {
1324 if ([recycler isFull] && [recycler isFull]) {
1325 if ([recycler selectedPath] != nil) {
1326 return YES;
1327 }
1328 }
1329 return NO;
1330 }
1331
1332 if ([title isEqual: NSLocalizedString(@"File Operations...", @"")]) {
1333 return [operations count];
1334 }
1335
1336 if ([title isEqual: NSLocalizedString(@"Open With...", @"")]) {
1337 BOOL found = NO;
1338 int i;
1339
1340 for (i = 0; i < [selectedPaths count]; i++) {
1341 NSString *spath = [selectedPaths objectAtIndex: i];
1342 NSDictionary *attributes = [fm fileAttributesAtPath: spath traverseLink: YES];
1343
1344 if ([attributes objectForKey: NSFileType] != NSFileTypeDirectory) {
1345 NSString *defApp, *fileType;
1346
1347 [ws getInfoForFile: spath application: &defApp type: &fileType];
1348
1349 if((fileType != NSPlainFileType) && (fileType != NSShellCommandFileType)) {
1350 found = YES;
1351 }
1352
1353 } else {
1354 found = YES;
1355 }
1356
1357 if (found) {
1358 break;
1359 }
1360 }
1361
1362 return !found;
1363 }
1364
1365 return YES;
1366 }
1367
1368 - (void)makeViewersTemplates
1369 {
1370 NSMutableArray *bundlesPaths;
1371 NSArray *bPaths;
1372 NSString *home;
1373 int i;
1374
1375 #define VERIFY_VIEWERS( x ) \
1376 if (!x) { \
1377 NSRunAlertPanel(NSLocalizedString(@"error", @""), \
1378 NSLocalizedString(@"No Viewer found! Quitting now.", @""), \
1379 NSLocalizedString(@"OK", @""), nil, nil); \
1380 [[NSApplication sharedApplication] terminate: nil]; \
1381 }
1382
1383 TEST_RELEASE (viewersTemplates);
1384 viewersTemplates = [[NSMutableArray alloc] initWithCapacity: 1];
1385
1386 bundlesPaths = [NSMutableArray array];
1387
1388 //load all default Viewers
1389 bPaths = [self bundlesWithExtension: @"viewer"
1390 inDirectory: [[NSBundle mainBundle] resourcePath]];
1391 [bundlesPaths addObjectsFromArray: bPaths];
1392
1393 VERIFY_VIEWERS (bundlesPaths && [bundlesPaths count]);
1394
1395 //load user Viewers
1396 home = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
1397 [bundlesPaths addObjectsFromArray: [self bundlesWithExtension: @"viewer"
1398 inDirectory: [home stringByAppendingPathComponent: @"GWorkspace"]]];
1399
1400 for (i = 0; i < [bundlesPaths count]; i++) {
1401 NSString *bpath = [bundlesPaths objectAtIndex: i];
1402 NSBundle *bundle = [NSBundle bundleWithPath: bpath];
1403
1404 if (bundle) {
1405 Class principalClass = [bundle principalClass];
1406
1407 if (principalClass) {
1408 if ([principalClass conformsToProtocol: @protocol(ViewersProtocol)]) {
1409 id<ViewersProtocol> vwr = AUTORELEASE ([[principalClass alloc] init]);
1410
1411 [self addViewer: vwr withBundlePath: bpath];
1412 }
1413 }
1414 }
1415 }
1416
1417 VERIFY_VIEWERS([viewersTemplates count]);
1418
1419 [[NSNotificationCenter defaultCenter] addObserver: self
1420 selector: @selector(watcherNotification:)
1421 name: GWFileWatcherFileDidChangeNotification
1422 object: nil];
1423
1424 [viewersSearchPaths addObject: [[NSBundle mainBundle] resourcePath]];
1425 [viewersSearchPaths addObject: [home stringByAppendingPathComponent: @"GWorkspace"]];
1426
1427 for (i = 0; i < [viewersSearchPaths count]; i++) {
1428 NSString *spath = [viewersSearchPaths objectAtIndex: i];
1429 [self addWatcherForPath: spath];
1430 }
1431 }
1432
1433 - (void)addViewer:(id)vwr withBundlePath:(NSString *)bpath
1434 {
1435 NSString *name = [vwr menuName];
1436 BOOL found = NO;
1437 int i = 0;
1438
1439 for (i = 0; i < [viewersTemplates count]; i++) {
1440 NSDictionary *vdict = [viewersTemplates objectAtIndex: i];
1441 NSString *vname = [vdict objectForKey: @"name"];
1442
1443 if ([vname isEqual: name]) {
1444 found = YES;
1445 break;
1446 }
1447 }
1448
1449 if (found == NO) {
1450 NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 1];
1451
1452 [dict setObject: vwr forKey: @"viewer"];
1453 [dict setObject: name forKey: @"name"];
1454 [dict setObject: bpath forKey: @"path"];
1455 [viewersTemplates addObject: dict];
1456
1457 if ([vwr hasPreferences]) {
1458 [prefController addPreference: [vwr prefController]];
1459 }
1460
1461 [[NSNotificationCenter defaultCenter]
1462 postNotificationName: GWViewersListDidChangeNotification
1463 object: viewersTemplates];
1464 }
1465 }
1466
1467 - (void)removeViewerWithBundlePath:(NSString *)bpath
1468 {
1469 int i, count;
1470
1471 count = [viewersTemplates count];
1472 for (i = 0; i < count; i++) {
1473 NSDictionary *vdict = [viewersTemplates objectAtIndex: i];
1474 id vwr = [vdict objectForKey: @"viewer"];
1475 NSString *path = [vdict objectForKey: @"path"];
1476
1477 if ([path isEqual: bpath]) {
1478 if ((count - 1) == 0) {
1479 NSRunAlertPanel(NSLocalizedString(@"error", @""),
1480 NSLocalizedString(@"No Viewer found! Quitting now.", @""),
1481 NSLocalizedString(@"OK", @""), nil, nil);
1482 [[NSApplication sharedApplication] terminate: nil];
1483 }
1484
1485 if ([vwr hasPreferences]) {
1486 [prefController removePreference: [vwr prefController]];
1487 }
1488
1489 [viewersTemplates removeObject: vdict];
1490 [[NSNotificationCenter defaultCenter]
1491 postNotificationName: GWViewersListDidChangeNotification
1492 object: viewersTemplates];
1493 break;
1494 }
1495 }
1496 }
1497
1498 - (NSMutableArray *)bundlesWithExtension:(NSString *)extension
1499 inDirectory:(NSString *)dirpath
1500 {
1501 NSMutableArray *bundleList = [NSMutableArray array];
1502 NSEnumerator *enumerator;
1503 NSString *dir;
1504 BOOL isDir;
1505
1506 if (!(([fm fileExistsAtPath: dirpath isDirectory: &isDir]) && isDir)) {
1507 return nil;
1508 }
1509
1510 enumerator = [[fm directoryContentsAtPath: dirpath] objectEnumerator];
1511 while ((dir = [enumerator nextObject])) {
1512 if ([[dir pathExtension] isEqualToString: extension]) {
1513 [bundleList addObject: [dirpath stringByAppendingPathComponent: dir]];
1514 }
1515 }
1516
1517 return bundleList;
1518 }
1519
1520 - (NSArray *)viewersPaths
1521 {
1522 NSMutableArray *vpaths = [NSMutableArray arrayWithCapacity: 1];
1523 int i;
1524
1525 for (i = 0; i < [viewersTemplates count]; i++) {
1526 NSDictionary *vdict = [viewersTemplates objectAtIndex: i];
1527 [vpaths addObject: [vdict objectForKey: @"path"]];
1528 }
1529
1530 return vpaths;
1531 }
1532
1533 - (void)watcherNotification:(NSNotification *)notification
1534 {
1535 NSDictionary *notifdict = (NSDictionary *)[notification object];
1536 NSString *path = [notifdict objectForKey: @"path"];
1537 NSArray *vpaths = [self viewersPaths];
1538
1539 if ([self cachedRepresentationForPath: path]) {
1540 [self removeCachedRepresentationForPath: path];
1541 }
1542
1543 if ([viewersSearchPaths containsObject: path] == NO) {
1544 return;
1545
1546 } else {
1547 NSString *event = [notifdict objectForKey: @"event"];
1548 int i, count;
1549
1550 if (event == GWFileDeletedInWatchedDirectory) {
1551 NSArray *files = [notifdict objectForKey: @"files"];
1552
1553 count = [files count];
1554 for (i = 0; i < count; i++) {
1555 NSString *fname = [files objectAtIndex: i];
1556 NSString *bpath = [path stringByAppendingPathComponent: fname];
1557
1558 if ([vpaths containsObject: bpath]) {
1559 [self removeViewerWithBundlePath: bpath];
1560 i--;
1561 count--;
1562 }
1563 }
1564
1565 } else if (event == GWFileCreatedInWatchedDirectory) {
1566 NSArray *files = [notifdict objectForKey: @"files"];
1567
1568 for (i = 0; i < [files count]; i++) {
1569 NSString *fname = [files objectAtIndex: i];
1570 NSString *bpath = [path stringByAppendingPathComponent: fname];
1571 NSBundle *bundle = [NSBundle bundleWithPath: bpath];
1572
1573 if (bundle) {
1574 Class principalClass = [bundle principalClass];
1575
1576 if (principalClass) {
1577 if ([principalClass conformsToProtocol: @protocol(ViewersProtocol)]) {
1578 id<ViewersProtocol> vwr = AUTORELEASE ([[principalClass alloc] init]);
1579
1580 [self addViewer: vwr withBundlePath: bpath];
1581 }
1582 }
1583 }
1584 }
1585 }
1586 }
1587 }
1588
1589 - (void)viewerHasClosed:(id)sender
1590 {
1591 if (sender != rootViewer) {
1592 [viewers removeObject: sender];
1593 }
1594 }
1595
1596 - (void)setCurrentViewer:(ViewersWindow *)viewer
1597 {
1598 currentViewer = viewer;
1599 }
1600
1601 - (void)setHideDotFiles:(NSNotification *)notif
1602 {
1603 NSString *hideStr = (NSString *)[notif object];
1604 BOOL hideDot = (BOOL)[hideStr intValue];
1605
1606 if (hideSysFiles != hideDot) {
1607 [self clearCache];
1608
1609 hideSysFiles = hideDot;
1610
1611 [[NSNotificationCenter defaultCenter]
1612 postNotificationName: GWSortTypeDidChangeNotification
1613 object: nil];
1614 }
1615 }
1616
1617 - (void)iconAnimationChanged:(NSNotification *)notif
1618 {
1619 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1620
1621 animateChdir = ![defaults boolForKey: @"nochdiranim"];
1622 animateLaunck = ![defaults boolForKey: @"nolaunchanim"];
1623 animateSlideBack = ![defaults boolForKey: @"noslidebackanim"];
1624 }
1625
1626 - (BOOL)showFileOpStatus
1627 {
1628 return showFileOpStatus;
1629 }
1630
1631 - (void)setShowFileOpStatus:(BOOL)value
1632 {
1633 if (showFileOpStatus != value) {
1634 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1635 showFileOpStatus = value;
1636 [defaults setBool: showFileOpStatus forKey: @"showfopstatus"];
1637 [defaults synchronize];
1638 }
1639 }
1640
1641 - (void)fileSystemWillChangeNotification:(NSNotification *)notif
1642 {
1643 NSDictionary *info = [notif userInfo];
1644 NSString *operation = [info objectForKey: @"operation"];
1645 NSString *source = [info objectForKey: @"source"];
1646 NSString *destination = [info objectForKey: @"destination"];
1647 NSArray *files = [info objectForKey: @"files"];
1648 NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 1];
1649 NSString *opPtr = nil;
1650
1651 if ([operation isEqual: NSWorkspaceMoveOperation]) {
1652 opPtr = NSWorkspaceMoveOperation;
1653 } else if ([operation isEqual: NSWorkspaceCopyOperation]) {
1654 opPtr = NSWorkspaceCopyOperation;
1655 } else if ([operation isEqual: NSWorkspaceLinkOperation]) {
1656 opPtr = NSWorkspaceLinkOperation;
1657 } else if ([operation isEqual: NSWorkspaceDuplicateOperation]) {
1658 opPtr = NSWorkspaceDuplicateOperation;
1659 } else if ([operation isEqual: NSWorkspaceDestroyOperation]) {
1660 opPtr = NSWorkspaceDestroyOperation;
1661 } else if ([operation isEqual: NSWorkspaceRecycleOperation]) {
1662 opPtr = NSWorkspaceRecycleOperation;
1663 } else if ([operation isEqual: GWorkspaceRecycleOutOperation]) {
1664 opPtr = GWorkspaceRecycleOutOperation;
1665 } else if ([operation isEqual: GWorkspaceEmptyRecyclerOperation]) {
1666 opPtr = GWorkspaceEmptyRecyclerOperation;
1667 }
1668
1669 if (opPtr == NSWorkspaceMoveOperation
1670 || opPtr == NSWorkspaceCopyOperation
1671 || opPtr == NSWorkspaceLinkOperation
1672 || opPtr == NSWorkspaceDuplicateOperation
1673 || opPtr == NSWorkspaceRecycleOperation
1674 || opPtr == GWorkspaceRecycleOutOperation) {
1675 if ([viewersSearchPaths containsObject: destination] == NO) {
1676 [self lockFiles: files inDirectoryAtPath: destination];
1677 }
1678 }
1679
1680 if (opPtr == NSWorkspaceMoveOperation
1681 || opPtr == NSWorkspaceDestroyOperation
1682 || opPtr == NSWorkspaceRecycleOperation
1683 || opPtr == GWorkspaceRecycleOutOperation
1684 || opPtr == GWorkspaceEmptyRecyclerOperation) {
1685 if ([viewersSearchPaths containsObject: source] == NO) {
1686 [self lockFiles: files inDirectoryAtPath: source];
1687 }
1688 }
1689
1690 [dict setObject: opPtr forKey: @"operation"];
1691 [dict setObject: source forKey: @"source"];
1692 [dict setObject: destination forKey: @"destination"];
1693 [dict setObject: files forKey: @"files"];
1694
1695 [[NSNotificationCenter defaultCenter]
1696 postNotificationName: GWFileSystemWillChangeNotification
1697 object: dict];
1698 }
1699
1700 - (void)fileSystemDidChangeNotification:(NSNotification *)notif
1701 {
1702 NSDictionary *info = [notif userInfo];
1703 NSString *operation = [info objectForKey: @"operation"];
1704 NSString *source = [info objectForKey: @"source"];
1705 NSString *destination = [info objectForKey: @"destination"];
1706 NSArray *files = [info objectForKey: @"files"];
1707 NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 1];
1708 NSString *opPtr = nil;
1709
1710 if ([operation isEqual: NSWorkspaceMoveOperation]) {
1711 opPtr = NSWorkspaceMoveOperation;
1712 } else if ([operation isEqual: NSWorkspaceCopyOperation]) {
1713 opPtr = NSWorkspaceCopyOperation;
1714 } else if ([operation isEqual: NSWorkspaceLinkOperation]) {
1715 opPtr = NSWorkspaceLinkOperation;
1716 } else if ([operation isEqual: NSWorkspaceDuplicateOperation]) {
1717 opPtr = NSWorkspaceDuplicateOperation;
1718 } else if ([operation isEqual: NSWorkspaceDestroyOperation]) {
1719 opPtr = NSWorkspaceDestroyOperation;
1720 } else if ([operation isEqual: NSWorkspaceRecycleOperation]) {
1721 opPtr = NSWorkspaceRecycleOperation;
1722 } else if ([operation isEqual: GWorkspaceRecycleOutOperation]) {
1723 opPtr = GWorkspaceRecycleOutOperation;
1724 } else if ([operation isEqual: GWorkspaceEmptyRecyclerOperation]) {
1725 opPtr = GWorkspaceEmptyRecyclerOperation;
1726 }
1727
1728 if (opPtr == NSWorkspaceMoveOperation
1729 || opPtr == NSWorkspaceCopyOperation
1730 || opPtr == NSWorkspaceLinkOperation
1731 || opPtr == NSWorkspaceDuplicateOperation
1732 || opPtr == NSWorkspaceRecycleOperation
1733 || opPtr == GWorkspaceRecycleOutOperation) {
1734 [self unLockFiles: files inDirectoryAtPath: destination];
1735 }
1736
1737 if (opPtr == NSWorkspaceMoveOperation
1738 || opPtr == NSWorkspaceDestroyOperation
1739 || opPtr == NSWorkspaceRecycleOperation
1740 || opPtr == GWorkspaceRecycleOutOperation
1741 || opPtr == GWorkspaceEmptyRecyclerOperation) {
1742 [self unLockFiles: files inDirectoryAtPath: source];
1743 }
1744
1745 [dict setObject: opPtr forKey: @"operation"];
1746 [dict setObject: source forKey: @"source"];
1747 [dict setObject: destination forKey: @"destination"];
1748 [dict setObject: files forKey: @"files"];
1749
1750 [[NSNotificationCenter defaultCenter]
1751 postNotificationName: GWFileSystemDidChangeNotification
1752 object: dict];
1753 }
1754
1755 - (void)setSelectedPaths:(NSArray *)paths
1756 {
1757 if (paths && ([selectedPaths isEqualToArray: paths] == NO)) {
1758 ASSIGN (selectedPaths, paths);
1759 if (inspController != nil) {
1760 [inspController setPaths: selectedPaths];
1761 }
1762
1763 [[NSNotificationCenter defaultCenter]
1764 postNotificationName: GWCurrentSelectionChangedNotification
1765 object: nil];
1766 }
1767 }
1768
1769 - (void)setSelectedPaths:(NSArray *)paths fromDesktopView:(DesktopView *)view
1770 {
1771 [rootViewer makeKeyAndOrderFront: nil];
1772 [self setSelectedPaths: paths];
1773 [rootViewer setViewerSelection: paths];
1774 }
1775
1776 - (void)setSelectedPaths:(NSArray *)paths
1777 fromDesktopView:(DesktopView *)view
1778 animateImage:(NSImage *)image
1779 startingAtPoint:(NSPoint)startp
1780 {
1781 #define SELRETURN \
1782 [self setSelectedPaths: paths]; \
1783 [rootViewer setViewerSelection: paths]; \
1784 return
1785
1786 NSPoint endp = [rootViewer positionForSlidedImage];
1787
1788 [rootViewer makeKeyAndOrderFront: nil];
1789
1790 if (animateChdir == NO) {
1791 SELRETURN;
1792 }
1793
1794 if (startp.x <= 0 || startp.y <= 0) {
1795 SELRETURN;
1796 }
1797
1798 if (endp.x <= 0 || endp.y <= 0) {
1799 SELRETURN;
1800 }
1801
1802 [self slideImage: image from: startp to: endp];
1803
1804 SELRETURN;
1805 }
1806
1807 - (NSArray *)selectedPaths
1808 {
1809 return selectedPaths;
1810 }
1811
1812 - (NSMutableDictionary *)cachedRepresentationForPath:(NSString *)path
1813 {
1814 NSMutableDictionary *contents = [cachedContents objectForKey: path];
1815
1816 if (contents) {
1817 NSDate *modDate = [contents objectForKey: @"moddate"];
1818 NSDictionary *attributes = [fm fileAttributesAtPath: path
1819 traverseLink: YES];
1820 NSDate *date = [attributes fileModificationDate];
1821
1822 if ([modDate isEqualToDate: date]) {
1823 return contents;
1824 } else {
1825 [cachedContents removeObjectForKey: path];
1826 }
1827 }
1828
1829 return nil;
1830 }
1831
1832 - (void)addCachedRepresentation:(NSDictionary *)contentsDict
1833 ofDirectory:(NSString *)path
1834 {
1835 [cachedContents setObject: contentsDict forKey: path];
1836
1837 if ([watchedPaths containsObject: path] == NO) {
1838 [watchedPaths addObject: path];
1839 [self addWatcherForPath: path];
1840 }
1841 }
1842
1843 - (void)removeCachedRepresentationForPath:(NSString *)path
1844 {
1845 [cachedContents removeObjectForKey: path];
1846
1847 if ([watchedPaths containsObject: path]) {
1848 [watchedPaths removeObject: path];
1849 [self removeWatcherForPath: path];
1850 }
1851 }
1852
1853 - (void)removeOlderCache
1854 {
1855 NSArray *keys = [cachedContents allKeys];
1856 NSDate *date = [NSDate date];
1857 NSString *removeKey = nil;
1858 int i;
1859
1860 if ([keys count]) {
1861 for (i = 0; i < [keys count]; i++) {
1862 NSString *key = [keys objectAtIndex: i];
1863 NSDate *stamp = [[cachedContents objectForKey: key] objectForKey: @"datestamp"];
1864 NSDate *d = [date earlierDate: stamp];
1865
1866 if ([date isEqualToDate: d] == NO) {
1867 date = d;
1868 removeKey = key;
1869 }
1870 }
1871
1872 if (removeKey == nil) {
1873 removeKey = [keys objectAtIndex: 0];
1874 }
1875
1876 [cachedContents removeObjectForKey: removeKey];
1877
1878 if ([watchedPaths containsObject: removeKey]) {
1879 [watchedPaths removeObject: removeKey];
1880 [self removeWatcherForPath: removeKey];
1881 }
1882 }
1883 }
1884
1885 - (void)clearCache
1886 {
1887 NSArray *keys = [cachedContents allKeys];
1888 int i;
1889
1890 for (i = 0; i < [keys count]; i++) {
1891 [self removeWatcherForPath: [keys objectAtIndex: i]];
1892 }
1893
1894 DESTROY (cachedContents);
1895 cachedContents = [NSMutableDictionary new];
1896 }
1897
1898 - (void)closeInspectors
1899 {
1900 [inspController release];
1901 inspController = nil;
1902 }
1903
1904 - (void)newObjectAtPath:(NSString *)basePath isDirectory:(BOOL)directory
1905 {
1906 NSString *fullPath;
1907 NSString *fileName;
1908 NSString *operation;
1909 NSMutableDictionary *notifObj;
1910 int suff;
1911
1912 if ([self verifyFileAtPath: basePath] == NO) {
1913 return;
1914 }
1915
1916 if ([fm isWritableFileAtPath: basePath] == NO) {
1917 NSString *err = NSLocalizedString(@"Error", @"");
1918 NSString *msg = NSLocalizedString(@"You have not write permission\nfor", @"");
1919 NSString *buttstr = NSLocalizedString(@"Continue", @"");
1920 NSRunAlertPanel(err, [NSString stringWithFormat: @"%@ \"%@\"!\n", msg, basePath], buttstr, nil, nil);
1921 return;
1922 }
1923
1924 if (directory == YES) {
1925 fileName = @"NewFolder";
1926 operation = GWorkspaceCreateDirOperation;
1927 } else {
1928 fileName = @"NewFile";
1929 operation = GWorkspaceCreateFileOperation;
1930 }
1931
1932 fullPath = [basePath stringByAppendingPathComponent: fileName];
1933
1934 if ([fm fileExistsAtPath: fullPath] == YES) {
1935 suff = 1;
1936 while (1) {
1937 NSString *s = [fileName stringByAppendingFormat: @"%i", suff];
1938 fullPath = [basePath stringByAppendingPathComponent: s];
1939 if ([fm fileExistsAtPath: fullPath] == NO) {
1940 fileName = [NSString stringWithString: s];
1941 break;
1942 }
1943 suff++;
1944 }
1945 }
1946
1947 notifObj = [NSMutableDictionary dictionaryWithCapacity: 1];
1948 [notifObj setObject: operation forKey: @"operation"];
1949 [notifObj setObject: @"" forKey: @"source"];
1950 [notifObj setObject: basePath forKey: @"destination"];
1951 [notifObj setObject: [NSArray arrayWithObjects: fileName, nil] forKey: @"files"];
1952
1953 [[NSNotificationCenter defaultCenter]
1954 postNotificationName: GWFileSystemWillChangeNotification
1955 object: notifObj];
1956
1957 if (directory == YES) {
1958 [fm createDirectoryAtPath: fullPath attributes: nil];
1959 } else {
1960 [fm createFileAtPath: fullPath contents: nil attributes: nil];
1961 }
1962
1963 [[NSNotificationCenter defaultCenter]
1964 postNotificationName: GWFileSystemDidChangeNotification
1965 object: notifObj];
1966 }
1967
1968 - (void)duplicateFiles
1969 {
1970 NSString *basePath;
1971 NSMutableArray *files;
1972 int tag, i;
1973
1974 basePath = [NSString stringWithString: [selectedPaths objectAtIndex: 0]];
1975 basePath = [basePath stringByDeletingLastPathComponent];
1976
1977 if ([fm isWritableFileAtPath: basePath] == NO) {
1978 NSString *err = NSLocalizedString(@"Error", @"");
1979 NSString *msg = NSLocalizedString(@"You have not write permission\nfor", @"");
1980 NSString *buttstr = NSLocalizedString(@"Continue", @"");
1981 NSRunAlertPanel(err, [NSString stringWithFormat: @"%@ \"%@\"!\n", msg, basePath], buttstr, nil, nil);
1982 return;
1983 }
1984
1985 files = [NSMutableArray arrayWithCapacity: 1];
1986 for (i = 0; i < [selectedPaths count]; i++) {
1987 [files addObject: [[selectedPaths objectAtIndex: i] lastPathComponent]];
1988 }
1989
1990 [self performFileOperation: NSWorkspaceDuplicateOperation
1991 source: basePath destination: basePath files: files tag: &tag];
1992 }
1993
1994 - (void)deleteFiles
1995 {
1996 NSString *basePath;
1997 NSMutableArray *files;
1998 int tag, i;
1999
2000 basePath = [NSString stringWithString: [selectedPaths objectAtIndex: 0]];
2001 basePath = [basePath stringByDeletingLastPathComponent];
2002
2003 if ([fm isWritableFileAtPath: basePath] == NO) {
2004 NSString *err = NSLocalizedString(@"Error", @"");
2005 NSString *msg = NSLocalizedString(@"You have not write permission\nfor", @"");
2006 NSString *buttstr = NSLocalizedString(@"Continue", @"");
2007 NSRunAlertPanel(err, [NSString stringWithFormat: @"%@ \"%@\"!\n", msg, basePath], buttstr, nil, nil);
2008 return;
2009 }
2010
2011 files = [NSMutableArray arrayWithCapacity: 1];
2012 for (i = 0; i < [selectedPaths count]; i++) {
2013 [files addObject: [[selectedPaths objectAtIndex: i] lastPathComponent]];
2014 }
2015
2016 [self performFileOperation: NSWorkspaceDestroyOperation
2017 source: basePath destination: basePath files: files tag: &tag];
2018 }
2019
2020 - (BOOL)verifyFileAtPath:(NSString *)path
2021 {
2022 if ([fm fileExistsAtPath: path] == NO) {
2023 NSString *err = NSLocalizedString(@"Error", @"");
2024 NSString *msg = NSLocalizedString(@": no such file or directory!", @"");
2025 NSString *buttstr = NSLocalizedString(@"Continue", @"");
2026 NSMutableDictionary *notifObj = [NSMutableDictionary dictionaryWithCapacity: 1];
2027 NSString *basePath = [path stringByDeletingLastPathComponent];
2028
2029 NSRunAlertPanel(err, [NSString stringWithFormat: @"%@%@", path, msg], buttstr, nil, nil);
2030
2031 [notifObj setObject: NSWorkspaceDestroyOperation forKey: @"operation"];
2032 [notifObj setObject: basePath forKey: @"source"];
2033 [notifObj setObject: basePath forKey: @"destination"];
2034 [notifObj setObject: [NSArray arrayWithObjects: path, nil] forKey: @"files"];
2035
2036 [[NSNotificationCenter defaultCenter]
2037 postNotificationName: GWFileSystemWillChangeNotification
2038 object: notifObj];
2039
2040 [[NSNotificationCenter defaultCenter]
2041 postNotificationName: GWFileSystemDidChangeNotification
2042 object: notifObj];
2043 return NO;
2044 }
2045
2046 return YES;
2047 }
2048
2049 - (void)removeWatcher:(Watcher *)awatcher
2050 {
2051 NSString *watchedPath = [awatcher watchedPath];
2052 NSTimer *timer = [self timerForPath: watchedPath];
2053
2054 if (timer && [timer isValid]) {
2055 [timer invalidate];
2056 [watchTimers removeObject: timer];
2057 }
2058
2059 [watchers removeObject: awatcher];
2060 }
2061
2062 - (Watcher *)watcherForPath:(NSString *)path
2063 {
2064 int i;
2065
2066 for (i = 0; i < [watchers count]; i++) {
2067 Watcher *watcher = [watchers objectAtIndex: i];
2068 if ([watcher isWathcingPath: path]) {
2069 return watcher;
2070 }
2071 }
2072
2073 return nil;
2074 }
2075
2076 - (NSTimer *)timerForPath:(NSString *)path
2077 {
2078 int i;
2079
2080 for (i = 0; i < [watchTimers count]; i++) {
2081 NSTimer *t = [watchTimers objectAtIndex: i];
2082
2083 if (([t isValid]) && ([(NSString *)[t userInfo] isEqual: path])) {
2084 return t;
2085 }
2086 }
2087
2088 return nil;
2089 }
2090
2091 - (void)watcherTimeOut:(id)sender
2092 {
2093 NSString *watchedPath = (NSString *)[sender userInfo];
2094
2095 if (watchedPath != nil) {
2096 Watcher *watcher = [self watcherForPath: watchedPath];
2097
2098 if (watcher != nil) {
2099 if ([watcher isOld]) {
2100 [self removeWatcher: watcher];
2101 } else {
2102 [watcher watchFile];
2103 }
2104 }
2105 }
2106 }
2107
2108 - (void)setUsesThumbnails:(BOOL)value
2109 {
2110 int i;
2111
2112 if (usesThumbnails == value) {
2113 return;
2114 }
2115
2116 usesThumbnails = value;
2117 if (usesThumbnails) {
2118 [self prepareThumbnailsCache];
2119 }
2120
2121 [rootViewer thumbnailsDidChangeInPaths: nil];
2122 for (i = 0; i < [viewers count]; i++) {
2123 [[viewers objectAtIndex: i] thumbnailsDidChangeInPaths: nil];
2124 }
2125 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
2126 [[desktopWindow desktopView] updateIcons];
2127 }
2128 if ((tshelfWin != nil) && ([tshelfWin isVisible])) {
2129 [tshelfWin updateIcons];
2130 }
2131 if (finder != nil) {
2132 [finder updateIcons];
2133 }
2134 }
2135
2136 - (void)prepareThumbnailsCache
2137 {
2138 NSString *dictName = @"thumbnails.plist";
2139 NSString *dictPath = [thumbnailDir stringByAppendingPathComponent: dictName];
2140 NSDictionary *tdict;
2141
2142 TEST_RELEASE (tumbsCache);
2143 tumbsCache = [NSMutableDictionary new];
2144
2145 tdict = [NSDictionary dictionaryWithContentsOfFile: dictPath];
2146
2147 if (tdict) {
2148 NSArray *keys = [tdict allKeys];
2149 int i;
2150
2151 for (i = 0; i < [keys count]; i++) {
2152 NSString *key = [keys objectAtIndex: i];
2153 NSString *tumbname = [tdict objectForKey: key];
2154 NSString *tumbpath = [thumbnailDir stringByAppendingPathComponent: tumbname];
2155
2156 if ([fm fileExistsAtPath: tumbpath]) {
2157 NSImage *tumb = [[NSImage alloc] initWithContentsOfFile: tumbpath];
2158
2159 if (tumb) {
2160 [tumbsCache setObject: tumb forKey: key];
2161 RELEASE (tumb);
2162 }
2163 }
2164 }
2165 }
2166 }
2167
2168 - (void)thumbnailsDidChange:(NSNotification *)notif
2169 {
2170 NSDictionary *info = [notif userInfo];
2171 NSArray *deleted = [info objectForKey: @"deleted"];
2172 NSArray *created = [info objectForKey: @"created"];
2173 NSMutableArray *tmbdirs = [NSMutableArray array];
2174 int i;
2175
2176 if (usesThumbnails == NO) {
2177 return;
2178 }
2179
2180 if ([deleted count]) {
2181 for (i = 0; i < [deleted count]; i++) {
2182 NSString *path = [deleted objectAtIndex: i];
2183 NSString *dir = [path stringByDeletingLastPathComponent];
2184
2185 [tumbsCache removeObjectForKey: path];
2186
2187 if ([tmbdirs containsObject: dir] == NO) {
2188 [tmbdirs addObject: dir];
2189 }
2190 }
2191
2192 [rootViewer thumbnailsDidChangeInPaths: tmbdirs];
2193 for (i = 0; i < [viewers count]; i++) {
2194 [[viewers objectAtIndex: i] thumbnailsDidChangeInPaths: tmbdirs];
2195 }
2196 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
2197 [[desktopWindow desktopView] updateIcons];
2198 }
2199 if ((tshelfWin != nil) && ([tshelfWin isVisible])) {
2200 [tshelfWin updateIcons];
2201 }
2202 if (finder != nil) {
2203 [finder updateIcons];
2204 }
2205
2206 [tmbdirs removeAllObjects];
2207 }
2208
2209 if ([created count]) {
2210 NSString *dictName = @"thumbnails.plist";
2211 NSString *dictPath = [thumbnailDir stringByAppendingPathComponent: dictName];
2212 NSDictionary *tdict = [NSDictionary dictionaryWithContentsOfFile: dictPath];
2213
2214 for (i = 0; i < [created count]; i++) {
2215 NSString *key = [created objectAtIndex: i];
2216 NSString *dir = [key stringByDeletingLastPathComponent];
2217 NSString *tumbname = [tdict objectForKey: key];
2218 NSString *tumbpath = [thumbnailDir stringByAppendingPathComponent: tumbname];
2219
2220 if ([fm fileExistsAtPath: tumbpath]) {
2221 NSImage *tumb = [[NSImage alloc] initWithContentsOfFile: tumbpath];
2222
2223 if (tumb) {
2224 [tumbsCache setObject: tumb forKey: key];
2225 RELEASE (tumb);
2226
2227 if ([tmbdirs containsObject: dir] == NO) {
2228 [tmbdirs addObject: dir];
2229 }
2230 }
2231 }
2232 }
2233
2234 [rootViewer thumbnailsDidChangeInPaths: tmbdirs];
2235 for (i = 0; i < [viewers count]; i++) {
2236 [[viewers objectAtIndex: i] thumbnailsDidChangeInPaths: tmbdirs];
2237 }
2238 if ((desktopWindow != nil) && ([desktopWindow isVisible])) {
2239 [[desktopWindow desktopView] updateIcons];
2240 }
2241 if ((tshelfWin != nil) && ([tshelfWin isVisible])) {
2242 [tshelfWin updateIcons];
2243 }
2244 if (finder != nil) {
2245 [finder updateIcons];
2246 }
2247 }
2248 }
2249
2250 - (NSImage *)thumbnailForPath:(NSString *)path
2251 {
2252 if (usesThumbnails == NO) {
2253 return nil;
2254 } else {
2255 return [tumbsCache objectForKey: path];
2256 }
2257
2258 return nil;
2259 }
2260
2261 - (id)connectApplication:(NSString *)appName
2262 {
2263 NSString *host;
2264 NSString *port;
2265 id app = nil;
2266
2267 host = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
2268 if (host == nil) {
2269 host = @"";
2270 } else {
2271 NSHost *h = [NSHost hostWithName: host];
2272
2273 if ([h isEqual: [NSHost currentHost]] == YES) {
2274 host = @"";
2275 }
2276 }
2277
2278 port = [appName stringByDeletingPathExtension];
2279
2280 NS_DURING
2281 {
2282 app = [NSConnection rootProxyForConnectionWithRegisteredName: port
2283 host: host];
2284 }
2285 NS_HANDLER
2286 {
2287 app = nil;
2288 }
2289 NS_ENDHANDLER
2290
2291 return app;
2292 }
2293
2294 //
2295 // NSServicesRequests protocol
2296 //
2297
2298 - (id)validRequestorForSendType:(NSString *)sendType
2299 returnType:(NSString *)returnType
2300 {
2301 BOOL sendOK = NO;
2302 BOOL returnOK = NO;
2303
2304 if (sendType == nil) {
2305 sendOK = YES;
2306 } else if ([sendType isEqual: NSFilenamesPboardType] && (selectedPaths != nil)) {
2307 sendOK = YES;
2308 }
2309
2310 if (returnType == nil) {
2311 returnOK = YES;
2312 } else if ([returnType isEqual: NSFilenamesPboardType]) {
2313 returnOK = YES;
2314 }
2315
2316 if (sendOK && returnOK) {
2317 return self;
2318 }
2319
2320 return nil;
2321 }
2322
2323 - (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard
2324 {
2325 if ([[pboard types] indexOfObject: NSFilenamesPboardType] != NSNotFound) {
2326 return YES;
2327 }
2328
2329 return NO;
2330 }
2331
2332 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
2333 types:(NSArray *)types
2334 {
2335 if ([types containsObject: NSFilenamesPboardType] == YES) {
2336 NSArray *typesDeclared = [NSArray arrayWithObject: NSFilenamesPboardType];
2337
2338 [pboard declareTypes: typesDeclared owner: self];
2339
2340 return [pboard setPropertyList: selectedPaths
2341 forType: NSFilenamesPboardType];
2342 }
2343
2344 return NO;
2345 }
2346
2347 //
2348 // Menu Operations
2349 //
2350 - (void)closeMainWin:(id)sender
2351 {
2352 [[[NSApplication sharedApplication] keyWindow] performClose: sender];
2353 }
2354
2355 - (void)showInfo:(id)sender
2356 {
2357 NSMutableDictionary *d = AUTORELEASE ([NSMutableDictionary new]);
2358 [d setObject: @"GWorkspace" forKey: @"ApplicationName"];
2359 [d setObject: NSLocalizedString(@"GNUstep Workspace Manager", @"")
2360 forKey: @"ApplicationDescription"];
2361 [d setObject: @"GWorkspace 0.6" forKey: @"ApplicationRelease"];
2362 [d setObject: @"10 2003" forKey: @"FullVersionID"];
2363 [d setObject: [NSArray arrayWithObjects:
2364 @"Enrico Sersale <enrico@imago.ro>.\n\
2365 InspectorViewer, PlistViewer, StringsViewer\n\
2366 by Fabien Vallon <fabien.vallon@fr.alcove.com>.\n\
2367 Makefiles and configuration scripts\n\
2368 by Alexey I. Froloff <raorn@altlinux.ru>.",
2369 nil]
2370 forKey: @"Authors"];
2371 [d setObject: NSLocalizedString(@"See http://www.gnustep.it/enrico/gworkspace", @"") forKey: @"URL"];
2372 [d setObject: @"Copyright (C) 2003 Free Software Foundation, Inc."
2373 forKey: @"Copyright"];
2374 [d setObject: NSLocalizedString(@"Released under the GNU General Public License 2.0", @"")
2375 forKey: @"CopyrightDescription"];
2376
2377 #ifdef GNUSTEP
2378 [NSApp orderFrontStandardInfoPanelWithOptions: d];
2379 #else
2380 [NSApp orderFrontStandardAboutPanel: d];
2381 #endif
2382 }
2383
2384 - (void)showPreferences:(id)sender
2385 {
2386 [prefController activate];
2387 }
2388
2389 - (void)showViewer:(id)sender
2390 {
2391 if(rootViewer == nil) {
2392 rootViewer = [[ViewersWindow alloc] initWithViewerTemplates: viewersTemplates
2393 forPath: fixPath(@"/", 0) viewPakages: NO
2394 isRootViewer: YES onStart: starting];
2395 } else {
2396 [self newViewerAtPath: fixPath(@"/", 0) canViewApps: NO];
2397 }
2398
2399 [rootViewer activate];
2400 }
2401
2402 - (void)showHistory:(id)sender
2403 {
2404 [history activate];
2405 }
2406
2407 - (void)showInspector:(id)sender
2408 {
2409 if (inspController == nil) {
2410 inspController = [[InspectorsController alloc] initForPaths: selectedPaths];
2411 }
2412 [[inspController myWin] makeKeyAndOrderFront: nil];
2413 }
2414
2415 - (void)showAttributesInspector:(id)sender
2416 {
2417 [self showInspector: nil];
2418 [inspController showAttributes];
2419 }
2420
2421 - (void)showContentsInspector:(id)sender
2422 {
2423 [self showInspector: nil];
2424 [inspController showContents];
2425 }
2426
2427 - (void)showToolsInspector:(id)sender
2428 {
2429 [self showInspector: nil];
2430 [inspController showTools];
2431 }
2432
2433 - (void)showPermissionsInspector:(id)sender
2434 {
2435 [self showInspector: nil];
2436 [inspController showPermissions];
2437 }
2438
2439 - (void)showApps:(id)sender
2440 {
2441 [appsViewer activate];
2442 }
2443
2444 - (void)showFileOps:(id)sender
2445 {
2446 int i;
2447
2448 for (i = 0; i < [operations count]; i++) {
2449 FileOperation *op = [operations objectAtIndex: i];
2450
2451 if ([op showsWindow] == NO) {
2452 [op showProgressWin];
2453 }
2454 }
2455 }
2456
2457 - (void)showFinder:(id)sender
2458 {
2459 if (finder == nil) {
2460 finder = [[FinderController alloc] init];
2461 }
2462 [finder activate];
2463 }
2464
2465 - (void)showFiend:(id)sender
2466 {
2467 NSMenu *menu = [[[NSApp mainMenu] itemWithTitle: NSLocalizedString(@"Tools", @"")] submenu];
2468 menu = [[menu itemWithTitle: NSLocalizedString(@"Fiend", @"")] submenu];
2469
2470 while (1) {
2471 if ([menu numberOfItems] == 0) {
2472 break;
2473 }
2474 [menu removeItemAtIndex: 0];
2475 }
2476
2477 [menu addItemWithTitle: NSLocalizedString(@"Hide Fiend", @"")
2478 action: @selector(hideFiend:) keyEquivalent: @""];
2479 [menu addItemWithTitle: NSLocalizedString(@"Remove Current Layer", @"")
2480 action: @selector(removeFiendLayer:) keyEquivalent: @""];
2481 [menu addItemWithTitle: NSLocalizedString(@"Rename Current Layer", @"")
2482 action: @selector(renameFiendLayer:) keyEquivalent: @""];
2483 [menu addItemWithTitle: NSLocalizedString(@"Add Layer...", @"")
2484 action: @selector(addFiendLayer:) keyEquivalent: @""];
2485
2486 if (fiend == nil) {
2487 fiend = [[Fiend alloc] init];
2488 }
2489 [fiend activate];
2490 }
2491
2492 - (void)hideFiend:(id)sender
2493 {
2494 NSMenu *menu = [[[NSApp mainMenu] itemWithTitle: NSLocalizedString(@"Tools", @"")] submenu];
2495 menu = [[menu itemWithTitle: NSLocalizedString(@"Fiend", @"")] submenu];
2496
2497 while (1) {
2498 if ([menu numberOfItems] == 0) {
2499 break;
2500 }
2501 [menu removeItemAtIndex: 0];
2502 }
2503
2504 [menu addItemWithTitle: NSLocalizedString(@"Show Fiend", @"")
2505 action: @selector(showFiend:) keyEquivalent: @""];
2506
2507 if (fiend != nil) {
2508 [fiend hide];
2509 }
2510 }
2511
2512 - (void)addFiendLayer:(id)sender
2513 {
2514 [fiend addLayer];
2515 }
2516
2517 - (void)removeFiendLayer:(id)sender
2518 {
2519 [fiend removeCurrentLayer];
2520 }
2521
2522 - (void)renameFiendLayer:(id)sender
2523 {
2524 [fiend renameCurrentLayer];
2525 }
2526
2527 - (void)showTShelf:(id)sender
2528 {
2529 NSMenu *menu = [[[NSApp mainMenu] itemWithTitle: NSLocalizedString(@"Tools", @"")] submenu];
2530 menu = [[menu itemWithTitle: NSLocalizedString(@"Tabbed Shelf", @"")] submenu];
2531
2532 while (1) {
2533 if ([menu numberOfItems] == 0) {
2534 break;
2535 }
2536 [menu removeItemAtIndex: 0];
2537 }
2538
2539 [menu addItemWithTitle: NSLocalizedString(@"Hide Tabbed Shelf", @"")
2540 action: @selector(hideTShelf:) keyEquivalent: @""];
2541 [menu addItemWithTitle: NSLocalizedString(@"Remove Current Tab", @"")
2542 action: @selector(removeTShelfTab:) keyEquivalent: @""];
2543 [menu addItemWithTitle: NSLocalizedString(@"Rename Current Tab", @"")
2544 action: @selector(renameTShelfTab:) keyEquivalent: @""];
2545 [menu addItemWithTitle: NSLocalizedString(@"Add Tab...", @"")
2546 action: @selector(addTShelfTab:) keyEquivalent: @""];
2547
2548 if (tshelfWin == nil) {
2549 tshelfWin = [[TShelfWin alloc] init];
2550 [tshelfWin activate];
2551 } else if ([tshelfWin isVisible] == NO) {
2552 [tshelfWin activate];
2553 }
2554 }
2555
2556 - (void)hideTShelf:(id)sender
2557 {
2558 NSMenu *menu = [[[NSApp mainMenu] itemWithTitle: NSLocalizedString(@"Tools", @"")] submenu];
2559 menu = [[menu itemWithTitle: NSLocalizedString(@"Tabbed Shelf", @"")] submenu];
2560
2561 while (1) {
2562 if ([menu numberOfItems] == 0) {
2563 break;
2564 }
2565 [menu removeItemAtIndex: 0];
2566 }
2567
2568 [menu addItemWithTitle: NSLocalizedString(@"Show Tabbed Shelf", @"")
2569 action: @selector(showTShelf:) keyEquivalent: @""];
2570
2571 if ((tshelfWin != nil) && ([tshelfWin isVisible])) {
2572 [tshelfWin saveDefaults];
2573 [tshelfWin deactivate];
2574 }
2575 }
2576
2577 - (void)addTShelfTab:(id)sender
2578 {
2579 [tshelfWin addTab];
2580 }
2581
2582 - (void)removeTShelfTab:(id)sender
2583 {
2584 [tshelfWin removeTab];
2585 }
2586
2587 - (void)renameTShelfTab:(id)sender
2588 {
2589 [tshelfWin renameTab];
2590 }
2591
2592 - (void)openWith:(id)sender
2593 {
2594 [self openSelectedPathsWith];
2595 }
2596
2597 - (void)runCommand:(id)sender
2598 {
2599 [runExtController activate];
2600 }
2601
2602 - (void)startXTerm:(id)sender
2603 {
2604 NSString *path;
2605 BOOL isdir;
2606
2607 path = [currentViewer currentViewedPath];
2608
2609 if (path == nil) {
2610 if ([selectedPaths count] > 1) {
2611 path = [[selectedPaths objectAtIndex: 0] stringByDeletingLastPathComponent];
2612 } else {
2613 path = [selectedPaths objectAtIndex: 0];
2614 [fm fileExistsAtPath: path isDirectory: &isdir];
2615 if (isdir == NO) {
2616 path = [path stringByDeletingLastPathComponent];
2617 }
2618 }
2619 }
2620
2621 [self startXTermOnDirectory: path];
2622 }
2623
2624 - (void)emptyRecycler:(id)sender
2625 {
2626 [recycler emptyRecycler];
2627 }
2628
2629 - (void)putAway:(id)sender
2630 {
2631 [recycler putAway];
2632 }
2633
2634 @end
2635
2636
2637

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