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