ProjectManager  0.2
UtilityFunctions.h
00001 /*
00002     UtilityFunctions.h
00003 
00004     Utility static functions for the FileManager class of ProjectManager.
00005 
00006     Copyright (C) 2005  Saso Kiselkov
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00021 */
00022 
00023 #import <Foundation/NSError.h>
00024 #import <Foundation/NSString.h>
00025 #import <Foundation/NSArray.h>
00026 #import <Foundation/NSBundle.h>
00027 #import <Foundation/NSFileManager.h>
00028 #import <Foundation/NSNotification.h>
00029 #import <Foundation/NSUserDefaults.h>
00030 #import <Foundation/NSException.h>
00031 #import <Foundation/NSValue.h>
00032 
00033 #import <AppKit/NSPanel.h>
00034 #import <AppKit/NSTextField.h>
00035 
00036 #import "FileManager.h"
00037 
00059 static int
00060 DescribeError (NSError * error,
00061                NSString * aTitle,
00062                NSString * aDescription,
00063                NSString * firstButton,
00064                NSString * secondButton,
00065                NSString * thirdButton,
00066                ...)
00067 {
00068   NSString * description;
00069   NSString * prefix, * errorDescription;
00070 
00071   if (aDescription == nil)
00072     {
00073       prefix = @"";
00074     }
00075   else
00076     {
00077       va_list arglist;
00078 
00079       va_start (arglist, thirdButton);
00080       prefix = [NSString stringWithFormat: aDescription arguments: arglist];
00081       va_end (arglist);
00082 
00083       prefix = [prefix stringByAppendingString: _(@": ")];
00084     }
00085 
00086   errorDescription = [[error userInfo] objectForKey:
00087     NSLocalizedDescriptionKey];
00088 
00089   description = [NSString stringWithFormat: @"%@%@", prefix, errorDescription];
00090 
00091   return NSRunAlertPanel (aTitle,
00092                           description,
00093                           firstButton,
00094                           secondButton,
00095                           thirdButton);
00096 }
00097 
00112 static void
00113 SetFileError (NSError ** ptr, int code, NSString * reasonFormat, ...)
00114 {
00115   if (ptr != NULL)
00116     {
00117       NSString * reason;
00118       NSDictionary * userInfo;
00119       va_list arglist;
00120 
00121       va_start (arglist, reasonFormat);
00122       reason = [[[NSString alloc]
00123         initWithFormat: reasonFormat arguments: arglist]
00124         autorelease];
00125       va_end (arglist);
00126 
00127       userInfo = [NSDictionary
00128         dictionaryWithObject: reason forKey: NSLocalizedDescriptionKey];
00129       *ptr = [NSError errorWithDomain: ProjectFilesErrorDomain
00130                                  code: code
00131                              userInfo: userInfo];
00132     }
00133 }
00134 
00148 static void
00149 PostFilesChangedNotification (FileManager * sender, NSString * category)
00150 {
00151   NSDictionary * userInfo;
00152   NSString * projectPath;
00153   static NSNotificationCenter * nc = nil;
00154 
00155   if (nc == nil)
00156     {
00157       nc = [NSNotificationCenter defaultCenter];
00158     }
00159 
00160   projectPath = [[sender document] fileName];
00161   if (category != nil)
00162     {
00163       userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
00164         projectPath, @"Project",
00165         category, @"Category",
00166         nil];
00167     }
00168   else
00169     {
00170       userInfo = [NSDictionary dictionaryWithObject: projectPath
00171                                              forKey: @"Project"];
00172     }
00173 
00174   [nc postNotificationName: ProjectFilesDidChangeNotification
00175                     object: sender
00176                   userInfo: userInfo];
00177 }
00178 
00179 
00186 static inline void
00187 SetTextFieldEnabled (NSTextField * tf, BOOL flag)
00188 {
00189   if ([tf isEnabled] != flag)
00190     {
00191       [tf setEnabled: flag];
00192       [tf setEditable: flag];
00193       [tf setSelectable: flag];
00194       [tf setDrawsBackground: flag];
00195     }
00196 }
00197 
00206 static inline NSString *
00207 MakeSizeStringFromValue (unsigned long long size)
00208 {
00209   if (size < 1024)
00210     {
00211       return [NSString stringWithFormat: _(@"%i bytes"), size];
00212     }
00213   else if (size < 1024 * 1024)
00214     {
00215       return [NSString stringWithFormat: _(@"%.2f kB"), (double) size / 1024];
00216     }
00217   else if (size < 1024 * 1024 * 1024)
00218     {
00219       return [NSString stringWithFormat: _(@"%.2f MB"), (double) size /
00220       (1024 * 1024)];
00221     }
00222   else
00223     {
00224       return [NSString stringWithFormat: _(@"%.2f GB"),
00225         (double) size / (1024 * 1024 * 1024)];
00226     }
00227 }
00228 
00236 static inline NSString *
00237 TranslocateLinkTarget (NSString * linkTarget, NSString * oldLocation,
00238                        NSString * newLocation)
00239 {
00240   // absolute paths do not need to be translocated
00241   if ([linkTarget isAbsolutePath])
00242     {
00243       return linkTarget;
00244     }
00245   else
00246     {
00247       return [newLocation stringByConstructingRelativePathTo:
00248         [oldLocation stringByConcatenatingWithPath: linkTarget]];
00249     }
00250 }
00251 
00256 static BOOL
00257 PurgeUnneededDirectories (NSString * aPath, NSError ** error)
00258 {
00259   NSFileManager * fm = [NSFileManager defaultManager];
00260 
00261   for (;
00262        [[fm directoryContentsAtPath: aPath] count] == 0;
00263        aPath = [aPath stringByDeletingLastPathComponent])
00264     {
00265       if (![fm removeFileAtPath: aPath handler: nil])
00266         {
00267           SetFileError (error, ProjectFilesDeletionError,
00268             _(@"Couldn't delete directory at path %@."), aPath);
00269 
00270           return NO;
00271         }
00272     }
00273 
00274   return YES;
00275 }