Various changes for Mac OS X 10.4 builds.
[MacTF.git] / UIElements.m
blob90013891c2d3a7b006c0934f776fa52fd86692e8
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         [pathBar setEnabled:YES];
59         [[pathBar cell] setSegmentCount:1];
60         [[pathBar cell] setLabel:@"Path:" forSegment:0];
61         [[pathBar cell] setWidth:0 forSegment:0];
62         [pathBar sizeToFit];
63         [[dh fileList] addObject:[NSDictionary dictionaryWithObject:NSLocalizedString(@"NOT_CONNECTED_ENTRY", @"Not connected") forKey:@"name"]];
64         [tableView reloadData];
65         prefs = [[NSUserDefaults standardUserDefaults] retain];
66         if ([prefs boolForKey:@"auto-connect"]) {
67                 [self connect:nil];
68                 [autoCB setState:1];    
69         }
70         // test code heres
71         if ([NSEvent isShiftKeyDown] && [NSEvent isControlKeyDown]) { NSLog(@"Testmode activated");
72         unsigned long long offset = 512*2000;
73         NSLog(@"%qu", offset);
74         const UInt64 offset_bigendian = EndianU64_NtoB(offset);
75         NSData* dat = [NSData dataWithBytes:&offset_bigendian length:8];
76         NSLog([dat description]);
77         
78         }
81 - (BOOL)validateMenuItem:(NSMenuItem*)anItem {
82     if ([[anItem title] isEqualToString:NSLocalizedString(@"DL_MENUITEM", @"Download")] && (1 > [tableView numberOfSelectedRows])) {
83         return NO;
84     }
85         if ([[anItem title] isEqualToString:NSLocalizedString(@"DEL_MENUITEM", @"Delete")] && (1 > [tableView numberOfSelectedRows])) {
86         return NO;
87     }
88         if ([[anItem title] isEqualToString:NSLocalizedString(@"RN_MENUITEM", @"Rename")] && (1 != [tableView numberOfSelectedRows])) {
89         return NO;
90     }
91         if ([[anItem title] isEqualToString:NSLocalizedString(@"UL_MENUITEM", @"Upload")] && (! connected)) {
92         return NO;
93     }
94         if ([[anItem title] isEqualToString:NSLocalizedString(@"NF_MENUITEM", @"NewFolder")] && (! connected)) {
95         return NO;
96     }
97     return YES;
100 - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem {
101     if ([[toolbarItem itemIdentifier] isEqual:@"ConnectTBIcon"]) {
102                 if (connected) {
103                         [toolbarItem setLabel:NSLocalizedString(@"DC_BUTTON", @"Disconnect")];
104                 } else {
105                         [toolbarItem setLabel:NSLocalizedString(@"CON_BUTTON", @"Connect")];
106                 }
107         }
108         if ([[toolbarItem itemIdentifier] isEqual:@"UploadTBIcon"] && (! connected)) {
109                 return NO;
110         }
111         if ([[toolbarItem itemIdentifier] isEqual:@"NewFolderTBIcon"] && (! connected)) {
112                 return NO;
113         }
114         if ([[toolbarItem itemIdentifier] isEqual:@"TurboTBIcon"] && (! connected)) {
115                 return NO;
116         }
117         if ([[toolbarItem itemIdentifier] isEqual:@"DownloadTBIcon"] && (1 > [tableView numberOfSelectedRows] || !connected)) {
118                 return NO;
119         }
120         if ([[toolbarItem itemIdentifier] isEqual:@"DeleteTBIcon"] && (1 > [tableView numberOfSelectedRows] || !connected)) {
121                 return NO;
122         }
123         if ([[toolbarItem itemIdentifier] isEqual:@"RenameTBIcon"] && (1 != [tableView numberOfSelectedRows] || !connected)) {
124                 return NO;
125         }
126     return YES;
130 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
132         [preview setString:@""];
133         if ([previewDrawer state] == NSDrawerClosedState) return; // don't bother getting previews if closed
134         if ([tableView numberOfSelectedRows] != 1 || !connected)
135                 return;
136         if ([[tfusbc transferQueue] count] > 0) return; //for now, change to a priority transfer later?
137         id currentSelectedItem = [[dh displayedList] objectAtIndex:[tableView selectedRow]];
138         int type = [[currentSelectedItem objectForKey:@"type"] intValue];
139         if (type == 2) { //file
140                 NSString* nameOnToppy = [currentSelectedItem objectForKey:@"name"]; 
141                 if (([nameOnToppy hasSuffix:@".ini"] || [nameOnToppy hasSuffix:@".txt"] || [nameOnToppy hasSuffix:@".tgd"] || [nameOnToppy hasSuffix:@".tsv"] || [nameOnToppy hasSuffix:@".dat"] || [nameOnToppy hasSuffix:@".tap"])) {
142                         [drawerTabView selectTabViewItemAtIndex:0];
143                         NSString* tempFile = NSTemporaryDirectory(); // download preview to temp folder
144                         tempFile = [tempFile stringByAppendingPathComponent:@"MacTFTemp"];
145                         [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];
146                         while ([[tfusbc transferQueue] count] > 0) {
147                                 usleep(10);
148                         }
149                         [preview setString:[NSString stringWithContentsOfFile:tempFile]];
150                 } else if ([nameOnToppy hasSuffix:@".rec"]) { //display headers
151                         [drawerTabView selectTabViewItemAtIndex:1];
152                         NSString* tempFile = NSTemporaryDirectory(); // download first 64k to temp folder
153                         tempFile = [tempFile stringByAppendingPathComponent:@"MacTFTemp"];
154                         [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];
155                         while ([[tfusbc transferQueue] count] > 0) {
156                                 usleep(10);
157                         }
158                         NSDictionary* recData = [dh extractDataFromRecHeader:tempFile forModel:[prefs objectForKey:@"modelType"]]; //then parse and display headers
159                         [recStart setObjectValue:[recData objectForKey:@"startTime"]];
160                         [recDuration setObjectValue:[recData objectForKey:@"duration"]];
161                         [recDescription setStringValue:[recData objectForKey:@"description"]];
162                         [recName setStringValue:[recData objectForKey:@"name"]];
163                         [recExtInfo setStringValue:[recData objectForKey:@"extInfo"]];
164                         [recChannel setStringValue:[recData objectForKey:@"channel"]];
165                 }       
166                 else {
167                         [drawerTabView selectTabViewItemAtIndex:0];
168                         return;
169                 }
170         } else if (type == 1) { //folder
171                 [drawerTabView selectTabViewItemAtIndex:0];
172                 return;
173         } else {
174                 [statusField setStringValue:NSLocalizedString(@"SEL_ERROR", @"Selection error...")];
175                 return;
176         }
179 - (void) setAvailableSpace:(NSData*)input {
180         [availSpaceField setStringValue:[self prepForSizeDisplay:input]];
183 - (void) setFreeSpace:(NSData*) input {
184         [freeSpaceField setStringValue:[self prepForSizeDisplay:input]];
187 - (NSString*) prepForSizeDisplay:(NSData*) input {
188         UInt32 size_bigendian;
189         [input getBytes:&size_bigendian];
190         unsigned size = EndianU32_BtoN(size_bigendian);
191         NSString *ret = nil;
192                 if( size == 0. ) ret = NSLocalizedString( @" - ", "no file size" );
193                 else if( size > 0. && size < 1024. ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.0f KB", "file size measured in kilobytes" ), size];
194                 else if( size >= 1024. && size < pow( 1024., 2. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.1f MB", "file size measured in megabytes" ), ( size / 1024. )];
195                 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. ) )];
196                 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. ) )];
197                 else if( size >= pow( 1024., 4. ) ) ret = [NSString stringWithFormat:NSLocalizedString( @"%.4f PB", "file size measured in pentabytes" ), ( size / pow( 1024., 4. ) )];
198         return ret;
201 - (IBAction) connect: (id) sender { 
202         if (! connected) {
203                 context = [tfusbc initializeUSB];
204                 if (context == nil) {
205                         [statusField setStringValue:NSLocalizedString(@"INIT_PROBLEM", @"Message when initialization fails.")];
206                         return;
207                 }
208                 // add a check here to see if really connected...
209                 connected = YES;
210                 [[dh fileList] removeAllObjects];
211                 [[dh fileList] addObject:[NSDictionary dictionaryWithObject:NSLocalizedString(@"FETCHING", @"Fetching") forKey:@"name"]];
212                 [tableView reloadData];
213                 [tfusbc clearQueues];
214                 paused = NO;
215                 [turboCB setState:0];
216                 [turboCB setEnabled:YES];
217                 [[pathBar cell] setSegmentCount:2];
218                 [[pathBar cell] setLabel:@"Path:" forSegment:0];
219                 [[pathBar cell] setLabel:@"\\" forSegment:1];
220                 [[pathBar cell] setWidth:0 forSegment:0];
221                 [[pathBar cell] setWidth:0 forSegment:1];
222                 [pathBar sizeToFit];
223                 [pathBar setHidden:NO];
224                 [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
225                 [connectButton setTitle:NSLocalizedString(@"DC_BUTTON", @"Disconnect.")];
226                 [statusField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"CONNECTED_MESSAGE", @"Message giving connection speed."), [tfusbc getSpeed]]];
227                 [NSThread detachNewThreadSelector:@selector(transfer:) toTarget:tfusbc withObject:nil];
228         } else { // already connected
229                 connected = NO;
230                 if ([[tfusbc transferQueue] count] != 0) { //gives a few seconds for busy thread to notice it should not be connected before cutting the device off
231                         sleep(3);
232                 }
233                 [tfusbc closeDevice:context];
234                 [connectButton setTitle:NSLocalizedString(@"CON_BUTTON", @"Connect.")];
235                 [statusField setStringValue:NSLocalizedString(@"NO_CONNECT", @"No connection.")];
236                 [[dh fileList] removeAllObjects];
237                 [tableView reloadData];
238                 [turboCB setState:0];
239                 [turboCB setEnabled:NO];
240                 [connectLight setImage:[NSImage imageNamed:@"red.tiff"]];
241                 currentPath = @"\\";
242                 return;
243         }
244         int ret = [self goToPath:@"\\"];
245         if (ret == 1) { 
246                 sleep (5); //error, wait a few secs for HDD to start if need be then try again
247                 [self goToPath:@"\\"];
248         }
249         currentPath = @"\\";
252 - (int) goToPath:(NSString*) path {
253         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:path,@"path",@"fileList",@"transferType",nil]];
256 - (void)doubleClick:(id)sender
258         if ([tableView numberOfSelectedRows] != 1)
259                 return;
260         id currentSelectedItem = [[dh displayedList] objectAtIndex:[tableView selectedRow]];
261         int type = [[currentSelectedItem objectForKey:@"type"] intValue];
262         if (type == 2) { //file
263                 [self downloadFileDoubleClickThread:nil];
264         } else if (type == 1) { //folder
265                 NSString* currentName = [currentSelectedItem objectForKey:@"name"];
266                 if ([currentName isEqualToString:@".. (Parent folder)"]) { // move up
267                         NSMutableArray* array = [NSMutableArray arrayWithArray:[currentPath componentsSeparatedByString:@"\\"]];
268                         if ([array count] > 1){ // not going to root
269                                 [array removeLastObject];
270                                 NSString* temp = [NSString stringWithString:[array componentsJoinedByString:@"\\"]];
271                                 if ([self goToPath:temp]) {// if error
272                                         [self goToPath:temp]; // hackish workaround
273                                 }
274                                 int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
275                                 NSRect r = [pathBar frame];
276                                 [[pathBar cell] setSegmentCount:segCount-1];
277                                 [pathBar setNeedsDisplayInRect:r];
278                                 [pathBar displayIfNeeded];
279                                 currentPath = [[NSString stringWithString:temp] retain];
280                                 [statusField setStringValue:NSLocalizedString(@"CONNECTED_OK", @"Connection OK")];
281                         } else {//root
282                                 currentPath = @"\\";
283                                 [[pathBar cell] setSegmentCount:1];
284                         }
285                 } else { //move down
286                         NSMutableString* temp = [NSMutableString stringWithString:currentPath];
287                         if (![temp isEqualToString:@"\\"])
288                                         [temp appendString:@"\\"];
289                         [temp appendString:currentName];
290                         if ([self goToPath:temp]) { // if error, try again
291                                 [self goToPath:temp]; // hackish workaround
292                 }
293                         currentPath = [[NSString stringWithString:temp] retain];
294                         int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
295                         NSRect r = [pathBar frame];
296                         [[pathBar cell] setSegmentCount:segCount+1];
297                         [[pathBar cell] setLabel:currentName forSegment:segCount];
298                         [[pathBar cell] setWidth:0 forSegment:segCount];
299                         [pathBar sizeToFit];
300                         [pathBar displayIfNeededInRect:r];
301                         [statusField setStringValue:NSLocalizedString(@"CONNECTED_OK", @"Connection OK")];
302                 }
303         } else {
304                 [statusField setStringValue:NSLocalizedString(@"SEL_ERROR", @"Selection error...")];
305                 return; 
306         }
309 - (void) downloadFileDoubleClickThread:(NSDictionary*)fileInfo {
310         if (! connected) return;
311                 [self downloadSelectedFile:nil];
312 //      [self updateHDDSize];
315 /*- (void) updateHDDSize {
316         if (! connected) return;
317         NSData* hddSizeString = [tfusbc getHDDSize:context];
318         if (hddSizeString != nil) {
319                 [self setAvailableSpace:[hddSizeString subdataWithRange:(NSRange) {8,4}]];
320                 [self setFreeSpace:[hddSizeString subdataWithRange:(NSRange) {12,4}]];
321         } 
324 - (void)tableView:(NSTableView *)tView didClickTableColumn:(NSTableColumn *)tableColumn
326         // Either reverse the sort or change the sorting column
327         NSArray* sortDescriptors = [[NSArray alloc] init];
328         NSArray* sortedArray;
329         NSImage *indicatorImage;
330     if (sortAscending || ![tableColumn isEqualTo:selectedColumn]) {
331                 if ([[tableColumn identifier] isEqualToString:@"name"]) {
332                         NSSortDescriptor* nameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
333                         sortDescriptors=[NSArray arrayWithObject:nameDescriptor];
334                 } else
335                         if ([[tableColumn identifier] isEqualToString:@"date"]) {
336                                 NSSortDescriptor* dateDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"sortdate" ascending:YES] autorelease];
337                                 sortDescriptors=[NSArray arrayWithObject:dateDescriptor];
338                         } else
339                                 if ([[tableColumn identifier] isEqualToString:@"size"]) {
340                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"fileSize" ascending:YES] autorelease];
341                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
342                                 }  else
343                                         if ([[tableColumn identifier] isEqualToString:@"icon"]) {
344                                                 NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"suffix" ascending:YES] autorelease];
345                                                 sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
346                                         }
347                 sortedArray=[[dh fileList] sortedArrayUsingDescriptors:sortDescriptors];                
348                 indicatorImage = [NSImage imageNamed: @"NSAscendingSortIndicator"];
349     } else {
350         if ([[tableColumn identifier] isEqualToString:@"name"]) {
351                         NSSortDescriptor* nameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO selector:@selector(caseInsensitiveCompare:)] autorelease];
352                         sortDescriptors=[NSArray arrayWithObject:nameDescriptor];
353                 } else
354                         if ([[tableColumn identifier] isEqualToString:@"date"]) {
355                                 NSSortDescriptor* dateDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"sortdate" ascending:NO] autorelease];
356                                 sortDescriptors=[NSArray arrayWithObject:dateDescriptor];
357                         } else
358                                 if ([[tableColumn identifier] isEqualToString:@"size"]) {
359                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"fileSize" ascending:NO] autorelease];
360                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
361                                 } else
362                                 if ([[tableColumn identifier] isEqualToString:@"icon"]) {
363                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"suffix" ascending:NO] autorelease];
364                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
365                                 }
367                 sortedArray=[[dh fileList] sortedArrayUsingDescriptors:sortDescriptors];                
368         indicatorImage = [NSImage imageNamed: @"NSDescendingSortIndicator"];
369     }
370     sortAscending = !sortAscending;
371         selectedColumn = tableColumn;
372         [tView setIndicatorImage: indicatorImage inTableColumn: tableColumn];
373    // remove other indicators
374         NSMutableArray* otherColumns = [NSMutableArray arrayWithArray:[tView tableColumns]];
375         [otherColumns  removeObject:tableColumn];
376         NSEnumerator* cols = [otherColumns objectEnumerator];
377         id currentCol;
378         while (currentCol = [cols nextObject]) {
379                 [tView setIndicatorImage: nil inTableColumn: currentCol];
380         }
381         [dh setFileList:sortedArray];
382         [dh search:searchField];
383         [dh reloadTable];
387 - (IBAction) downloadSelectedFile:(id)sender{
388         if (! connected)
389                 return;
390         NSLog(@"Download file starting...");
391         NSEnumerator* selected = [tableView selectedRowEnumerator];
392         id currentSelected;
393         while (currentSelected = [selected nextObject]) {
394                 id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
395                 int type = [[currentSelectedItem objectForKey:@"type"] intValue];
396                 if (type == 1) {[statusField setStringValue:NSLocalizedString(@"NO_FOLDER_DL", @"Folder download not supported yet")];}
397                 else if (type == 2) {
398                         NSString* nameOnToppy = [currentSelectedItem objectForKey:@"name"];
399                         NSSavePanel *nssave = [[NSSavePanel savePanel]retain];
400                         int retButton = [nssave runModalForDirectory:nil file:nameOnToppy];
401                         if (retButton) {
402                                 NSString* savePath= [nssave filename]; 
403                                 NSLog(savePath);
404                                 unsigned long long offset = 0;
405                                 NSFileHandle *newFileHandle = [NSFileHandle fileHandleForReadingAtPath:savePath];
406                                 if (!(newFileHandle==nil)) { // there is a file there, ask if want to resume
407                                         NSLog(@"existing file length: %qu", [newFileHandle seekToEndOfFile]);
408                                         //ask to resume, save offset if yes
409                                         //offset = [newFileHandle seekToEndOfFile];
410                                 }
411                                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
412                                 [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];
413                         }
414                 }               
415         }
416         //              [self updateHDDSize];
417         }
419 - (void) finishTransfer {
420         [currentlyField setStringValue:@""];
421         [progressBar setDoubleValue:0];
422         [[NSSound soundNamed:@"Ping"] play];
423         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
424         [currentlyField setStringValue:NSLocalizedString(@"IDLE", @"Idle")];
425         [currentlyField display];
428 - (IBAction) uploadFile: (id) sender {
429         if (! connected)
430                 return;
431         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
432         [nsop setAllowsMultipleSelection:YES];
433         [nsop setCanChooseFiles:YES];
434         [nsop setCanChooseDirectories:YES];
435         int retButton = [nsop runModal];
436         NSArray *returnedNames = [nsop filenames];      
437         if (retButton == NSFileHandlingPanelCancelButton) {             
438                 NSLog(@"Upload cancelled");
439                 return;
440         }
441         //get info about the chosen file - later if do folders check here and do recursive all things in folder???
442         NSEnumerator *enumerator = [returnedNames objectEnumerator];
443         id returnedName;
444 //      [statusField setStringValue:[NSLocalizedString(@"CONNECTED_OK", @"Connection OK") stringByAppendingString:NSLocalizedString(@"DOWNLOAD", @"Download")]; 
445         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
446         while (returnedName = [enumerator nextObject]) {
447                 NSLog(returnedName);
448                 [self uploadPath:returnedName toPath:[NSString stringWithString:currentPath]];
449         }
454 - (void) uploadPath:(NSString*) path toPath:(NSString*) toPath {
455         if (! connected)
456                 return;
457         NSFileManager* fm = [NSFileManager defaultManager];
458         NSDictionary *fattrs = [fm fileAttributesAtPath:path traverseLink:NO];
459         if (!fattrs) {
460                 NSLog(@"Path of file to upload is incorrect!");
461                 return; }
462         NSString* type = [fattrs fileType];
463         if ([type isEqualToString:@"NSFileTypeDirectory"]) {
464                 // should look to create folder on Toppy, or add stuff if already there (maybe it does this automatically?), and place in subfolders etc
465                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[path lastPathComponent],@"newName",toPath,@"path",@"newFolder",@"transferType", nil]];
466                 NSArray* subPaths = [fm directoryContentsAtPath:path];
467                 NSEnumerator* e = [subPaths objectEnumerator];
468                 id object;
469                 while (object = [e nextObject]) {
470                         NSString* subPath = [NSString stringWithFormat:@"%@/%@", path, object];
471                         NSString* subToPath = [NSString stringWithFormat:@"%@\\%@", toPath, [path lastPathComponent]];
472                 //      NSLog(@"subdir: %@, %@", subPath, subToPath);
473                         if (![object isEqualToString:@".DS_Store"]) {
474                                 [self uploadPath:subPath toPath:subToPath];
475                         }
476                 }
477                 if (connected) { //may have disconnected during threaded upload (although not actually threaded here!)
478         //              [self updateHDDSize];
479                         [self goToPath:currentPath];
480                 }
481         }
482         else {
483                 NSDictionary* fileAttr = [dh extractAttributes:fattrs];         // turn Dict into a new TypeFile dict
484                 NSMutableArray* array = [NSMutableArray arrayWithArray:[path componentsSeparatedByString:@"/"]]; // cut down name
485                 NSString* fileName = [NSString stringWithString:[array lastObject]];
486                 NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
487                 [progressBar setDoubleValue:0];
488                 [currentlyField setStringValue:[NSLocalizedString(@"UPLOADING", @"Uploading") stringByAppendingString:fileName]];
489                 [currentlyField displayIfNeeded];
490                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
491                 [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];
492         }
495 -(IBAction)deleteFile:(id)sender
497         if (! connected)
498                 return;
499         if ( [tableView numberOfSelectedRows] == 0 )
500         return;
501         NSString *title = NSLocalizedString(@"WARNING", @"Warning!");
502     NSString *defaultButton = NSLocalizedString(@"DEL", @"Delete");
503     NSString *alternateButton = NSLocalizedString(@"NO_DEL", @"Don't Delete");
504     NSString *otherButton = nil;
505     NSString *message = NSLocalizedString(@"DEL_MESSAGE", @"Are you sure you want to delete the selected file(s)?");
507     NSBeep();
508     NSBeginAlertSheet(title, defaultButton, alternateButton, otherButton, mainWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, nil, message);
511 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
513     if ( returnCode == NSAlertDefaultReturn ) {
514                 NSLog(@"Deleting file(s) starting...");
515                 NSEnumerator* selected = [tableView selectedRowEnumerator];
516                 id currentSelected;
517                 while (currentSelected = [selected nextObject]) {
518                         id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
519                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"file",currentPath,@"path",@"delete",@"transferType", nil]];
520                 }
521         //      [self updateHDDSize];
522                 [self goToPath:currentPath];
523                 //should check so don't delete root folders?
524         }
527 - (IBAction)openPrefsSheet:(id)sender
529         [NSApp beginSheet:prefsWindow
530            modalForWindow:mainWindow
531                 modalDelegate:self
532            didEndSelector:@selector(mySheetDidEnd:returnCode:contextInfo:)
533           contextInfo: nil];
534         return;  // leave without doing anything else
537 - (IBAction) mySheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
538                            contextInfo:(void *)contextInfo {
539         
540         [sheet orderOut:self];
541         if(returnCode == 0)  return;
542         // continue with application  
545 - (IBAction)closePrefsSheet:(id)sender
547         //do changes to prefs here
548         //    if (connected) {
549         [tfusbc setDebug:[debugCB state]]; 
550         //  }
551         NSLog(@"auto: %i", [autoCB state]);
552         [prefs setBool:[autoCB state] forKey:@"auto-connect"];
553 //      [prefs setBool:[epgCB state] forKey:@"epgSync"];
554         [prefs synchronize];
555         [NSApp endSheet:prefsWindow returnCode:1];
558 - (IBAction)openRenameSheet:(id)sender
560         if ( [tableView numberOfSelectedRows] != 1 )
561         return;
562         [renameOld setStringValue:[[[dh displayedList] objectAtIndex:[tableView selectedRow]] objectForKey:@"name"]];
563         [renameNew setStringValue:[renameOld stringValue]];
564 //      [renameWindow setTitleBarHeight:0.0];
565         [NSApp beginSheet: renameWindow
566            modalForWindow: mainWindow
567                 modalDelegate: nil
568            didEndSelector: nil
569                   contextInfo: nil];
570     [NSApp runModalForWindow: renameWindow];
571     // Sheet is up here.
574 - (IBAction)cancelRename:(id)sender{
575         [NSApp endSheet: renameWindow];
576     [renameWindow orderOut: self];
577         [NSApp stopModal];
580 - (IBAction)closeRenameSheet:(id)sender
582         //do changes to rename here
583         if (connected) {
584                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[renameOld stringValue],@"oldName",[renameNew stringValue],@"newName", currentPath,@"path",@"rename",@"transferType",nil]];
585                 [self goToPath:currentPath];
586         }
587                 //then close up
588         [self cancelRename:sender];
592 - (IBAction)openNewFolderSheet:(id)sender
594         [NSApp beginSheet: newFolderWindow
595            modalForWindow: mainWindow
596                 modalDelegate: nil
597            didEndSelector: nil
598                   contextInfo: nil];
599     [NSApp runModalForWindow: newFolderWindow];
600     // Sheet is up here.
601         
604 - (IBAction)cancelNewFolder:(id)sender{
605         [NSApp endSheet: newFolderWindow];
606     [newFolderWindow orderOut: self];
607         [NSApp stopModal];
610 - (IBAction)closeNewFolderSheet:(id)sender
612         //do changes to make new folder here
613         if (connected) {
614                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[newFolderNew stringValue],@"newName",currentPath,@"path",@"newFolder",@"transferType", nil]];
615                 [self goToPath:currentPath];
616         }
617         //then close up
618         [self cancelNewFolder:sender];
621 - (IBAction)pathBarClick:(id)sender {
622         int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
623         int selectedSegment = [sender selectedSegment]; 
624         if (selectedSegment == segCount - 1) return; //no need to move anywhere
625         int i = 1; // remember have "path" there too 
626         NSMutableArray* pathArray = [NSMutableArray arrayWithCapacity:selectedSegment];
627         while (i<=selectedSegment) {
628                 [pathArray addObject:[[pathBar cell] labelForSegment:i]];
629                 i++;
630         } 
631         NSString* pathString = [pathArray componentsJoinedByString:@"\\"];
632         if ([pathString hasPrefix:@"\\\\"]) pathString = [pathString substringFromIndex:1];
633         [self goToPath:pathString];
634         currentPath = [[NSString stringWithString:pathString] retain];
635         NSRect r = [pathBar frame];
636         [[pathBar cell] setSegmentCount:selectedSegment+1];
637         [pathBar displayIfNeededInRect:r];      
640 - (id)getTfusbc {
641         return tfusbc;
644 - (USBDeviceContext*) getContext {
645         return context;
648 - (NSNumber*) isConnected {
649         return [NSNumber numberWithBool:connected];
653 - (NSString*) currentPath {
654         return currentPath;
657 - (IBAction) toggleTurbo:(id)sender {
658         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
659                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
660         }
663 - (IBAction) toggleTurboCB:(id)sender {
664         if (! connected)
665                 return;
666         if ([turboCB state]) { // currently on, want off
667                 [turboCB setState:0];
668         } else {
669                 [turboCB setState:1];
670         }
671         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
672                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
673         }
676 - (IBAction) togglePreview:(id)sender {
677                 [previewDrawer toggle:sender];
680 /*- (IBAction) snapshot:(id) sender {
681         NSArray* snapshotData = [self snapshotOfPath:@"\\"];
682         [dh setSnapShot:snapshotData];
683         // show snapshot window
684         [snapshotWindow makeKeyAndOrderFront:sender];
685         [outlineView reloadData];
688 - (NSArray*) snapshotOfPath:(NSString*)path {
689         
690 NSData* hddFileData = [tfusbc getFileList:context forPath:path];
691 NSData* checkForError = [hddFileData subdataWithRange:(NSRange){4,4}];
692 const UInt32 check_bigendian = EndianU32_NtoB(USB_Fail);
693 const UInt32 check2_bigendian = EndianU32_NtoB(USB_DataHddDir);
694 if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
695         [statusField setStringValue:@"Connected - error on last command"];
697 if (! [checkForError isEqualToData:[NSData dataWithBytes:&check2_bigendian length:4]]) {
698         hddFileData = [tfusbc getFileList:context forPath:path]; //try again
699         if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
700                 [statusField setStringValue:@"Connected - error on last command"];
701         }
703 hddFileData = [hddFileData subdataWithRange:(NSRange) {8, [hddFileData length]-8}]; // cut off header and cmd 
704 int i;
705 NSMutableArray* paths = [[NSMutableArray alloc] init];
706 for (i=0; i*114 < [hddFileData length]-4; i++) { // 4 is there cause swapping sometimes adds a byte of padding  
707         NSData* temp = [hddFileData subdataWithRange:(NSRange) {i*114,114}];
708         NSMutableDictionary* tfFile = [dh getTFFileFromSwappedHexData:temp];
709         [dh convertRawDataToUseful:tfFile];
710         if (!([[tfFile objectForKey:@"name"] isEqualToString:@".."])) {
711                 if ([[tfFile objectForKey:@"type"] intValue] == 1) { //folder
712                         NSMutableString* temp = [NSMutableString stringWithString:path];
713                         if (![temp isEqualToString:@"\\"])
714                                 [temp appendString:@"\\"];
715                         [temp appendString:[tfFile objectForKey:@"name"]];
716                         [paths addObject:tfFile];
717                         [paths addObject:[self snapshotOfPath:temp]];
718                 } else {
719                         [paths addObject:tfFile];
720                 }
721         }
723 return paths;
728 /*- (IBAction) epg:(id) sender {
729         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
730         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
731     NSArray *fileType = [NSArray arrayWithObject:@"xml"];
732     [nsop setAllowsMultipleSelection:NO];
733     [nsop setCanChooseFiles:YES];
734     [nsop setCanChooseDirectories:NO];
735     [nsop runModalForTypes:fileType];
736     NSMutableArray* importedXML = [xmlConv importXML:[nsop URL]];
737         [xmlConv fixData:importedXML];
738         [xmlConv exportFixedXML:importedXML toFile:@"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.tgd"];
743 /*      if ([prefs boolForKey:@"epgSync"]) {
744                         [epgCB setState:1];
745                         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
746                         NSString* path = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/tv.xml";
747                         NSString* tempFile = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.epg";
748                         NSMutableArray* importedXML = [xmlConv importXML:[NSURL fileURLWithPath:path]];
749                         [xmlConv fixData:importedXML];
750                         [xmlConv exportFixedXML:importedXML toFile:tempFile];
751                         if (! connected)
752                                 return;
753                         NSFileManager* fm = [NSFileManager defaultManager];
754                         NSDictionary *fattrs = [fm fileAttributesAtPath:tempFile traverseLink:NO];
755                         if (!fattrs) {
756                                 NSLog(@"Path of file to upload is incorrect!");
757                                 return;
758                         }
759                         NSDictionary* fileAttr = [dh extractAttributes:fattrs];
760                         NSMutableArray* array = [NSMutableArray arrayWithArray:[tempFile componentsSeparatedByString:@"/"]];
761                         NSString* fileName = [NSString stringWithString:[array lastObject]];
762                         NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
763                         [tfusbc uploadFile:tempFile ofSize:[fattrs fileSize] fromPath:@"\\Program Files\\TimerKey\\" withAttributes:typeFile toDevice:context];
764                         [self goToPath:currentPath];
765                         [self resetTurbo];
766                 } */
770 /*- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
772         if ([prefs objectForKey:@"NoRollover"] != nil) return;
773         if ([aTableView mouseOverRow] == rowIndex && ([aTableView selectedRow] != rowIndex))
774                         if ([aTableView lockFocusIfCanDraw]) {
775                                 NSRect rowRect = [aTableView rectOfRow:rowIndex];
776                                 NSRect columnRect = [aTableView rectOfColumn:[[aTableView tableColumns] indexOfObject:aTableColumn]];
778                                         if (!highlightImage) {
779                                                 highlightImage = [[NSImage alloc] initWithData:[highlightImageData propertyList]];
780                                                         [highlightImage setDataRetained:YES]; //?
781                                                         [highlightImage setCacheMode:NSImageCacheAlways]; //?
782                                         }
784                                 [highlightImage drawInRect:NSIntersectionRect(rowRect, columnRect) fromRect:NSMakeRect(0,0,1,[highlightImage size].height) operation:NSCompositeSourceOver fraction:0.3];
785                                 [aTableView unlockFocus];
786                         }
790 - (void)dealloc
792   if (highlightImage) [highlightImage release];
793 [super dealloc];
796 - (IBAction)pauseCurrentTransfer:(id)sender {
797         if (!paused) {
798         [pauseButton setImage:[NSImage imageNamed:@"DownloadResume.tif"]];
799         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadResumePressed.tif"]];
800         //add priority "halt" to queue naming file
801         id current = [[tfusbc transferQueue] objectAtIndex:0];
802         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"pause",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
803         paused = YES;
804         [currentlyField setStringValue:[NSLocalizedString(@"PAUSED", @"Paused: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
805         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
806         [currentlyField displayIfNeeded];
807         } else {
808         //change image to pause
809         //add priority "resume" to queue naming file
810         [pauseButton setImage:[NSImage imageNamed:@"DownloadStop.tif"]];
811         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadStopPressed.tif"]];
812         id current = [[tfusbc pausedQueue] objectAtIndex:0];//temp as for now only have 1 paused
813         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"resume",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
814         paused = NO;
815         [currentlyField setStringValue:[NSLocalizedString(@"DOWNLOADING", @"Downloading: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
816         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
817         [currentlyField displayIfNeeded];
818         }
821 - (id) selectedColumn {
822         return selectedColumn;
824 - (id) currentlyField {
825         return currentlyField;
827 - (id) connectLight {
828         return connectLight;
831 @end