Logo Search packages:      
Sourcecode: zipper.app version File versions  Download package

ZipperDocument.m

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Renaissance/Renaissance.h>
#import "ZipperDocument.h"
#import "ZipperCell.h"
#import "Archive.h"
#import "TableViewDataSource.h"
#import "PreferencesController.h"
#import "Preferences.h"
#import "NSFileManager+Custom.h"
#import "FileInfo.h"

@interface ZipperDocument (PrivateAPI)
- (BOOL)openArchiveWithPath:(NSString *)path;
- (void)addRatioColumn;
- (void)removeRatioColumn;
- (void)extractIncludingPathInfo:(BOOL)includePathInfo;
- (void)setArchive:(Archive *)archive;
- (void)openFile:(NSString *)file withDefaultApp:(NSString *)defaultApp;
- (Class)archiveClassForFile:(NSString *)filename;
@end

@implementation ZipperDocument : GSMarkupDocument

- (id)init
{
      [super init];
      _tableViewDataSource = nil;
      return self;
}

- (void)dealloc
{
      [_archive release];
      [_tableViewDataSource release];
      [super dealloc];
}

//-----------------------------------------------------------------------------
// NSDocument overrides
//-----------------------------------------------------------------------------
/*" Name of the .gsmarkup file to load */
- (NSString *)windowNibName
{
      return @"Zipper";
}

/*" Override of NSDocument, called when document is about to be opened */
- (void)windowControllerDidLoadNib:(NSWindowController *)controller;
{
      NSSize size;
      NSTableColumn *tableColumn;
      NSCell *cell = [[ZipperCell alloc] init];

      [super windowControllerDidLoadNib: controller];
      
      // allow for a little bit more space between the columns
      size = [_tableView intercellSpacing];
      size.width += 5.0;
      [_tableView setIntercellSpacing:size];
            
      // right-align the size column
      tableColumn = [_tableView tableColumnWithIdentifier:COL_ID_SIZE];
      [[tableColumn dataCell] setAlignment:NSRightTextAlignment];
      // set the ZipperCell for the name column
      tableColumn = [_tableView tableColumnWithIdentifier:COL_ID_NAME];
      [tableColumn setDataCell:cell];
      [cell release];   
}

- (BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)docType
{
      return [self openArchiveWithPath:fileName];
}

//-----------------------------------------------------------------------------
// Opening archive files
//-----------------------------------------------------------------------------
- (BOOL)openArchiveWithPath:(NSString *)path
{
      Class archiveClass = nil;

      archiveClass = [self archiveClassForFile:path];
      if ([archiveClass hasRatio])
      {
            [self addRatioColumn];
      }
      else
      {
            [self removeRatioColumn];
      }
            
      [self setArchive:[archiveClass newWithPath:path]];
      [_archive sortByFilename];
      [_tableView reloadData];

      return YES;
}

- (Class)archiveClassForFile:(NSString *)path
{
      NSString *extension, *secondExtension;
      Class archiveClass = nil;

      extension = [[path pathExtension] lowercaseString];
      secondExtension = [[[path stringByDeletingPathExtension] pathExtension] lowercaseString];

      if ([extension isEqual:@""] == NO)
      {
            NSString *fullExtension;
            
            if ([secondExtension isEqual:@""]) 
            {
                  // extension is .gz, .bz etc.
                  fullExtension = extension;
            }
            else 
            {
                  // extension is .tar.gz etc.
                  fullExtension = [secondExtension stringByAppendingPathExtension:extension];
            }

            archiveClass = [Archive classForFileExtension:fullExtension];
            if (archiveClass == nil)
            {
                  NSLog(@"No archive class registered for '%@'.", fullExtension);
                  
                  // try only the last extension
                  archiveClass = [Archive classForFileExtension:extension];
                  NSAssert1(archiveClass != nil, 
                        @"No archive class registered for '%@'. This should not happen", extension);  
            }
            

            if ([archiveClass executableDoesExist] == NO)
            {
                  // ouch, no executable set (yet)
                  NSString *message;
                  PreferencesController *prefsController;
      
                  message = [NSString stringWithFormat:
                        @"Missing unarchiver for file extension \"%@\". Please provide a value!", fullExtension];
                  NSRunAlertPanel(@"Error in Preferences", message, nil, nil, nil);
                        
                  // bring up the prefs panel
                  prefsController = [[PreferencesController alloc] init];
                  [prefsController setArchiveForRequiredType:archiveClass];
                  [prefsController showPreferencesPanel];
            }
      }

      return archiveClass;    
}

