1/* HiddenFilesPref.m 2 * 3 * Copyright (C) 2003-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. 23 */ 24 25 26#import <Foundation/Foundation.h> 27#import <AppKit/AppKit.h> 28#import <GNUstepBase/GNUstep.h> 29 30#import "FSNodeRep.h" 31#import "FSNFunctions.h" 32#import "HiddenFilesPref.h" 33#import "GWorkspace.h" 34 35 36static NSString *nibName = @"HiddenFilesPref"; 37 38#define ICON_SIZE 48 39#define LINEH 20 40 41#define CHECKSIZE(sz) \ 42if (sz.width < 0) sz.width = 0; \ 43if (sz.height < 0) sz.height = 0 44 45@implementation HiddenFilesPref 46 47- (void)dealloc 48{ 49 [[NSNotificationCenter defaultCenter] removeObserver: self]; 50 RELEASE (prefbox); 51 RELEASE (currentNode); 52 RELEASE (hiddenPaths); 53 RELEASE (leftMatrix); 54 RELEASE (rightMatrix); 55 RELEASE (dirsMatrix); 56 RELEASE (cellPrototipe); 57 [super dealloc]; 58} 59 60- (id)init 61{ 62 self = [super init]; 63 64 if (self) { 65 if ([NSBundle loadNibNamed: nibName owner: self] == NO) { 66 NSLog(@"failed to load %@!", nibName); 67 } else { 68 NSArray *hpaths; 69 NSArray *selection; 70 FSNode *node; 71 NSImage *icon; 72 73 RETAIN (prefbox); 74 RELEASE (win); 75 76 gw = [GWorkspace gworkspace]; 77 fm = [NSFileManager defaultManager]; 78 ws = [NSWorkspace sharedWorkspace]; 79 80 selection = [gw selectedPaths]; 81 node = [FSNode nodeWithPath: [selection objectAtIndex: 0]]; 82 83 if ([selection count] > 1) { 84 node = [FSNode nodeWithPath: [node parentPath]]; 85 } else { 86 if ([node isDirectory] == NO) { 87 node = [FSNode nodeWithPath: [node parentPath]]; 88 } else if ([node isPackage]) { 89 node = [FSNode nodeWithPath: [node parentPath]]; 90 } 91 } 92 93 ASSIGN (currentNode, node); 94 95 icon = [[FSNodeRep sharedInstance] iconOfSize: ICON_SIZE 96 forNode: currentNode]; 97 [iconView setImage: icon]; 98 99 cellPrototipe = [NSBrowserCell new]; 100 101 [leftScroll setBorderType: NSBezelBorder]; 102 [leftScroll setHasHorizontalScroller: NO]; 103 [leftScroll setHasVerticalScroller: YES]; 104 105 [rightScroll setBorderType: NSBezelBorder]; 106 [rightScroll setHasHorizontalScroller: NO]; 107 [rightScroll setHasVerticalScroller: YES]; 108 109 leftMatrix = nil; 110 rightMatrix = nil; 111 112 [addButt setImage: [NSImage imageNamed: @"common_ArrowLeftH.tiff"]]; 113 [removeButt setImage: [NSImage imageNamed: @"common_ArrowRightH.tiff"]]; 114 115 [setButt setEnabled: NO]; 116 117 [[NSNotificationCenter defaultCenter] addObserver: self 118 selector: @selector(selectionChanged:) 119 name: @"GWCurrentSelectionChangedNotification" 120 object: nil]; 121 122 [hiddenDirsScroll setBorderType: NSBezelBorder]; 123 [hiddenDirsScroll setHasHorizontalScroller: NO]; 124 [hiddenDirsScroll setHasVerticalScroller: YES]; 125 126 hiddenPaths = [NSMutableArray new]; 127 hpaths = [[FSNodeRep sharedInstance] hiddenPaths]; 128 129 if ([hpaths count]) { 130 NSSize cs, ms; 131 NSUInteger i; 132 133 [hiddenPaths addObjectsFromArray: hpaths]; 134 135 dirsMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(0, 0, 100, 100) 136 mode: NSListModeMatrix prototype: cellPrototipe 137 numberOfRows: 0 numberOfColumns: 0]; 138 [dirsMatrix setIntercellSpacing: NSZeroSize]; 139 [dirsMatrix setCellSize: NSMakeSize(130, LINEH)]; 140 [dirsMatrix setAutoscroll: YES]; 141 [dirsMatrix setAllowsEmptySelection: YES]; 142 cs = [hiddenDirsScroll contentSize]; 143 ms = [dirsMatrix cellSize]; 144 ms.width = cs.width; 145 CHECKSIZE (ms); 146 [dirsMatrix setCellSize: ms]; 147 [hiddenDirsScroll setDocumentView: dirsMatrix]; 148 149 [dirsMatrix addColumn]; 150 for (i = 0; i < [hiddenPaths count]; ++i) { 151 id cell; 152 153 if (i != 0) { 154 [dirsMatrix insertRow: i]; 155 } 156 cell = [dirsMatrix cellAtRow: i column: 0]; 157 [cell setStringValue: [hiddenPaths objectAtIndex: i]]; 158 [cell setLeaf: YES]; 159 } 160 [dirsMatrix sizeToCells]; 161 } else { 162 dirsMatrix = nil; 163 } 164 165 [setDirButt setEnabled: NO]; 166 167 /* Internationalization */ 168 { 169 NSInteger tabindex; 170 NSTabViewItem *item; 171 172 tabindex = [tabView indexOfTabViewItemWithIdentifier: @"Files"]; 173 item = [tabView tabViewItemAtIndex: tabindex]; 174 [item setLabel: NSLocalizedString(@"Files", @"")]; 175 176 tabindex = [tabView indexOfTabViewItemWithIdentifier: @"Folders"]; 177 item = [tabView tabViewItemAtIndex: tabindex]; 178 [item setLabel: NSLocalizedString(@"Folders", @"")]; 179 180 [setButt setTitle: NSLocalizedString(@"Activate changes", @"")]; 181 [loadButt setTitle: NSLocalizedString(@"Load", @"")]; 182 [hiddenlabel setStringValue: NSLocalizedString(@"Hidden files", @"")]; 183 [shownlabel setStringValue: NSLocalizedString(@"Shown files", @"")]; 184 [labelinfo setStringValue: NSLocalizedString(@"Select and move the files to hide or to show", @"")]; 185 [hiddenDirslabel setStringValue: NSLocalizedString(@"Hidden directories", @"")]; 186 [addDirButt setTitle: NSLocalizedString(@"Add", @"")]; 187 [removeDirButt setTitle: NSLocalizedString(@"Remove", @"")]; 188 [setDirButt setTitle: NSLocalizedString(@"Activate changes", @"")]; 189 } 190 } 191 } 192 193 return self; 194} 195 196- (NSView *)prefView 197{ 198 return prefbox; 199} 200 201- (NSString *)prefName 202{ 203 return NSLocalizedString(@"Hidden Files", @""); 204} 205 206- (void)selectionChanged:(NSNotification *)n 207{ 208 NSArray *selection; 209 FSNode *node; 210 NSImage *icon; 211 212 selection = [gw selectedPaths]; 213 node = [FSNode nodeWithPath: [selection objectAtIndex: 0]]; 214 215 if ([selection count] > 1) { 216 node = [FSNode nodeWithPath: [node parentPath]]; 217 } else { 218 if ([node isDirectory] == NO) { 219 node = [FSNode nodeWithPath: [node parentPath]]; 220 } else if ([node isPackage]) { 221 node = [FSNode nodeWithPath: [node parentPath]]; 222 } 223 } 224 225 ASSIGN (currentNode, node); 226 227 icon = [[FSNodeRep sharedInstance] iconOfSize: ICON_SIZE 228 forNode: currentNode]; 229 [iconView setImage: icon]; 230 231 [pathField setStringValue: [currentNode name]]; 232 233 [self clearAll]; 234 235 [prefbox setNeedsDisplay: YES]; 236} 237 238- (void)clearAll 239{ 240 NSSize cs, ms; 241 242 if (leftMatrix) { 243 [leftMatrix removeFromSuperview]; 244 [leftScroll setDocumentView: nil]; 245 DESTROY (leftMatrix); 246 } 247 248 leftMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(0, 0, 100, 100) 249 mode: NSListModeMatrix prototype: cellPrototipe 250 numberOfRows: 0 numberOfColumns: 0]; 251 [leftMatrix setIntercellSpacing: NSZeroSize]; 252 [leftMatrix setCellSize: NSMakeSize(130, LINEH)]; 253 [leftMatrix setAutoscroll: YES]; 254 [leftMatrix setAllowsEmptySelection: YES]; 255 cs = [leftScroll contentSize]; 256 ms = [leftMatrix cellSize]; 257 ms.width = cs.width; 258 CHECKSIZE (ms); 259 [leftMatrix setCellSize: ms]; 260 [leftScroll setDocumentView: leftMatrix]; 261 262 if (rightMatrix) { 263 [rightMatrix removeFromSuperview]; 264 [rightScroll setDocumentView: nil]; 265 DESTROY (rightMatrix); 266 } 267 268 rightMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(0, 0, 100, 100) 269 mode: NSListModeMatrix prototype: cellPrototipe 270 numberOfRows: 0 numberOfColumns: 0]; 271 [rightMatrix setIntercellSpacing: NSZeroSize]; 272 [rightMatrix setCellSize: NSMakeSize(130, LINEH)]; 273 [rightMatrix setAutoscroll: YES]; 274 [rightMatrix setAllowsEmptySelection: YES]; 275 cs = [rightScroll contentSize]; 276 ms = [rightMatrix cellSize]; 277 ms.width = cs.width; 278 CHECKSIZE (ms); 279 [rightMatrix setCellSize: ms]; 280 [rightScroll setDocumentView: rightMatrix]; 281 282 [setButt setEnabled: NO]; 283} 284 285- (IBAction)loadContents:(id)sender 286{ 287 NSArray *subNodes; 288 NSMutableArray *hiddenFiles; 289 BOOL hideSysFiles; 290 NSString *h; 291 NSUInteger i, count; 292 293 [self clearAll]; 294 295 subNodes = [currentNode subNodes]; 296 297 h = [[currentNode path] stringByAppendingPathComponent: @".hidden"]; 298 299 if ([fm fileExistsAtPath: h]) { 300 h = [NSString stringWithContentsOfFile: h]; 301 hiddenFiles = [[h componentsSeparatedByString: @"\n"] mutableCopy]; 302 303 count = [hiddenFiles count]; 304 for (i = 0; i < count; i++) { 305 NSString *s = [hiddenFiles objectAtIndex: i]; 306 307 if ([s length] == 0) { 308 [hiddenFiles removeObject: s]; 309 count--; 310 i--; 311 } 312 } 313 314 } else { 315 hiddenFiles = nil; 316 } 317 hideSysFiles = [[FSNodeRep sharedInstance] hideSysFiles]; 318 319 if (hiddenFiles != nil || hideSysFiles) { 320 NSMutableArray *mutableNodes = AUTORELEASE ([subNodes mutableCopy]); 321 322 if (hiddenFiles) { 323 NSUInteger count = [mutableNodes count]; 324 325 for (i = 0; i < count; i++) { 326 FSNode *node = [mutableNodes objectAtIndex: i]; 327 328 if ([hiddenFiles containsObject: [node name]]) { 329 [mutableNodes removeObject: node]; 330 count--; 331 i--; 332 } 333 } 334 } 335 336 if (hideSysFiles) { 337 int j = [mutableNodes count] - 1; 338 339 while (j >= 0) { 340 NSString *file = [(FSNode *)[mutableNodes objectAtIndex: j] name]; 341 342 if ([file hasPrefix: @"."]) { 343 [mutableNodes removeObjectAtIndex: j]; 344 } 345 j--; 346 } 347 } 348 349 subNodes = mutableNodes; 350 } 351 352 count = [subNodes count]; 353 if (count == 0) { 354 TEST_RELEASE (hiddenFiles); 355 return; 356 } 357 358 [rightMatrix addColumn]; 359 for (i = 0; i < count; ++i) { 360 id cell; 361 362 if (i != 0) { 363 [rightMatrix insertRow: i]; 364 } 365 cell = [rightMatrix cellAtRow: i column: 0]; 366 [cell setStringValue: [(FSNode *)[subNodes objectAtIndex: i] name]]; 367 [cell setLeaf: YES]; 368 } 369 [rightMatrix sizeToCells]; 370 371 if (hiddenFiles != nil) { 372 count = [hiddenFiles count]; 373 if (count == 0) { 374 TEST_RELEASE (hiddenFiles); 375 return; 376 } 377 378 [leftMatrix addColumn]; 379 for (i = 0; i < count; ++i) { 380 id cell; 381 382 if (i != 0) { 383 [leftMatrix insertRow: i]; 384 } 385 cell = [leftMatrix cellAtRow: i column: 0]; 386 [cell setStringValue: [hiddenFiles objectAtIndex: i]]; 387 [cell setLeaf: YES]; 388 } 389 [leftMatrix sizeToCells]; 390 } 391 392 TEST_RELEASE (hiddenFiles); 393} 394 395- (IBAction)moveToHidden:(id)sender 396{ 397 NSArray *cells = [rightMatrix selectedCells]; 398 399 if (cells) { 400 NSMutableArray *names = [NSMutableArray arrayWithCapacity: 1]; 401 NSUInteger i; 402 403 for (i = 0; i < [cells count]; i++) { 404 NSString *name = [[cells objectAtIndex: i] stringValue]; 405 [names addObject: name]; 406 } 407 408 [self removeCellsWithNames: names inMatrix: rightMatrix]; 409 [self addCellsWithNames: names inMatrix: leftMatrix]; 410 411 [setButt setEnabled: YES]; 412 } 413} 414 415- (IBAction)moveToShown:(id)sender 416{ 417 NSArray *cells = [leftMatrix selectedCells]; 418 419 if (cells) { 420 NSMutableArray *names = [NSMutableArray arrayWithCapacity: 1]; 421 NSUInteger i; 422 423 for (i = 0; i < [cells count]; i++) { 424 NSString *name = [[cells objectAtIndex: i] stringValue]; 425 [names addObject: name]; 426 } 427 428 [self removeCellsWithNames: names inMatrix: leftMatrix]; 429 [self addCellsWithNames: names inMatrix: rightMatrix]; 430 431 [setButt setEnabled: YES]; 432 } 433} 434 435- (IBAction)activateChanges:(id)sender 436{ 437 if ([currentNode isWritable] == NO) 438 { 439 NSString *message = NSLocalizedString(@"You have not write permission\nfor",""); 440 message = [message stringByAppendingString: [currentNode name]]; 441 442 NSRunAlertPanel(NSLocalizedString(@"Error", @""), 443 message, 444 NSLocalizedString(@"Continue", @""), 445 nil, nil); 446 return; 447 } 448 else { 449 NSString *base = [currentNode path]; 450 NSMutableArray *paths = [NSMutableArray array]; 451 NSArray *cells = [leftMatrix cells]; 452 453 if (cells) { 454 NSMutableArray *names; 455 NSString *hconts; 456 NSString *h; 457 NSUInteger i; 458 459 names = [NSMutableArray arrayWithCapacity: 1]; 460 for (i = 0; i < [cells count]; i++) { 461 id cell = [cells objectAtIndex: i]; 462 NSString *name = [cell stringValue]; 463 464 [names addObject: name]; 465 [paths addObject: [base stringByAppendingPathComponent: name]]; 466 } 467 468 hconts = [names componentsJoinedByString: @"\n"]; 469 h = [[currentNode path] stringByAppendingPathComponent: @".hidden"]; 470 [hconts writeToFile: h atomically: YES]; 471 [gw hiddenFilesDidChange: paths]; 472 [setButt setEnabled: NO]; 473 } 474 } 475} 476 477- (IBAction)addDir:(id)sender 478{ 479 NSOpenPanel *openPanel; 480 NSString *hidePath; 481 NSInteger result; 482 483 openPanel = [NSOpenPanel openPanel]; 484 [openPanel setTitle: _(@"Hide")]; 485 [openPanel setAllowsMultipleSelection: NO]; 486 [openPanel setCanChooseFiles: NO]; 487 [openPanel setCanChooseDirectories: YES]; 488 489 result = [openPanel runModalForDirectory: path_separator() 490 file: nil 491 types: nil]; 492 if(result != NSOKButton) 493 return; 494 495 hidePath = [NSString stringWithString: [openPanel filename]]; 496 497 if ([hiddenPaths containsObject: hidePath] == NO) { 498 NSSize cs, ms; 499 NSUInteger i; 500 501 [hiddenPaths addObject: hidePath]; 502 503 if (dirsMatrix) { 504 [dirsMatrix removeFromSuperview]; 505 [hiddenDirsScroll setDocumentView: nil]; 506 DESTROY (dirsMatrix); 507 } 508 509 dirsMatrix = [[NSMatrix alloc] initWithFrame: NSMakeRect(0, 0, 100, 100) 510 mode: NSListModeMatrix prototype: cellPrototipe 511 numberOfRows: 0 numberOfColumns: 0]; 512 [dirsMatrix setIntercellSpacing: NSZeroSize]; 513 [dirsMatrix setCellSize: NSMakeSize(130, LINEH)]; 514 [dirsMatrix setAutoscroll: YES]; 515 [dirsMatrix setAllowsEmptySelection: YES]; 516 cs = [hiddenDirsScroll contentSize]; 517 ms = [dirsMatrix cellSize]; 518 ms.width = cs.width; 519 CHECKSIZE (ms); 520 [dirsMatrix setCellSize: ms]; 521 [hiddenDirsScroll setDocumentView: dirsMatrix]; 522 523 [dirsMatrix addColumn]; 524 for (i = 0; i < [hiddenPaths count]; ++i) { 525 id cell; 526 527 if (i != 0) { 528 [dirsMatrix insertRow: i]; 529 } 530 cell = [dirsMatrix cellAtRow: i column: 0]; 531 [cell setStringValue: [hiddenPaths objectAtIndex: i]]; 532 [cell setLeaf: YES]; 533 } 534 [dirsMatrix sizeToCells]; 535 536 [setDirButt setEnabled: YES]; 537 } 538} 539 540- (IBAction)removeDir:(id)sender 541{ 542 NSArray *cells = [dirsMatrix selectedCells]; 543 544 if (cells) { 545 NSMutableArray *paths = [NSMutableArray arrayWithCapacity: 1]; 546 NSUInteger i; 547 548 for (i = 0; i < [cells count]; i++) { 549 NSString *path = [[cells objectAtIndex: i] stringValue]; 550 [hiddenPaths removeObject: path]; 551 [paths addObject: path]; 552 } 553 554 [self removeCellsWithNames: paths inMatrix: dirsMatrix]; 555 [setDirButt setEnabled: YES]; 556 } 557} 558 559- (IBAction)activateDirChanges:(id)sender 560{ 561 [[FSNodeRep sharedInstance] setHiddenPaths: hiddenPaths]; 562 [gw hiddenFilesDidChange: hiddenPaths]; 563 [setDirButt setEnabled: NO]; 564} 565 566- (void)addCellsWithNames:(NSArray *)names inMatrix:(NSMatrix *)matrix 567{ 568 id cell; 569 NSSize cs, ms; 570 NSUInteger i; 571 572 [matrix setIntercellSpacing: NSMakeSize(0, 0)]; 573 574 for (i = 0; i < [names count]; i++) { 575 [matrix addRow]; 576 cell = [matrix cellAtRow: [[matrix cells] count] -1 column: 0]; 577 [cell setStringValue: [names objectAtIndex: i]]; 578 [cell setLeaf: YES]; 579 } 580 581 if (matrix == leftMatrix) { 582 cs = [leftScroll contentSize]; 583 } else { 584 cs = [rightScroll contentSize]; 585 } 586 ms = [matrix cellSize]; 587 ms.width = cs.width; 588 CHECKSIZE (ms); 589 [matrix setCellSize: ms]; 590 [matrix sizeToCells]; 591 592 [self selectCellsWithNames: names inMatrix: matrix]; 593 594 [matrix setNeedsDisplay: YES]; 595} 596 597- (void)removeCellsWithNames:(NSArray *)names inMatrix:(NSMatrix *)matrix 598{ 599 id cell; 600 NSUInteger i; 601 602 for (i = 0; i < [names count]; i++) { 603 cell = [self cellWithTitle: [names objectAtIndex: i] inMatrix: matrix]; 604 605 if (cell != nil) { 606 NSInteger row, col; 607 608 [matrix getRow: &row column: &col ofCell: cell]; 609 [matrix removeRow: row]; 610 } 611 } 612 613 [matrix sizeToCells]; 614 [matrix setNeedsDisplay: YES]; 615} 616 617- (void)selectCellsWithNames:(NSArray *)names inMatrix:(NSMatrix *)matrix 618{ 619 NSUInteger i, count; 620 NSInteger max; 621 NSInteger *selectedIndexes = NULL; 622 NSMutableArray *cells; 623 624 cells = [NSMutableArray arrayWithCapacity: 1]; 625 for (i = 0; i < [names count]; i++) { 626 NSString *name = [names objectAtIndex: i]; 627 id cell = [self cellWithTitle: name inMatrix: matrix]; 628 629 if (cell) { 630 [cells addObject: cell]; 631 } 632 } 633 634 count = [cells count]; 635 max = [matrix numberOfRows]; 636 selectedIndexes = NSZoneMalloc(NSDefaultMallocZone(), sizeof(NSInteger) * count); 637 638 for (i = 0; i < count; i++) { 639 NSCell *cell; 640 NSInteger sRow, sColumn; 641 642 cell = [cells objectAtIndex: i]; 643 [matrix getRow: &sRow column: &sColumn ofCell: cell]; 644 selectedIndexes[i] = sRow; 645 } 646 647 for (i = 0; i < count; i++) { 648 if (selectedIndexes[i] > max) { 649 break; 650 } 651 [matrix selectCellAtRow: selectedIndexes[i] column: 0]; 652 } 653 654 NSZoneFree(NSDefaultMallocZone(), selectedIndexes); 655} 656 657- (id)cellWithTitle:(NSString *)title inMatrix:(NSMatrix *)matrix 658{ 659 NSArray *cells; 660 id cell; 661 NSUInteger i; 662 663 cells = [matrix cells]; 664 if (cells) { 665 for (i = 0; i < [cells count]; i++) { 666 cell = [cells objectAtIndex: i]; 667 if ([[cell stringValue] isEqualToString: title]) { 668 return cell; 669 } 670 } 671 } 672 673 return nil; 674} 675 676@end 677