Hide variables inside TFUSBController.m.
[MacTF.git] / UIElements.m
blobc834cce784fd9b14aeec7a4905c6be7848417fd5
1 // MacTF Copyright 2004 Nathan Oates
3 /* 
5  * This source code is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Public License as published
7  * by the Free Software Foundation; either version 2 of the License,
8  * or (at your option) any later version.
9  *
10  * This source code is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * Please refer to the GNU Public License for more details.
14  *
15  * You should have received a copy of the GNU Public License along with
16  * this source code; if not, write to:
17  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
20 /* This file was modified by Kalle Olavi Niemitalo on 2007-10-18.  */
22 #import "UIElements.h"
24 @implementation UIElements
26 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:
27         (NSApplication *)theApplication {
28     return YES;
31 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)path
33         if (!connected) 
34                 [self connect:nil];
35         [self uploadPath:path toPath:[NSString stringWithString:currentPath]];
36         NSLog(@"DockUpload:%@", path);
37         return YES;
40 -(void) awakeFromNib {
41         [mainWindow setTitleBarHeight:22.0];
42         [mainWindow setBottomBarHeight:18.0];
43         [mainWindow setMidBarHeight: 32.0 origin:40.0];
44         connected = NO;
45         paused = NO;
46         highlightImageData = @"<4d4d002a 00000048 800f4f6d a2ca65ca 564b390a 69371941 1ee22622 dc04743b 7c86826e 900fcdb1 d9e5b237 3ab60647 06b0b8d8 d5151a1a 82732348 46616888 4bcd00f9 719f0100 000d0100 00030000 00010001 00000101 00030000 00010012 00000102 00030000 00030000 00ea0103 00030000 00010005 00000106 00030000 00010002 00000111 00040000 00010000 00080115 00030000 00010003 00000116 00040000 00010000 2aaa0117 00040000 00010000 003f011a 00050000 00010000 00f0011b 00050000 00010000 00f8011c 00030000 00010001 00000128 00030000 00010002 00000000 00000008 00080008 000afc80 00002710 000afc80 00002710 >";
47         currentPath = [[NSString stringWithString:@"\\"] retain];
48         [currentlyField setStringValue:NSLocalizedString(@"IDLE", @"Idle")];
49         [currentlyField displayIfNeeded];
50         [tableView setDoubleAction: @selector(doubleClick:)];
51         [tableView setTarget: self];
52         [tableView registerForDraggedTypes: [NSArray arrayWithObjects: @"NSFilenamesPboardType", @"NSFilenamesPboardType", nil]];
53         tfusbc = [[TFUSBController alloc] init];
54         [tfusbc setDH:dh tableView:tableView]; //send needed items to tfusbc
55         sortAscending = TRUE;
56         [turboCB setState:0];
57         [turboCB setEnabled:NO];
58         [versionField setStringValue:[[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleVersion"]]; 
59         [pathBar setEnabled:YES];
60         [[pathBar cell] setSegmentCount:1];
61         [[pathBar cell] setLabel:@"Path:" forSegment:0];
62         [[pathBar cell] setWidth:0 forSegment:0];
63         [pathBar sizeToFit];
64         [[dh fileList] addObject:[NSDictionary dictionaryWithObject:NSLocalizedString(@"NOT_CONNECTED_ENTRY", @"Not connected") forKey:@"name"]];
65         [tableView reloadData];
66         prefs = [[NSUserDefaults standardUserDefaults] retain];
67         if ([prefs boolForKey:@"auto-connect"]) {
68                 [self connect:nil];
69                 [autoCB setState:1];    
70         }
73 - (BOOL)validateMenuItem:(NSMenuItem*)anItem {
74     if ([[anItem title] isEqualToString:NSLocalizedString(@"DL_MENUITEM", @"Download")] && (1 > [tableView numberOfSelectedRows])) {
75         return NO;
76     }
77         if ([[anItem title] isEqualToString:NSLocalizedString(@"DEL_MENUITEM", @"Delete")] && (1 > [tableView numberOfSelectedRows])) {
78         return NO;
79     }
80         if ([[anItem title] isEqualToString:NSLocalizedString(@"RN_MENUITEM", @"Rename")] && (1 != [tableView numberOfSelectedRows])) {
81         return NO;
82     }
83         if ([[anItem title] isEqualToString:NSLocalizedString(@"UL_MENUITEM", @"Upload")] && (! connected)) {
84         return NO;
85     }
86         if ([[anItem title] isEqualToString:NSLocalizedString(@"NF_MENUITEM", @"NewFolder")] && (! connected)) {
87         return NO;
88     }
89     return YES;
92 - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem {
93     if ([[toolbarItem itemIdentifier] isEqual:@"ConnectTBIcon"]) {
94                 if (connected) {
95                         [toolbarItem setLabel:NSLocalizedString(@"DC_BUTTON", @"Disconnect")];
96                 } else {
97                         [toolbarItem setLabel:NSLocalizedString(@"CON_BUTTON", @"Connect")];
98                 }
99         }
100         if ([[toolbarItem itemIdentifier] isEqual:@"UploadTBIcon"] && (! connected)) {
101                 return NO;
102         }
103         if ([[toolbarItem itemIdentifier] isEqual:@"NewFolderTBIcon"] && (! connected)) {
104                 return NO;
105         }
106         if ([[toolbarItem itemIdentifier] isEqual:@"TurboTBIcon"] && (! connected)) {
107                 return NO;
108         }
109         if ([[toolbarItem itemIdentifier] isEqual:@"DownloadTBIcon"] && (1 > [tableView numberOfSelectedRows] || !connected)) {
110                 return NO;
111         }
112         if ([[toolbarItem itemIdentifier] isEqual:@"DeleteTBIcon"] && (1 > [tableView numberOfSelectedRows] || !connected)) {
113                 return NO;
114         }
115         if ([[toolbarItem itemIdentifier] isEqual:@"RenameTBIcon"] && (1 != [tableView numberOfSelectedRows] || !connected)) {
116                 return NO;
117         }
118     return YES;
122 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
124         [preview setString:@""];
125         if ([previewDrawer state] == NSDrawerClosedState) return; // don't bother getting previews if closed
126         if ([tableView numberOfSelectedRows] != 1 || !connected)
127                 return;
128         if ([[tfusbc transferQueue] count] > 0) return; //for now, change to a priority transfer later?
129         id currentSelectedItem = [[dh displayedList] objectAtIndex:[tableView selectedRow]];
130         int type = [[currentSelectedItem objectForKey:@"type"] intValue];
131         if (type == 2) { //file
132                 NSString* nameOnToppy = [currentSelectedItem objectForKey:@"name"]; 
133                 if (([nameOnToppy hasSuffix:@".ini"] || [nameOnToppy hasSuffix:@".txt"] || [nameOnToppy hasSuffix:@".tgd"] || [nameOnToppy hasSuffix:@".tsv"] || [nameOnToppy hasSuffix:@".dat"] || [nameOnToppy hasSuffix:@".tap"])) {
134                         [drawerTabView selectTabViewItemAtIndex:0];
135                         NSString* tempFile = NSTemporaryDirectory(); // download preview to temp folder
136                         tempFile = [tempFile stringByAppendingPathComponent:@"MacTFTemp"];
137                         [tfusbc addTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"filename",currentPath,@"path",tempFile,@"savePath",[NSNumber numberWithUnsignedLongLong:0],@"offset",@"download",@"transferType",[NSNumber numberWithBool:NO],@"looping",[NSNumber numberWithInt:0],@"existingTime",nil] atIndex:-1];
138                         while ([[tfusbc transferQueue] count] > 0) {
139                                 usleep(10);
140                         }
141                         [preview setString:[NSString stringWithContentsOfFile:tempFile]];
142                 } else if ([nameOnToppy hasSuffix:@".rec"]) { //display headers
143                         [drawerTabView selectTabViewItemAtIndex:1];
144                         NSString* tempFile = NSTemporaryDirectory(); // download first 64k to temp folder
145                         tempFile = [tempFile stringByAppendingPathComponent:@"MacTFTemp"];
146                         [tfusbc addTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"filename",currentPath,@"path",tempFile,@"savePath",[NSNumber numberWithUnsignedLongLong:0],@"offset",@"download",@"transferType",[NSNumber numberWithBool:NO],@"looping",[NSNumber numberWithInt:0],@"existingTime",nil] atIndex:-1];
147                         while ([[tfusbc transferQueue] count] > 0) {
148                                 usleep(10);
149                         }
150                         NSDictionary* recData = [dh extractDataFromRecHeader:tempFile forModel:[prefs objectForKey:@"modelType"]]; //then parse and display headers
151                         [recStart setObjectValue:[recData objectForKey:@"startTime"]];
152                         [recDuration setObjectValue:[recData objectForKey:@"duration"]];
153                         [recDescription setStringValue:[recData objectForKey:@"description"]];
154                         [recName setStringValue:[recData objectForKey:@"name"]];
155                         [recExtInfo setStringValue:[recData objectForKey:@"extInfo"]];
156                         [recChannel setStringValue:[recData objectForKey:@"channel"]];
157                 }       
158                 else {
159                         [drawerTabView selectTabViewItemAtIndex:0];
160                         return;
161                 }
162         } else if (type == 1) { //folder
163                 [drawerTabView selectTabViewItemAtIndex:0];
164                 return;
165         } else {
166                 [statusField setStringValue:NSLocalizedString(@"SEL_ERROR", @"Selection error...")];
167                 return;
168         }
171 - (void) setAvailableSpace:(NSData*)input {
172         [availSpaceField setStringValue:[self prepForSizeDisplay:input]];
175 - (void) setFreeSpace:(NSData*) input {
176         [freeSpaceField setStringValue:[self prepForSizeDisplay:input]];
179 - (NSString*) prepForSizeDisplay:(NSData*) input {
180         UInt32 size_bigendian;
181         [input getBytes:&size_bigendian];
182         unsigned size = EndianU32_BtoN(size_bigendian);
183         NSString *ret = nil;
184                 if( size == 0. ) ret = NSLocalizedString( @" - ", "no file size" );
185                 else if( size > 0. && size < 1024. ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.0f KB", "file size measured in kilobytes" ), size];
186                 else if( size >= 1024. && size < pow( 1024., 2. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.1f MB", "file size measured in megabytes" ), ( size / 1024. )];
187                 else if( size >= pow( 1024., 2. ) && size < pow( 1024., 3. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.2f GB", "file size measured in gigabytes" ), ( size / pow( 1024., 2. ) )];
188                 else if( size >= pow( 1024., 3. ) && size < pow( 1024., 4. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.3f TB", "file size measured in terabytes" ), ( size / pow( 1024., 3. ) )];
189                 else if( size >= pow( 1024., 4. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.4f PB", "file size measured in pentabytes" ), ( size / pow( 1024., 4. ) )];
190         return ret;
193 - (IBAction) connect: (id) sender { 
194         if (! connected) {
195                 context = [tfusbc initializeUSB];
196                 if (context == nil) {
197                         [statusField setStringValue:NSLocalizedString(@"INIT_PROBLEM", @"Message when initialization fails.")];
198                         return;
199                 }
200                 // add a check here to see if really connected...
201                 connected = YES;
202                 [[dh fileList] removeAllObjects];
203                 [[dh fileList] addObject:[NSDictionary dictionaryWithObject:NSLocalizedString(@"FETCHING", @"Fetching") forKey:@"name"]];
204                 [tableView reloadData];
205                 [tfusbc clearQueues];
206                 paused = NO;
207                 [turboCB setState:0];
208                 [turboCB setEnabled:YES];
209                 [[pathBar cell] setSegmentCount:2];
210                 [[pathBar cell] setLabel:@"Path:" forSegment:0];
211                 [[pathBar cell] setLabel:@"\\" forSegment:1];
212                 [[pathBar cell] setWidth:0 forSegment:0];
213                 [[pathBar cell] setWidth:0 forSegment:1];
214                 [pathBar sizeToFit];
215                 [pathBar setHidden:NO];
216                 [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
217                 [connectButton setTitle:NSLocalizedString(@"DC_BUTTON", @"Disconnect.")];
218                 [statusField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"CONNECTED_MESSAGE", @"Message giving connection speed."), [tfusbc getSpeed]]];
219                 [NSThread detachNewThreadSelector:@selector(transfer:) toTarget:tfusbc withObject:nil];
220         } else { // already connected
221                 connected = NO;
222                 if ([[tfusbc transferQueue] count] != 0) { //gives a few seconds for busy thread to notice it should not be connected before cutting the device off
223                         sleep(3);
224                 }
225                 [tfusbc closeDevice:context];
226                 [connectButton setTitle:NSLocalizedString(@"CON_BUTTON", @"Connect.")];
227                 [statusField setStringValue:NSLocalizedString(@"NO_CONNECT", @"No connection.")];
228                 [[dh fileList] removeAllObjects];
229                 [tableView reloadData];
230                 [turboCB setState:0];
231                 [turboCB setEnabled:NO];
232                 [connectLight setImage:[NSImage imageNamed:@"red.tiff"]];
233                 currentPath = @"\\";
234                 return;
235         }
236         int ret = [self goToPath:@"\\"];
237         if (ret == 1) { 
238                 sleep (5); //error, wait a few secs for HDD to start if need be then try again
239                 [self goToPath:@"\\"];
240         }
241         currentPath = @"\\";
244 - (int) goToPath:(NSString*) path {
245         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:path,@"path",@"fileList",@"transferType",nil]];
246         // FIXME: The caller would like to know whether the operation succeeded.
247         // But it has not even finished yet.  So goToPath should somehow notify
248         // the caller on completion.
249         return 0;
252 - (void)doubleClick:(id)sender
254         if ([tableView numberOfSelectedRows] != 1)
255                 return;
256         id currentSelectedItem = [[dh displayedList] objectAtIndex:[tableView selectedRow]];
257         int type = [[currentSelectedItem objectForKey:@"type"] intValue];
258         if (type == 2) { //file
259                 [self downloadFileDoubleClickThread:nil];
260         } else if (type == 1) { //folder
261                 NSString* currentName = [currentSelectedItem objectForKey:@"name"];
262                 if ([currentName isEqualToString:@".. (Parent folder)"]) { // move up
263                         NSMutableArray* array = [NSMutableArray arrayWithArray:[currentPath componentsSeparatedByString:@"\\"]];
264                         if ([array count] > 1){ // not going to root
265                                 [array removeLastObject];
266                                 NSString* temp = [NSString stringWithString:[array componentsJoinedByString:@"\\"]];
267                                 if ([self goToPath:temp]) {// if error
268                                         [self goToPath:temp]; // hackish workaround
269                                 }
270                                 int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
271                                 NSRect r = [pathBar frame];
272                                 [[pathBar cell] setSegmentCount:segCount-1];
273                                 [pathBar setNeedsDisplayInRect:r];
274                                 [pathBar displayIfNeeded];
275                                 currentPath = [[NSString stringWithString:temp] retain];
276                                 [statusField setStringValue:NSLocalizedString(@"CONNECTED_OK", @"Connection OK")];
277                         } else {//root
278                                 currentPath = @"\\";
279                                 [[pathBar cell] setSegmentCount:1];
280                         }
281                 } else { //move down
282                         NSMutableString* temp = [NSMutableString stringWithString:currentPath];
283                         if (![temp isEqualToString:@"\\"])
284                                         [temp appendString:@"\\"];
285                         [temp appendString:currentName];
286                         if ([self goToPath:temp]) { // if error, try again
287                                 [self goToPath:temp]; // hackish workaround
288                 }
289                         currentPath = [[NSString stringWithString:temp] retain];
290                         int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
291                         NSRect r = [pathBar frame];
292                         [[pathBar cell] setSegmentCount:segCount+1];
293                         [[pathBar cell] setLabel:currentName forSegment:segCount];
294                         [[pathBar cell] setWidth:0 forSegment:segCount];
295                         [pathBar sizeToFit];
296                         [pathBar displayIfNeededInRect:r];
297                         [statusField setStringValue:NSLocalizedString(@"CONNECTED_OK", @"Connection OK")];
298                 }
299         } else {
300                 [statusField setStringValue:NSLocalizedString(@"SEL_ERROR", @"Selection error...")];
301                 return; 
302         }
305 - (void) downloadFileDoubleClickThread:(NSDictionary*)fileInfo {
306         if (! connected) return;
307                 [self downloadSelectedFile:nil];
308 //      [self updateHDDSize];
311 /*- (void) updateHDDSize {
312         if (! connected) return;
313         NSData* hddSizeString = [tfusbc getHDDSize:context];
314         if (hddSizeString != nil) {
315                 [self setAvailableSpace:[hddSizeString subdataWithRange:(NSRange) {8,4}]];
316                 [self setFreeSpace:[hddSizeString subdataWithRange:(NSRange) {12,4}]];
317         } 
320 - (void)tableView:(NSTableView *)tView didClickTableColumn:(NSTableColumn *)tableColumn
322         // Either reverse the sort or change the sorting column
323         NSString* columnIdentifier = [tableColumn identifier];
324         BOOL newSortAscending = !(sortAscending && [tableColumn isEqualTo:selectedColumn]);
325         
326         NSString* sortKey = nil;
327         SEL sortSelector = @selector(compare:);
328         if ([columnIdentifier isEqualToString:@"name"]) {
329                 sortKey = @"name";
330                 sortSelector = @selector(caseInsensitiveCompare:);
331         } else if ([columnIdentifier isEqualToString:@"date"]) {
332                 sortKey = @"sortdate";
333         } else if ([columnIdentifier isEqualToString:@"size"]) {
334                 sortKey = @"fileSize";
335         } else if ([columnIdentifier isEqualToString:@"icon"]) {
336                 sortKey = @"suffix";
337         }
338         if (sortKey == nil)
339                 return;
341         NSSortDescriptor* descriptor = [[[NSSortDescriptor alloc]
342                         initWithKey:sortKey ascending:newSortAscending selector:sortSelector]
343                 autorelease];
344         NSArray* sortedArray = [[dh fileList] sortedArrayUsingDescriptors:
345                 [NSArray arrayWithObject:descriptor]];
346         NSImage* indicatorImage = [NSImage imageNamed:
347                 newSortAscending ? @"NSAscendingSortIndicator" : @"NSDescendingSortIndicator"];
349         sortAscending = newSortAscending;
350         selectedColumn = tableColumn;
351         [tView setIndicatorImage: indicatorImage inTableColumn: tableColumn];
352         // remove other indicators
353         NSMutableArray* otherColumns = [NSMutableArray arrayWithArray:[tView tableColumns]];
354         [otherColumns  removeObject:tableColumn];
355         NSEnumerator* cols = [otherColumns objectEnumerator];
356         id currentCol;
357         while (currentCol = [cols nextObject]) {
358                 [tView setIndicatorImage: nil inTableColumn: currentCol];
359         }
360         [dh setFileList:sortedArray];
361         [dh search:searchField];
362         [dh reloadTable];
366 - (IBAction) downloadSelectedFile:(id)sender{
367         if (! connected)
368                 return;
369         NSLog(@"Download file starting...");
370         NSEnumerator* selected = [tableView selectedRowEnumerator];
371         id currentSelected;
372         while (currentSelected = [selected nextObject]) {
373                 id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
374                 int type = [[currentSelectedItem objectForKey:@"type"] intValue];
375                 if (type == 1) {[statusField setStringValue:NSLocalizedString(@"NO_FOLDER_DL", @"Folder download not supported yet")];}
376                 else if (type == 2) {
377                         NSString* nameOnToppy = [currentSelectedItem objectForKey:@"name"];
378                         NSSavePanel *nssave = [[NSSavePanel savePanel]retain];
379                         int retButton = [nssave runModalForDirectory:nil file:nameOnToppy];
380                         if (retButton) {
381                                 NSString* savePath= [nssave filename]; 
382                                 NSLog(savePath);
383                                 unsigned long long offset = 0;
384                                 NSFileHandle *newFileHandle = [NSFileHandle fileHandleForReadingAtPath:savePath];
385                                 if (!(newFileHandle==nil)) { // there is a file there, ask if want to resume
386                                         NSLog(@"existing file length: %qu", [newFileHandle seekToEndOfFile]);
387                                         //ask to resume, save offset if yes
388                                         //offset = [newFileHandle seekToEndOfFile];
389                                 }
390                                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
391                                 [tfusbc addTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"filename",currentPath,@"path",savePath,@"savePath",[NSNumber numberWithUnsignedLongLong:offset],@"offset",@"download",@"transferType",[NSNumber numberWithBool:YES],@"looping",[NSNumber numberWithInt:0],@"existingTime",nil] atIndex:-1];
392                         }
393                 }               
394         }
395         //              [self updateHDDSize];
396         }
398 - (void) finishTransfer {
399         [currentlyField setStringValue:@""];
400         [progressBar setDoubleValue:0];
401         [[NSSound soundNamed:@"Ping"] play];
402         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
403         [currentlyField setStringValue:NSLocalizedString(@"IDLE", @"Idle")];
404         [currentlyField display];
407 - (IBAction) uploadFile: (id) sender {
408         if (! connected)
409                 return;
410         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
411         [nsop setAllowsMultipleSelection:YES];
412         [nsop setCanChooseFiles:YES];
413         [nsop setCanChooseDirectories:YES];
414         int retButton = [nsop runModal];
415         NSArray *returnedNames = [nsop filenames];      
416         if (retButton == NSFileHandlingPanelCancelButton) {             
417                 NSLog(@"Upload cancelled");
418                 return;
419         }
420         //get info about the chosen file - later if do folders check here and do recursive all things in folder???
421         NSEnumerator *enumerator = [returnedNames objectEnumerator];
422         id returnedName;
423 //      [statusField setStringValue:[NSLocalizedString(@"CONNECTED_OK", @"Connection OK") stringByAppendingString:NSLocalizedString(@"DOWNLOAD", @"Download")]; 
424         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
425         while (returnedName = [enumerator nextObject]) {
426                 NSLog(returnedName);
427                 [self uploadPath:returnedName toPath:[NSString stringWithString:currentPath]];
428         }
433 - (void) uploadPath:(NSString*) path toPath:(NSString*) toPath {
434         if (! connected)
435                 return;
436         NSFileManager* fm = [NSFileManager defaultManager];
437         NSDictionary *fattrs = [fm fileAttributesAtPath:path traverseLink:NO];
438         if (!fattrs) {
439                 NSLog(@"Path of file to upload is incorrect!");
440                 return; }
441         NSString* type = [fattrs fileType];
442         if ([type isEqualToString:@"NSFileTypeDirectory"]) {
443                 // should look to create folder on Toppy, or add stuff if already there (maybe it does this automatically?), and place in subfolders etc
444                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[path lastPathComponent],@"newName",toPath,@"path",@"newFolder",@"transferType", nil]];
445                 NSArray* subPaths = [fm directoryContentsAtPath:path];
446                 NSEnumerator* e = [subPaths objectEnumerator];
447                 id object;
448                 while (object = [e nextObject]) {
449                         NSString* subPath = [NSString stringWithFormat:@"%@/%@", path, object];
450                         NSString* subToPath = [NSString stringWithFormat:@"%@\\%@", toPath, [path lastPathComponent]];
451                 //      NSLog(@"subdir: %@, %@", subPath, subToPath);
452                         if (![object isEqualToString:@".DS_Store"]) {
453                                 [self uploadPath:subPath toPath:subToPath];
454                         }
455                 }
456                 if (connected) { //may have disconnected during threaded upload (although not actually threaded here!)
457         //              [self updateHDDSize];
458                         [self goToPath:currentPath];
459                 }
460         }
461         else {
462                 NSDictionary* fileAttr = [dh extractAttributes:fattrs];         // turn Dict into a new TypeFile dict
463                 NSMutableArray* array = [NSMutableArray arrayWithArray:[path componentsSeparatedByString:@"/"]]; // cut down name
464                 NSString* fileName = [NSString stringWithString:[array lastObject]];
465                 NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
466                 [progressBar setDoubleValue:0];
467                 [currentlyField setStringValue:[NSLocalizedString(@"UPLOADING", @"Uploading") stringByAppendingString:fileName]];
468                 [currentlyField displayIfNeeded];
469                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
470                 [tfusbc addTransfer:[NSDictionary dictionaryWithObjectsAndKeys:path,@"filename",[NSNumber numberWithUnsignedLongLong:[fattrs fileSize]],@"fileSize",toPath,@"path",typeFile,@"attributes",@"upload",@"transferType",[NSNumber numberWithUnsignedLongLong:0],@"offset",[NSNumber numberWithInt:0],@"existingTime",nil] atIndex:-1];
471         }
474 -(IBAction)deleteFile:(id)sender
476         if (! connected)
477                 return;
478         if ( [tableView numberOfSelectedRows] == 0 )
479         return;
480         NSString *title = NSLocalizedString(@"WARNING", @"Warning!");
481     NSString *defaultButton = NSLocalizedString(@"DEL", @"Delete");
482     NSString *alternateButton = NSLocalizedString(@"NO_DEL", @"Don't Delete");
483     NSString *otherButton = nil;
484     NSString *message = NSLocalizedString(@"DEL_MESSAGE", @"Are you sure you want to delete the selected file(s)?");
486     NSBeep();
487     NSBeginAlertSheet(title, defaultButton, alternateButton, otherButton, mainWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, nil, message);
490 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
492     if ( returnCode == NSAlertDefaultReturn ) {
493                 NSLog(@"Deleting file(s) starting...");
494                 NSEnumerator* selected = [tableView selectedRowEnumerator];
495                 id currentSelected;
496                 while (currentSelected = [selected nextObject]) {
497                         id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
498                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"file",currentPath,@"path",@"delete",@"transferType", nil]];
499                 }
500         //      [self updateHDDSize];
501                 [self goToPath:currentPath];
502                 //should check so don't delete root folders?
503         }
506 - (IBAction)openPrefsSheet:(id)sender
508         [NSApp beginSheet:prefsWindow
509            modalForWindow:mainWindow
510                 modalDelegate:self
511            didEndSelector:@selector(mySheetDidEnd:returnCode:contextInfo:)
512           contextInfo: nil];
513         return;  // leave without doing anything else
516 - (IBAction) mySheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
517                            contextInfo:(void *)contextInfo {
518         
519         [sheet orderOut:self];
520         if(returnCode == 0)  return;
521         // continue with application  
524 - (IBAction)closePrefsSheet:(id)sender
526         //do changes to prefs here
527         //    if (connected) {
528         [tfusbc setDebug:[debugCB state]]; 
529         //  }
530         NSLog(@"auto: %i", [autoCB state]);
531         [prefs setBool:[autoCB state] forKey:@"auto-connect"];
532 //      [prefs setBool:[epgCB state] forKey:@"epgSync"];
533         [prefs synchronize];
534         [NSApp endSheet:prefsWindow returnCode:1];
537 - (IBAction)openRenameSheet:(id)sender
539         if ( [tableView numberOfSelectedRows] != 1 )
540         return;
541         [renameOld setStringValue:[[[dh displayedList] objectAtIndex:[tableView selectedRow]] objectForKey:@"name"]];
542         [renameNew setStringValue:[renameOld stringValue]];
543 //      [renameWindow setTitleBarHeight:0.0];
544         [NSApp beginSheet: renameWindow
545            modalForWindow: mainWindow
546                 modalDelegate: nil
547            didEndSelector: nil
548                   contextInfo: nil];
549     [NSApp runModalForWindow: renameWindow];
550     // Sheet is up here.
553 - (IBAction)cancelRename:(id)sender{
554         [NSApp endSheet: renameWindow];
555     [renameWindow orderOut: self];
556         [NSApp stopModal];
559 - (IBAction)closeRenameSheet:(id)sender
561         //do changes to rename here
562         if (connected) {
563                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[renameOld stringValue],@"oldName",[renameNew stringValue],@"newName", currentPath,@"path",@"rename",@"transferType",nil]];
564                 [self goToPath:currentPath];
565         }
566                 //then close up
567         [self cancelRename:sender];
571 - (IBAction)openNewFolderSheet:(id)sender
573         [NSApp beginSheet: newFolderWindow
574            modalForWindow: mainWindow
575                 modalDelegate: nil
576            didEndSelector: nil
577                   contextInfo: nil];
578     [NSApp runModalForWindow: newFolderWindow];
579     // Sheet is up here.
580         
583 - (IBAction)cancelNewFolder:(id)sender{
584         [NSApp endSheet: newFolderWindow];
585     [newFolderWindow orderOut: self];
586         [NSApp stopModal];
589 - (IBAction)closeNewFolderSheet:(id)sender
591         //do changes to make new folder here
592         if (connected) {
593                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[newFolderNew stringValue],@"newName",currentPath,@"path",@"newFolder",@"transferType", nil]];
594                 [self goToPath:currentPath];
595         }
596         //then close up
597         [self cancelNewFolder:sender];
600 - (IBAction)pathBarClick:(id)sender {
601         int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
602         int selectedSegment = [sender selectedSegment]; 
603         if (selectedSegment == segCount - 1) return; //no need to move anywhere
604         int i = 1; // remember have "path" there too 
605         NSMutableArray* pathArray = [NSMutableArray arrayWithCapacity:selectedSegment];
606         while (i<=selectedSegment) {
607                 [pathArray addObject:[[pathBar cell] labelForSegment:i]];
608                 i++;
609         } 
610         NSString* pathString = [pathArray componentsJoinedByString:@"\\"];
611         if ([pathString hasPrefix:@"\\\\"]) pathString = [pathString substringFromIndex:1];
612         [self goToPath:pathString];
613         currentPath = [[NSString stringWithString:pathString] retain];
614         NSRect r = [pathBar frame];
615         [[pathBar cell] setSegmentCount:selectedSegment+1];
616         [pathBar displayIfNeededInRect:r];      
619 - (id)getTfusbc {
620         return tfusbc;
623 - (USBDeviceContext*) getContext {
624         return context;
627 - (NSNumber*) isConnected {
628         return [NSNumber numberWithBool:connected];
632 - (NSString*) currentPath {
633         return currentPath;
636 - (IBAction) toggleTurbo:(id)sender {
637         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
638                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
639         }
642 - (IBAction) toggleTurboCB:(id)sender {
643         if (! connected)
644                 return;
645         if ([turboCB state]) { // currently on, want off
646                 [turboCB setState:0];
647         } else {
648                 [turboCB setState:1];
649         }
650         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
651                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
652         }
655 - (IBAction) togglePreview:(id)sender {
656                 [previewDrawer toggle:sender];
659 /*- (IBAction) snapshot:(id) sender {
660         NSArray* snapshotData = [self snapshotOfPath:@"\\"];
661         [dh setSnapShot:snapshotData];
662         // show snapshot window
663         [snapshotWindow makeKeyAndOrderFront:sender];
664         [outlineView reloadData];
667 - (NSArray*) snapshotOfPath:(NSString*)path {
668         
669 NSData* hddFileData = [tfusbc getFileList:context forPath:path];
670 NSData* checkForError = [hddFileData subdataWithRange:(NSRange){4,4}];
671 const UInt32 check_bigendian = EndianU32_NtoB(USB_Fail);
672 const UInt32 check2_bigendian = EndianU32_NtoB(USB_DataHddDir);
673 if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
674         [statusField setStringValue:@"Connected - error on last command"];
676 if (! [checkForError isEqualToData:[NSData dataWithBytes:&check2_bigendian length:4]]) {
677         hddFileData = [tfusbc getFileList:context forPath:path]; //try again
678         if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
679                 [statusField setStringValue:@"Connected - error on last command"];
680         }
682 hddFileData = [hddFileData subdataWithRange:(NSRange) {8, [hddFileData length]-8}]; // cut off header and cmd 
683 int i;
684 NSMutableArray* paths = [[NSMutableArray alloc] init];
685 for (i=0; i*114 < [hddFileData length]-4; i++) { // 4 is there cause swapping sometimes adds a byte of padding  
686         NSData* temp = [hddFileData subdataWithRange:(NSRange) {i*114,114}];
687         NSMutableDictionary* tfFile = [dh getTFFileFromSwappedHexData:temp];
688         [dh convertRawDataToUseful:tfFile];
689         if (!([[tfFile objectForKey:@"name"] isEqualToString:@".."])) {
690                 if ([[tfFile objectForKey:@"type"] intValue] == 1) { //folder
691                         NSMutableString* temp = [NSMutableString stringWithString:path];
692                         if (![temp isEqualToString:@"\\"])
693                                 [temp appendString:@"\\"];
694                         [temp appendString:[tfFile objectForKey:@"name"]];
695                         [paths addObject:tfFile];
696                         [paths addObject:[self snapshotOfPath:temp]];
697                 } else {
698                         [paths addObject:tfFile];
699                 }
700         }
702 return paths;
707 /*- (IBAction) epg:(id) sender {
708         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
709         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
710     NSArray *fileType = [NSArray arrayWithObject:@"xml"];
711     [nsop setAllowsMultipleSelection:NO];
712     [nsop setCanChooseFiles:YES];
713     [nsop setCanChooseDirectories:NO];
714     [nsop runModalForTypes:fileType];
715     NSMutableArray* importedXML = [xmlConv importXML:[nsop URL]];
716         [xmlConv fixData:importedXML];
717         [xmlConv exportFixedXML:importedXML toFile:@"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.tgd"];
722 /*      if ([prefs boolForKey:@"epgSync"]) {
723                         [epgCB setState:1];
724                         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
725                         NSString* path = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/tv.xml";
726                         NSString* tempFile = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.epg";
727                         NSMutableArray* importedXML = [xmlConv importXML:[NSURL fileURLWithPath:path]];
728                         [xmlConv fixData:importedXML];
729                         [xmlConv exportFixedXML:importedXML toFile:tempFile];
730                         if (! connected)
731                                 return;
732                         NSFileManager* fm = [NSFileManager defaultManager];
733                         NSDictionary *fattrs = [fm fileAttributesAtPath:tempFile traverseLink:NO];
734                         if (!fattrs) {
735                                 NSLog(@"Path of file to upload is incorrect!");
736                                 return;
737                         }
738                         NSDictionary* fileAttr = [dh extractAttributes:fattrs];
739                         NSMutableArray* array = [NSMutableArray arrayWithArray:[tempFile componentsSeparatedByString:@"/"]];
740                         NSString* fileName = [NSString stringWithString:[array lastObject]];
741                         NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
742                         [tfusbc uploadFile:tempFile ofSize:[fattrs fileSize] fromPath:@"\\Program Files\\TimerKey\\" withAttributes:typeFile toDevice:context];
743                         [self goToPath:currentPath];
744                         [self resetTurbo];
745                 } */
749 /*- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
751         if ([prefs objectForKey:@"NoRollover"] != nil) return;
752         if ([aTableView mouseOverRow] == rowIndex && ([aTableView selectedRow] != rowIndex))
753                         if ([aTableView lockFocusIfCanDraw]) {
754                                 NSRect rowRect = [aTableView rectOfRow:rowIndex];
755                                 NSRect columnRect = [aTableView rectOfColumn:[[aTableView tableColumns] indexOfObject:aTableColumn]];
757                                         if (!highlightImage) {
758                                                 highlightImage = [[NSImage alloc] initWithData:[highlightImageData propertyList]];
759                                                         [highlightImage setDataRetained:YES]; //?
760                                                         [highlightImage setCacheMode:NSImageCacheAlways]; //?
761                                         }
763                                 [highlightImage drawInRect:NSIntersectionRect(rowRect, columnRect) fromRect:NSMakeRect(0,0,1,[highlightImage size].height) operation:NSCompositeSourceOver fraction:0.3];
764                                 [aTableView unlockFocus];
765                         }
769 - (void)dealloc
771   if (highlightImage) [highlightImage release];
772 [super dealloc];
775 - (IBAction)pauseCurrentTransfer:(id)sender {
776         if (!paused) {
777         [pauseButton setImage:[NSImage imageNamed:@"DownloadResume.tif"]];
778         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadResumePressed.tif"]];
779         //add priority "halt" to queue naming file
780         id current = [[tfusbc transferQueue] objectAtIndex:0];
781         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"pause",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
782         paused = YES;
783         [currentlyField setStringValue:[NSLocalizedString(@"PAUSED", @"Paused: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
784         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
785         [currentlyField displayIfNeeded];
786         } else {
787         //change image to pause
788         //add priority "resume" to queue naming file
789         [pauseButton setImage:[NSImage imageNamed:@"DownloadStop.tif"]];
790         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadStopPressed.tif"]];
791         id current = [[tfusbc pausedQueue] objectAtIndex:0];//temp as for now only have 1 paused
792         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"resume",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
793         paused = NO;
794         [currentlyField setStringValue:[NSLocalizedString(@"DOWNLOADING", @"Downloading: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
795         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
796         [currentlyField displayIfNeeded];
797         }
800 - (id) selectedColumn {
801         return selectedColumn;
803 - (id) currentlyField {
804         return currentlyField;
806 - (id) connectLight {
807         return connectLight;
810 @end