//-----------------------------------------------------------------------------
// validating the UI
//-----------------------------------------------------------------------------
- (BOOL)validateMenuItem:(NSMenuItem *)anItem
{
      SEL   action = [anItem action];
      
      if (sel_eq(action, @selector(openFile:)) ||     sel_eq(action, @selector(showPreferences:))) 
      {
            return YES;
      }
      
      // enable the extract menu item only if we have something to extract
      if (_archive == nil)
      {
            return NO;
      }
      // do not enable the 'extract flat' menu item if the extractor does not support it
      if (([anItem tag] == 2) && ([[_archive class] canExtractWithoutFullPath] == NO))
      {
            return NO;
      }
      return YES;
}

//------------------------------------------------------------------------------
// action methods
//------------------------------------------------------------------------------
- (void)extract:(id)sender
{
      [self extractIncludingPathInfo:YES];
}

- (void)extractFlat:(id)sender
{
      [self extractIncludingPathInfo:NO];
}

- (void)extractIncludingPathInfo:(BOOL)includePathInfo
{
      NSOpenPanel *openPanel;
      int rc;

      if (_archive == nil)
      {
            return;
      }

      openPanel = [NSOpenPanel openPanel];
      [openPanel setTitle:@"Extract to"];
      [openPanel setCanChooseFiles:NO];
      [openPanel setCanChooseDirectories:YES];
      
      rc = [openPanel runModalForDirectory:[Preferences lastExtractDirectory] file:nil types:nil];
      if (rc == NSOKButton)
      {
            NSString *message;
            NSString *path = [openPanel directory];

            if ([_tableView selectedRow] == -1)
            {
                  // no rows selected ... extract the whole archive
                  [_archive expandFiles:nil withPathInfo:includePathInfo toPath:path];
            }
            else
            {
                  NSNumber *rowIndex;

                  // retrieve selected rows && extract them
                  NSMutableArray *extractFiles = [NSMutableArray array];
                  NSEnumerator *rows = [_tableView selectedRowEnumerator];
                  while ((rowIndex = [rows nextObject]) != nil)
                  {
                        [extractFiles addObject:[_archive elementAtIndex:[rowIndex intValue]]]; 
                  }
                  [_archive expandFiles:extractFiles withPathInfo:includePathInfo toPath:path];
            }
            
            // save the selected directory for later
            [Preferences setLastExtractDirectory:path];

            message = [NSString stringWithFormat:@"Successfully expanded to %@", path];
            NSRunAlertPanel(@"Expand", message, nil, nil, nil);
      }
}

- (void)tableViewDoubleAction:(id)sender
{
      NSEnumerator *enumerator;
      NSMutableArray *filesToExtract;
      NSNumber *row;
      NSString *tempDir;
      FileInfo *info;
      
      // collect all files to extract
      filesToExtract = [NSMutableArray array];
      enumerator = [_tableView selectedRowEnumerator];
      while ((row = [enumerator nextObject]) != nil)
      {
            [filesToExtract addObject:[_archive elementAtIndex:[row intValue]]];
      }
      
      tempDir = [[NSFileManager defaultManager] createTemporaryDirectory];
      [_archive expandFiles:filesToExtract withPathInfo:YES toPath:tempDir];
      // NSWorkspace hopefully knows how to handle the file
      enumerator = [filesToExtract objectEnumerator];
      while ((info = [enumerator nextObject]) != nil)
      {
            NSString *tempFile;
            
            tempFile = [NSString pathWithComponents:[NSArray arrayWithObjects:tempDir, 
                  [info fullPath], nil]];
            [self openFile:tempFile withDefaultApp:[Preferences defaultOpenApp]];
      }
}

