Warn about missing newline.
[MacTF.git] / UIElements.m
blobca4380d23c78bd9c74b2d8655751246e07ff2941
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         NSArray* sortDescriptors = [[NSArray alloc] init];
324         NSArray* sortedArray;
325         NSImage *indicatorImage;
326     if (sortAscending || ![tableColumn isEqualTo:selectedColumn]) {
327                 if ([[tableColumn identifier] isEqualToString:@"name"]) {
328                         NSSortDescriptor* nameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
329                         sortDescriptors=[NSArray arrayWithObject:nameDescriptor];
330                 } else
331                         if ([[tableColumn identifier] isEqualToString:@"date"]) {
332                                 NSSortDescriptor* dateDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"sortdate" ascending:YES] autorelease];
333                                 sortDescriptors=[NSArray arrayWithObject:dateDescriptor];
334                         } else
335                                 if ([[tableColumn identifier] isEqualToString:@"size"]) {
336                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"fileSize" ascending:YES] autorelease];
337                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
338                                 }  else
339                                         if ([[tableColumn identifier] isEqualToString:@"icon"]) {
340                                                 NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"suffix" ascending:YES] autorelease];
341                                                 sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
342                                         }
343                 sortedArray=[[dh fileList] sortedArrayUsingDescriptors:sortDescriptors];                
344                 indicatorImage = [NSImage imageNamed: @"NSAscendingSortIndicator"];
345     } else {
346         if ([[tableColumn identifier] isEqualToString:@"name"]) {
347                         NSSortDescriptor* nameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO selector:@selector(caseInsensitiveCompare:)] autorelease];
348                         sortDescriptors=[NSArray arrayWithObject:nameDescriptor];
349                 } else
350                         if ([[tableColumn identifier] isEqualToString:@"date"]) {
351                                 NSSortDescriptor* dateDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"sortdate" ascending:NO] autorelease];
352                                 sortDescriptors=[NSArray arrayWithObject:dateDescriptor];
353                         } else
354                                 if ([[tableColumn identifier] isEqualToString:@"size"]) {
355                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"fileSize" ascending:NO] autorelease];
356                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
357                                 } else
358                                 if ([[tableColumn identifier] isEqualToString:@"icon"]) {
359                                         NSSortDescriptor* sizeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"suffix" ascending:NO] autorelease];
360                                         sortDescriptors=[NSArray arrayWithObject:sizeDescriptor];
361                                 }
363                 sortedArray=[[dh fileList] sortedArrayUsingDescriptors:sortDescriptors];                
364         indicatorImage = [NSImage imageNamed: @"NSDescendingSortIndicator"];
365     }
366     sortAscending = !sortAscending;
367         selectedColumn = tableColumn;
368         [tView setIndicatorImage: indicatorImage inTableColumn: tableColumn];
369    // remove other indicators
370         NSMutableArray* otherColumns = [NSMutableArray arrayWithArray:[tView tableColumns]];
371         [otherColumns  removeObject:tableColumn];
372         NSEnumerator* cols = [otherColumns objectEnumerator];
373         id currentCol;
374         while (currentCol = [cols nextObject]) {
375                 [tView setIndicatorImage: nil inTableColumn: currentCol];
376         }
377         [dh setFileList:sortedArray];
378         [dh search:searchField];
379         [dh reloadTable];
383 - (IBAction) downloadSelectedFile:(id)sender{
384         if (! connected)
385                 return;
386         NSLog(@"Download file starting...");
387         NSEnumerator* selected = [tableView selectedRowEnumerator];
388         id currentSelected;
389         while (currentSelected = [selected nextObject]) {
390                 id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
391                 int type = [[currentSelectedItem objectForKey:@"type"] intValue];
392                 if (type == 1) {[statusField setStringValue:NSLocalizedString(@"NO_FOLDER_DL", @"Folder download not supported yet")];}
393                 else if (type == 2) {
394                         NSString* nameOnToppy = [currentSelectedItem objectForKey:@"name"];
395                         NSSavePanel *nssave = [[NSSavePanel savePanel]retain];
396                         int retButton = [nssave runModalForDirectory:nil file:nameOnToppy];
397                         if (retButton) {
398                                 NSString* savePath= [nssave filename]; 
399                                 NSLog(savePath);
400                                 unsigned long long offset = 0;
401                                 NSFileHandle *newFileHandle = [NSFileHandle fileHandleForReadingAtPath:savePath];
402                                 if (!(newFileHandle==nil)) { // there is a file there, ask if want to resume
403                                         NSLog(@"existing file length: %qu", [newFileHandle seekToEndOfFile]);
404                                         //ask to resume, save offset if yes
405                                         //offset = [newFileHandle seekToEndOfFile];
406                                 }
407                                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
408                                 [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];
409                         }
410                 }               
411         }
412         //              [self updateHDDSize];
413         }
415 - (void) finishTransfer {
416         [currentlyField setStringValue:@""];
417         [progressBar setDoubleValue:0];
418         [[NSSound soundNamed:@"Ping"] play];
419         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
420         [currentlyField setStringValue:NSLocalizedString(@"IDLE", @"Idle")];
421         [currentlyField display];
424 - (IBAction) uploadFile: (id) sender {
425         if (! connected)
426                 return;
427         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
428         [nsop setAllowsMultipleSelection:YES];
429         [nsop setCanChooseFiles:YES];
430         [nsop setCanChooseDirectories:YES];
431         int retButton = [nsop runModal];
432         NSArray *returnedNames = [nsop filenames];      
433         if (retButton == NSFileHandlingPanelCancelButton) {             
434                 NSLog(@"Upload cancelled");
435                 return;
436         }
437         //get info about the chosen file - later if do folders check here and do recursive all things in folder???
438         NSEnumerator *enumerator = [returnedNames objectEnumerator];
439         id returnedName;
440 //      [statusField setStringValue:[NSLocalizedString(@"CONNECTED_OK", @"Connection OK") stringByAppendingString:NSLocalizedString(@"DOWNLOAD", @"Download")]; 
441         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
442         while (returnedName = [enumerator nextObject]) {
443                 NSLog(returnedName);
444                 [self uploadPath:returnedName toPath:[NSString stringWithString:currentPath]];
445         }
450 - (void) uploadPath:(NSString*) path toPath:(NSString*) toPath {
451         if (! connected)
452                 return;
453         NSFileManager* fm = [NSFileManager defaultManager];
454         NSDictionary *fattrs = [fm fileAttributesAtPath:path traverseLink:NO];
455         if (!fattrs) {
456                 NSLog(@"Path of file to upload is incorrect!");
457                 return; }
458         NSString* type = [fattrs fileType];
459         if ([type isEqualToString:@"NSFileTypeDirectory"]) {
460                 // should look to create folder on Toppy, or add stuff if already there (maybe it does this automatically?), and place in subfolders etc
461                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[path lastPathComponent],@"newName",toPath,@"path",@"newFolder",@"transferType", nil]];
462                 NSArray* subPaths = [fm directoryContentsAtPath:path];
463                 NSEnumerator* e = [subPaths objectEnumerator];
464                 id object;
465                 while (object = [e nextObject]) {
466                         NSString* subPath = [NSString stringWithFormat:@"%@/%@", path, object];
467                         NSString* subToPath = [NSString stringWithFormat:@"%@\\%@", toPath, [path lastPathComponent]];
468                 //      NSLog(@"subdir: %@, %@", subPath, subToPath);
469                         if (![object isEqualToString:@".DS_Store"]) {
470                                 [self uploadPath:subPath toPath:subToPath];
471                         }
472                 }
473                 if (connected) { //may have disconnected during threaded upload (although not actually threaded here!)
474         //              [self updateHDDSize];
475                         [self goToPath:currentPath];
476                 }
477         }
478         else {
479                 NSDictionary* fileAttr = [dh extractAttributes:fattrs];         // turn Dict into a new TypeFile dict
480                 NSMutableArray* array = [NSMutableArray arrayWithArray:[path componentsSeparatedByString:@"/"]]; // cut down name
481                 NSString* fileName = [NSString stringWithString:[array lastObject]];
482                 NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
483                 [progressBar setDoubleValue:0];
484                 [currentlyField setStringValue:[NSLocalizedString(@"UPLOADING", @"Uploading") stringByAppendingString:fileName]];
485                 [currentlyField displayIfNeeded];
486                 [tfusbc setProgressBar:progressBar time:progressTime turbo:turboCB];
487                 [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];
488         }
491 -(IBAction)deleteFile:(id)sender
493         if (! connected)
494                 return;
495         if ( [tableView numberOfSelectedRows] == 0 )
496         return;
497         NSString *title = NSLocalizedString(@"WARNING", @"Warning!");
498     NSString *defaultButton = NSLocalizedString(@"DEL", @"Delete");
499     NSString *alternateButton = NSLocalizedString(@"NO_DEL", @"Don't Delete");
500     NSString *otherButton = nil;
501     NSString *message = NSLocalizedString(@"DEL_MESSAGE", @"Are you sure you want to delete the selected file(s)?");
503     NSBeep();
504     NSBeginAlertSheet(title, defaultButton, alternateButton, otherButton, mainWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, nil, message);
507 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
509     if ( returnCode == NSAlertDefaultReturn ) {
510                 NSLog(@"Deleting file(s) starting...");
511                 NSEnumerator* selected = [tableView selectedRowEnumerator];
512                 id currentSelected;
513                 while (currentSelected = [selected nextObject]) {
514                         id currentSelectedItem = [[dh displayedList] objectAtIndex:[currentSelected intValue]];
515                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:currentSelectedItem,@"file",currentPath,@"path",@"delete",@"transferType", nil]];
516                 }
517         //      [self updateHDDSize];
518                 [self goToPath:currentPath];
519                 //should check so don't delete root folders?
520         }
523 - (IBAction)openPrefsSheet:(id)sender
525         [NSApp beginSheet:prefsWindow
526            modalForWindow:mainWindow
527                 modalDelegate:self
528            didEndSelector:@selector(mySheetDidEnd:returnCode:contextInfo:)
529           contextInfo: nil];
530         return;  // leave without doing anything else
533 - (IBAction) mySheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode
534                            contextInfo:(void *)contextInfo {
535         
536         [sheet orderOut:self];
537         if(returnCode == 0)  return;
538         // continue with application  
541 - (IBAction)closePrefsSheet:(id)sender
543         //do changes to prefs here
544         //    if (connected) {
545         [tfusbc setDebug:[debugCB state]]; 
546         //  }
547         NSLog(@"auto: %i", [autoCB state]);
548         [prefs setBool:[autoCB state] forKey:@"auto-connect"];
549 //      [prefs setBool:[epgCB state] forKey:@"epgSync"];
550         [prefs synchronize];
551         [NSApp endSheet:prefsWindow returnCode:1];
554 - (IBAction)openRenameSheet:(id)sender
556         if ( [tableView numberOfSelectedRows] != 1 )
557         return;
558         [renameOld setStringValue:[[[dh displayedList] objectAtIndex:[tableView selectedRow]] objectForKey:@"name"]];
559         [renameNew setStringValue:[renameOld stringValue]];
560 //      [renameWindow setTitleBarHeight:0.0];
561         [NSApp beginSheet: renameWindow
562            modalForWindow: mainWindow
563                 modalDelegate: nil
564            didEndSelector: nil
565                   contextInfo: nil];
566     [NSApp runModalForWindow: renameWindow];
567     // Sheet is up here.
570 - (IBAction)cancelRename:(id)sender{
571         [NSApp endSheet: renameWindow];
572     [renameWindow orderOut: self];
573         [NSApp stopModal];
576 - (IBAction)closeRenameSheet:(id)sender
578         //do changes to rename here
579         if (connected) {
580                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[renameOld stringValue],@"oldName",[renameNew stringValue],@"newName", currentPath,@"path",@"rename",@"transferType",nil]];
581                 [self goToPath:currentPath];
582         }
583                 //then close up
584         [self cancelRename:sender];
588 - (IBAction)openNewFolderSheet:(id)sender
590         [NSApp beginSheet: newFolderWindow
591            modalForWindow: mainWindow
592                 modalDelegate: nil
593            didEndSelector: nil
594                   contextInfo: nil];
595     [NSApp runModalForWindow: newFolderWindow];
596     // Sheet is up here.
597         
600 - (IBAction)cancelNewFolder:(id)sender{
601         [NSApp endSheet: newFolderWindow];
602     [newFolderWindow orderOut: self];
603         [NSApp stopModal];
606 - (IBAction)closeNewFolderSheet:(id)sender
608         //do changes to make new folder here
609         if (connected) {
610                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:[newFolderNew stringValue],@"newName",currentPath,@"path",@"newFolder",@"transferType", nil]];
611                 [self goToPath:currentPath];
612         }
613         //then close up
614         [self cancelNewFolder:sender];
617 - (IBAction)pathBarClick:(id)sender {
618         int segCount = [pathBar segmentCount]; //remember count starts at 1, not zero!
619         int selectedSegment = [sender selectedSegment]; 
620         if (selectedSegment == segCount - 1) return; //no need to move anywhere
621         int i = 1; // remember have "path" there too 
622         NSMutableArray* pathArray = [NSMutableArray arrayWithCapacity:selectedSegment];
623         while (i<=selectedSegment) {
624                 [pathArray addObject:[[pathBar cell] labelForSegment:i]];
625                 i++;
626         } 
627         NSString* pathString = [pathArray componentsJoinedByString:@"\\"];
628         if ([pathString hasPrefix:@"\\\\"]) pathString = [pathString substringFromIndex:1];
629         [self goToPath:pathString];
630         currentPath = [[NSString stringWithString:pathString] retain];
631         NSRect r = [pathBar frame];
632         [[pathBar cell] setSegmentCount:selectedSegment+1];
633         [pathBar displayIfNeededInRect:r];      
636 - (id)getTfusbc {
637         return tfusbc;
640 - (USBDeviceContext*) getContext {
641         return context;
644 - (NSNumber*) isConnected {
645         return [NSNumber numberWithBool:connected];
649 - (NSString*) currentPath {
650         return currentPath;
653 - (IBAction) toggleTurbo:(id)sender {
654         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
655                 [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
656         }
659 - (IBAction) toggleTurboCB:(id)sender {
660         if (! connected)
661                 return;
662         if ([turboCB state]) { // currently on, want off
663                 [turboCB setState:0];
664         } else {
665                 [turboCB setState:1];
666         }
667         if ([[tfusbc transferQueue] count] > 0) { //have a current transfer, lets toggle it
668                         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"turbo",@"transferType",[NSNumber numberWithBool:[turboCB state]],@"turboOn",nil]];
669         }
672 - (IBAction) togglePreview:(id)sender {
673                 [previewDrawer toggle:sender];
676 /*- (IBAction) snapshot:(id) sender {
677         NSArray* snapshotData = [self snapshotOfPath:@"\\"];
678         [dh setSnapShot:snapshotData];
679         // show snapshot window
680         [snapshotWindow makeKeyAndOrderFront:sender];
681         [outlineView reloadData];
684 - (NSArray*) snapshotOfPath:(NSString*)path {
685         
686 NSData* hddFileData = [tfusbc getFileList:context forPath:path];
687 NSData* checkForError = [hddFileData subdataWithRange:(NSRange){4,4}];
688 const UInt32 check_bigendian = EndianU32_NtoB(USB_Fail);
689 const UInt32 check2_bigendian = EndianU32_NtoB(USB_DataHddDir);
690 if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
691         [statusField setStringValue:@"Connected - error on last command"];
693 if (! [checkForError isEqualToData:[NSData dataWithBytes:&check2_bigendian length:4]]) {
694         hddFileData = [tfusbc getFileList:context forPath:path]; //try again
695         if ([checkForError isEqualToData:[NSData dataWithBytes:&check_bigendian length:4]]) {
696                 [statusField setStringValue:@"Connected - error on last command"];
697         }
699 hddFileData = [hddFileData subdataWithRange:(NSRange) {8, [hddFileData length]-8}]; // cut off header and cmd 
700 int i;
701 NSMutableArray* paths = [[NSMutableArray alloc] init];
702 for (i=0; i*114 < [hddFileData length]-4; i++) { // 4 is there cause swapping sometimes adds a byte of padding  
703         NSData* temp = [hddFileData subdataWithRange:(NSRange) {i*114,114}];
704         NSMutableDictionary* tfFile = [dh getTFFileFromSwappedHexData:temp];
705         [dh convertRawDataToUseful:tfFile];
706         if (!([[tfFile objectForKey:@"name"] isEqualToString:@".."])) {
707                 if ([[tfFile objectForKey:@"type"] intValue] == 1) { //folder
708                         NSMutableString* temp = [NSMutableString stringWithString:path];
709                         if (![temp isEqualToString:@"\\"])
710                                 [temp appendString:@"\\"];
711                         [temp appendString:[tfFile objectForKey:@"name"]];
712                         [paths addObject:tfFile];
713                         [paths addObject:[self snapshotOfPath:temp]];
714                 } else {
715                         [paths addObject:tfFile];
716                 }
717         }
719 return paths;
724 /*- (IBAction) epg:(id) sender {
725         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
726         NSOpenPanel *nsop = [[NSOpenPanel openPanel]retain];
727     NSArray *fileType = [NSArray arrayWithObject:@"xml"];
728     [nsop setAllowsMultipleSelection:NO];
729     [nsop setCanChooseFiles:YES];
730     [nsop setCanChooseDirectories:NO];
731     [nsop runModalForTypes:fileType];
732     NSMutableArray* importedXML = [xmlConv importXML:[nsop URL]];
733         [xmlConv fixData:importedXML];
734         [xmlConv exportFixedXML:importedXML toFile:@"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.tgd"];
739 /*      if ([prefs boolForKey:@"epgSync"]) {
740                         [epgCB setState:1];
741                         XMLToEPG *xmlConv = [[XMLToEPG alloc] init];
742                         NSString* path = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/tv.xml";
743                         NSString* tempFile = @"/Volumes/Tyr/nathan/Desktop/TV/Guides/test.epg";
744                         NSMutableArray* importedXML = [xmlConv importXML:[NSURL fileURLWithPath:path]];
745                         [xmlConv fixData:importedXML];
746                         [xmlConv exportFixedXML:importedXML toFile:tempFile];
747                         if (! connected)
748                                 return;
749                         NSFileManager* fm = [NSFileManager defaultManager];
750                         NSDictionary *fattrs = [fm fileAttributesAtPath:tempFile traverseLink:NO];
751                         if (!fattrs) {
752                                 NSLog(@"Path of file to upload is incorrect!");
753                                 return;
754                         }
755                         NSDictionary* fileAttr = [dh extractAttributes:fattrs];
756                         NSMutableArray* array = [NSMutableArray arrayWithArray:[tempFile componentsSeparatedByString:@"/"]];
757                         NSString* fileName = [NSString stringWithString:[array lastObject]];
758                         NSData* typeFile = [dh getDataFromTFFile:fileAttr withName:fileName];
759                         [tfusbc uploadFile:tempFile ofSize:[fattrs fileSize] fromPath:@"\\Program Files\\TimerKey\\" withAttributes:typeFile toDevice:context];
760                         [self goToPath:currentPath];
761                         [self resetTurbo];
762                 } */
766 /*- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
768         if ([prefs objectForKey:@"NoRollover"] != nil) return;
769         if ([aTableView mouseOverRow] == rowIndex && ([aTableView selectedRow] != rowIndex))
770                         if ([aTableView lockFocusIfCanDraw]) {
771                                 NSRect rowRect = [aTableView rectOfRow:rowIndex];
772                                 NSRect columnRect = [aTableView rectOfColumn:[[aTableView tableColumns] indexOfObject:aTableColumn]];
774                                         if (!highlightImage) {
775                                                 highlightImage = [[NSImage alloc] initWithData:[highlightImageData propertyList]];
776                                                         [highlightImage setDataRetained:YES]; //?
777                                                         [highlightImage setCacheMode:NSImageCacheAlways]; //?
778                                         }
780                                 [highlightImage drawInRect:NSIntersectionRect(rowRect, columnRect) fromRect:NSMakeRect(0,0,1,[highlightImage size].height) operation:NSCompositeSourceOver fraction:0.3];
781                                 [aTableView unlockFocus];
782                         }
786 - (void)dealloc
788   if (highlightImage) [highlightImage release];
789 [super dealloc];
792 - (IBAction)pauseCurrentTransfer:(id)sender {
793         if (!paused) {
794         [pauseButton setImage:[NSImage imageNamed:@"DownloadResume.tif"]];
795         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadResumePressed.tif"]];
796         //add priority "halt" to queue naming file
797         id current = [[tfusbc transferQueue] objectAtIndex:0];
798         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"pause",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
799         paused = YES;
800         [currentlyField setStringValue:[NSLocalizedString(@"PAUSED", @"Paused: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
801         [connectLight setImage:[NSImage imageNamed:@"green.tiff"]];
802         [currentlyField displayIfNeeded];
803         } else {
804         //change image to pause
805         //add priority "resume" to queue naming file
806         [pauseButton setImage:[NSImage imageNamed:@"DownloadStop.tif"]];
807         [pauseButton setAlternateImage:[NSImage imageNamed:@"DownloadStopPressed.tif"]];
808         id current = [[tfusbc pausedQueue] objectAtIndex:0];//temp as for now only have 1 paused
809         [tfusbc addPriorityTransfer:[NSDictionary dictionaryWithObjectsAndKeys:@"resume",@"transferType",[current objectForKey:@"filename"],@"filename",nil]];
810         paused = NO;
811         [currentlyField setStringValue:[NSLocalizedString(@"DOWNLOADING", @"Downloading: ") stringByAppendingString:[[current objectForKey:@"filename"]objectForKey:@"name"]]];
812         [connectLight setImage:[NSImage imageNamed:@"blink.tiff"]];
813         [currentlyField displayIfNeeded];
814         }
817 - (id) selectedColumn {
818         return selectedColumn;
820 - (id) currentlyField {
821         return currentlyField;
823 - (id) connectLight {
824         return connectLight;
827 @end