//------------------------------------------------------------------------------
// private API
//------------------------------------------------------------------------------
- (void)addRatioColumn
{
      NSTableColumn *ratioColumn;
      int colIndex;
            
      // do it only if the tableView was already loaded
      if (_tableView != nil)
      {     
            ratioColumn = [_tableView tableColumnWithIdentifier:COL_ID_RATIO];
            if (ratioColumn == nil)
            {
                  ratioColumn = [[[NSTableColumn alloc] initWithIdentifier:COL_ID_RATIO] autorelease];
                  [[ratioColumn headerCell] setStringValue:@"Ratio"];
                  [ratioColumn setWidth:50.0];
                  [[ratioColumn dataCell] setAlignment:NSRightTextAlignment];
                  [_tableView addTableColumn:ratioColumn];
            }
            
            // here we have a ratio column for sure
            colIndex = [_tableView columnWithIdentifier:COL_ID_RATIO];
            [_tableView moveColumn:colIndex toColumn:3];

            [_tableView reloadData];
      }
}

- (void)removeRatioColumn;
{     
      if (_tableView != nil)
      {           
            NSTableColumn *ratioCol;

            ratioCol = [_tableView tableColumnWithIdentifier:COL_ID_RATIO];
            if (ratioCol != nil)
            {
                  [_tableView removeTableColumn:ratioCol];
            }
      }
}

/**
 * Returns the DataSource for our table view
 */
00317 - (TableViewDataSource *)tableViewDataSource
{
      if (_tableViewDataSource == nil)
      {
            _tableViewDataSource = [[TableViewDataSource alloc] init];
            [_tableViewDataSource setArchive:_archive];
      }
      return _tableViewDataSource;
}

- (void)setArchive:(Archive *)archive
{
      ASSIGN(_archive, archive);
      // make sure the data source knows the archive as well
      [_tableViewDataSource setArchive:archive];
}

- (void)openFile:(NSString *)file withDefaultApp:(NSString *)defaultApp;
{
      NSString *extension;
      int rc;
      
      extension = [file pathExtension];
      // this sux: if the file does not have an extension, NSWorkspace does not know how to 
      // handle it. Handling of files should be based on file's contents instead of its 
      // extension, like the unix command 'file' does.
      if ([extension isEqual:@""])
      {
            if (defaultApp == nil)
            {
                  NSRunAlertPanel(@"Could not open", @"No default open application set in preferences", 
                        nil, nil, nil);
                  return;
            }
            else
            {
                  rc = [[NSWorkspace sharedWorkspace] openFile:file withApplication:defaultApp];
            }
      }
      else
      {
            // we have a valid path extension, try opening with NSWorkspace's default app
            rc = [[NSWorkspace sharedWorkspace] openFile:file];
            if (rc == NO)
            {
                  // NSWorkspace could not open the file, try again with the default app we've been given
                  if (defaultApp != nil)
                  {
                        rc = [[NSWorkspace sharedWorkspace] openFile:file withApplication:defaultApp];
                  }
                  else
                  {
                        NSRunAlertPanel(@"Could not open", @"No default open application set in preferences", 
                              nil, nil, nil);
                        return;
                  }
            }
      }
                  
      if (rc == NO)
      {
            NSRunAlertPanel(@"Could not open", @"Don't know how to open file %@", nil, nil, nil, file);
      }
}

@end

Generated by  Doxygen 1.6.0   Back to index