source: trunk/SapphireFrappliance/Browser/SapphireMarkMenu.m @ 1270

Revision 1270, 36.7 KB checked in by gbooker, 5 years ago (diff)

Corrected spelling of invocation

Line 
1/*
2 * SapphireMarkMenu.m
3 * Sapphire
4 *
5 * Created by Graham Booker on Jun. 25, 2007.
6 * Copyright 2007 Sapphire Development Team and/or www.nanopi.net
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation; either version 3 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
14 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 * Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program; if not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#import "SapphireMarkMenu.h"
22#import "SapphireDirectoryMetaData.h"
23#import "SapphireCollectionDirectory.h"
24#import "SapphireFileMetaData.h"
25#import "SapphireJoinedFile.h"
26#import "SapphireMetaDataSupport.h"
27#import "SapphireMediaPreview.h"
28#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
29#import <QTKit/QTKit.h>
30#import "SapphireTextEntryController.h"
31#import "SapphireErrorDisplayController.h"
32#import "SapphireWaitDisplay.h"
33#import "SapphireConfirmPrompt.h"
34#import "SapphireApplianceController.h"
35#import "SapphirePosterChooser.h"
36#import "NSImage-Extensions.h"
37#import "NSFileManager-Extensions.h"
38#import "SapphireSettings.h"
39
40BOOL allowCoverArtChange( NSString * const path )
41{
42        if ( [[NSFileManager defaultManager] hasVIDEO_TS:path] )
43                return NO;
44       
45        static NSSet *disallowedFormats = nil;
46        if(disallowedFormats == nil)
47        {
48                disallowedFormats = [[NSSet alloc] initWithObjects:@"mkv", @"flv", nil];
49        }
50       
51        return ![disallowedFormats containsObject:[path pathExtension]];
52}
53
54@implementation SapphireMarkMenu
55
56NSString *MARK_NAME                                     = @"Name";
57NSString *MARK_DESCRIPTION                      = @"Description";
58NSString *MARK_COMMAND                          = @"Command";
59
60typedef enum {
61        COMMAND_MARK_WATCHED,
62        COMMAND_MARK_UNWATCHED,
63        COMMAND_MARK_FAVORITE,
64        COMMAND_MARK_NOT_FAVORITE,
65        COMMAND_MARK_TO_REFETCH_TV,
66        COMMAND_MARK_TO_REFETCH_MOVIE,
67        COMMAND_MARK_TO_DELETE_METADATA,
68        COMMAND_MARK_TO_RESET_IMPORT,
69        COMMAND_RENAME,
70        COMMAND_RENAME_TO_PRETTY,
71        COMMAND_CUT_PATH,
72        COMMAND_DELETE_PATH,
73        COMMAND_CHANGE_ARTWORK,
74        //File Only Commands
75        COMMAND_MARK_TO_JOIN,
76        COMMAND_MARK_AND_JOIN,
77        COMMAND_CLEAR_JOIN_MARK,
78        COMMAND_JOIN,
79        COMMAND_SHOW_ONLY_SUMMARY,
80        //Directory Only Commands
81        COMMAND_TOGGLE_SKIP,
82        COMMAND_TOGGLE_COLLECTION,
83        COMMAND_PASTE_PATH,
84} MarkCommand;
85
86static NSMutableArray *joinList;
87static NSString *movingPath = nil;
88
89+ (void)initialize
90{
91        joinList = [[NSMutableArray alloc] init];
92}
93
94- (id) initWithScene: (BRRenderScene *) scene metaData: (id <SapphireMetaData>)meta
95{
96        self = [super initWithScene:scene];
97        if(!self)
98                return nil;
99       
100        /*Check to see if it is directory or file*/
101        isDir = [meta conformsToProtocol:@protocol(SapphireDirectory)];
102        metaData = [meta retain];
103        /*Create the menu*/
104        if(isDir)
105        {
106                marks = [[NSMutableArray alloc] initWithObjects:
107                        [NSDictionary dictionaryWithObjectsAndKeys:
108                                BRLocalizedString(@"Rename this Directory", @"Rename a directory"), MARK_NAME,
109                                BRLocalizedString(@"Edit the name for this directory", @"Renaming a directory description"), MARK_DESCRIPTION,
110                                [NSNumber numberWithInt:COMMAND_RENAME], MARK_COMMAND,
111                                nil],
112                        [NSDictionary dictionaryWithObjectsAndKeys:
113                                BRLocalizedString(@"Rename all Files to Pretty Name", @"Rename all files to a pretty name"), MARK_NAME,
114                                BRLocalizedString(@"Rename all files to a pretty name for those which a pretty name exists", @"Rename all files to a pretty name description"), MARK_DESCRIPTION,
115                                [NSNumber numberWithInt:COMMAND_RENAME_TO_PRETTY], MARK_COMMAND,
116                                nil],
117                        [NSDictionary dictionaryWithObjectsAndKeys:
118                                BRLocalizedString(@"Mark All as Watched", @"Mark whole directory as watched"), MARK_NAME,
119                                BRLocalizedString(@"Sapphire will save this directory as watched.", @"Mark directory watched description"), MARK_DESCRIPTION,
120                                [NSNumber numberWithInt:COMMAND_MARK_WATCHED], MARK_COMMAND,
121                                nil],
122                        [NSDictionary dictionaryWithObjectsAndKeys:
123                                BRLocalizedString(@"            Unwatched", @"Mark whole directory as unwatched"), MARK_NAME,
124                                BRLocalizedString(@"Sapphire will save this directory as unwatched.", @"Mark directory as unwatched description"), MARK_DESCRIPTION,
125                                [NSNumber numberWithInt:COMMAND_MARK_UNWATCHED], MARK_COMMAND,
126                                nil],
127                        [NSDictionary dictionaryWithObjectsAndKeys:
128                                BRLocalizedString(@"            Favorite", @"Mark whole directory as favorite"), MARK_NAME,
129                                BRLocalizedString(@"Sapphire will add this directory as favorite.", @"Mark directory as favorite description"), MARK_DESCRIPTION,
130                                [NSNumber numberWithInt:COMMAND_MARK_FAVORITE], MARK_COMMAND,
131                                nil],
132                        [NSDictionary dictionaryWithObjectsAndKeys:
133                                BRLocalizedString(@"            Not Favorite", @"Mark whole directory as not favorite"), MARK_NAME,
134                                BRLocalizedString(@"Sapphire will remove this directory from favorites.", @"Mark directory as not favorite"), MARK_DESCRIPTION,
135                                [NSNumber numberWithInt:COMMAND_MARK_NOT_FAVORITE], MARK_COMMAND,
136                                nil],
137                        [NSDictionary dictionaryWithObjectsAndKeys:
138                                BRLocalizedString(@"            Refetch TV Data", @"Mark whole directory to re-fetch its tv data"), MARK_NAME,
139                                BRLocalizedString(@"Tells Sapphire to refetch TV Show metadata for this directory the next time an import is run.", @"Mark directory to refetch tv data description"), MARK_DESCRIPTION,
140                                [NSNumber numberWithInt:COMMAND_MARK_TO_REFETCH_TV], MARK_COMMAND,
141                                nil],
142                        [NSDictionary dictionaryWithObjectsAndKeys:
143                                BRLocalizedString(@"            Refetch Movie Data", @"Mark whole directory to re-fetch its movie data"), MARK_NAME,
144                                BRLocalizedString(@"Tells Sapphire to refetch Movie metadata for this directory the next time an import is run.", @"Mark whole directory to re-fetch its movie data"), MARK_DESCRIPTION,
145                                [NSNumber numberWithInt:COMMAND_MARK_TO_REFETCH_MOVIE], MARK_COMMAND,
146                                nil],
147                        [NSDictionary dictionaryWithObjectsAndKeys:
148                                BRLocalizedString(@"            Clear Metadata", @"Mark whole directory to delete the metadata"), MARK_NAME,
149                                BRLocalizedString(@"Tells Sapphire to remove all metadata for this directory.", @"Mark directory to delete metadata description"), MARK_DESCRIPTION,
150                                [NSNumber numberWithInt:COMMAND_MARK_TO_DELETE_METADATA], MARK_COMMAND,
151                                nil],
152                        [NSDictionary dictionaryWithObjectsAndKeys:
153                                BRLocalizedString(@"            Reset Import Decisions", @"Mark whole directory to reset import decisions"), MARK_NAME,
154                                BRLocalizedString(@"Tells Sapphire to forget import decisions made on files in this directory.", @"Mark directory to reset import decisions description"), MARK_DESCRIPTION,
155                                [NSNumber numberWithInt:COMMAND_MARK_TO_RESET_IMPORT], MARK_COMMAND,
156                                nil],
157                         nil];
158                id <SapphireDirectory> dirMeta = (id <SapphireDirectory>)meta;
159                if([dirMeta isKindOfClass:[SapphireDirectoryMetaData class]])
160                {
161                        SapphireCollectionDirectory *collection = [(SapphireDirectoryMetaData *)dirMeta collectionDirectory];
162                        if([collection isMountValue])
163                        {
164                                [marks replaceObjectAtIndex:0 withObject:
165                                        [NSDictionary dictionaryWithObjectsAndKeys:
166                                                BRLocalizedString(@"Rename this Collection", @"Rename a collection"), MARK_NAME,
167                                                BRLocalizedString(@"Edit the display name for this collection", @"Rename a collection description"), MARK_DESCRIPTION,
168                                                [NSNumber numberWithInt:COMMAND_RENAME], MARK_COMMAND,
169                                                nil]];
170                        }
171                        if([collection skipValue])
172                        {
173                                [marks addObject:
174                                        [NSDictionary dictionaryWithObjectsAndKeys:
175                                                BRLocalizedString(@"Mark Directory For Importing", @"Marks this directory to be no longer be skipped during import"), MARK_NAME,
176                                                BRLocalizedString(@"Tells Sapphire it's okay to import from this directory.", @"Mark Directory For Importing description"), MARK_DESCRIPTION,
177                                                [NSNumber numberWithInt:COMMAND_TOGGLE_SKIP], MARK_COMMAND,
178                                                nil]];
179                        }
180                        else
181                        {
182                                [marks addObject:
183                                        [NSDictionary dictionaryWithObjectsAndKeys:
184                                                BRLocalizedString(@"Mark this Directory to Skip Import", @"Marks this directory to be skipped during import"), MARK_NAME,
185                                                BRLocalizedString(@"Tells Sapphire to skip this directory when importing.", @"Mark this Directory to Skip Import description"), MARK_DESCRIPTION,
186                                                [NSNumber numberWithInt:COMMAND_TOGGLE_SKIP], MARK_COMMAND,
187                                                nil]];
188                        }
189                        if(![collection isMountValue])
190                        {
191                                if(collection != nil)
192                                {
193                                        [marks addObject:
194                                                [NSDictionary dictionaryWithObjectsAndKeys:
195                                                        BRLocalizedString(@"                    to Not be a Collection", @"Marks the directory to no longer be a collection"), MARK_NAME,
196                                                        BRLocalizedString(@"Tells Sapphire to remove this directory from the Collections list.", @"Marks the directory to no longer be a collection description"), MARK_DESCRIPTION,
197                                                        [NSNumber numberWithInt:COMMAND_TOGGLE_COLLECTION], MARK_COMMAND,
198                                                        nil]];
199                                }
200                                else
201                                {
202                                        [marks addObject:
203                                                [NSDictionary dictionaryWithObjectsAndKeys:
204                                                        BRLocalizedString(@"                    as a Collection", @"Marks the directory to be a collection"), MARK_NAME,
205                                                        BRLocalizedString(@"Tells Sapphire to add this directory to the Collections list.", @"Marks the directory to be a collection description"), MARK_DESCRIPTION,
206                                                        [NSNumber numberWithInt:COMMAND_TOGGLE_COLLECTION], MARK_COMMAND,
207                                                        nil]];
208                                }
209                        }
210                        if(![collection isMountValue])
211                        {
212                                [marks addObject:
213                                        [NSDictionary dictionaryWithObjectsAndKeys:
214                                                BRLocalizedString(@"Move Directory", @"Marks this directory to be moved"), MARK_NAME,
215                                                BRLocalizedString(@"Move this directory.  Select destination later.", @"Marks this directory to be moved description"), MARK_DESCRIPTION,
216                                                [NSNumber numberWithInt:COMMAND_CUT_PATH], MARK_COMMAND,
217                                                nil]];
218                                [marks addObject:
219                                        [NSDictionary dictionaryWithObjectsAndKeys:
220                                                BRLocalizedString(@"Delete Directory", @"Marks this directory to be deleted"), MARK_NAME,
221                                                BRLocalizedString(@"Deletes this directory and its contents", @"Marks this directory to be deleted description"), MARK_DESCRIPTION,
222                                                [NSNumber numberWithInt:COMMAND_DELETE_PATH], MARK_COMMAND,
223                                                nil]];
224                        }
225                        if(movingPath != nil && ![[dirMeta path] hasPrefix:movingPath])
226                        {
227                                [marks addObject:
228                                        [NSDictionary dictionaryWithObjectsAndKeys:
229                                                BRLocalizedString(@"Move to Here", @"Move File to within this directory"), MARK_NAME,
230                                                [NSString stringWithFormat:BRLocalizedString(@"Move %@ to %@", @"parameter is last component of path, second is last path component of destination"), [movingPath lastPathComponent], [[meta path] lastPathComponent]], MARK_DESCRIPTION,
231                                                [NSNumber numberWithInt:COMMAND_PASTE_PATH], MARK_COMMAND,
232                                                nil]];
233                        }
234                }
235                else
236                {
237                        [marks removeObjectAtIndex:0];
238                }
239        }
240        else if([meta isKindOfClass:[SapphireFileMetaData class]])
241        {
242                SapphireFileMetaData *fileMeta = (SapphireFileMetaData *)metaData;
243                NSString *watched = nil;
244                NSString *watchedDesc = nil;
245                MarkCommand watchedCommand = 0;
246                NSString *favorite = nil;
247                NSString *favoriteDesc = nil;
248                MarkCommand favoriteCommand = 0;
249               
250                if([fileMeta watchedValue])
251                {
252                        watched                 = BRLocalizedString(@"Mark as Unwatched", @"Mark file as unwatched");
253                        watchedDesc             = BRLocalizedString(@"Sapphire will save this file as unwatched.", @"Mark directory watched description");
254                        watchedCommand  = COMMAND_MARK_UNWATCHED;
255                }
256                else
257                {
258                        watched                 = BRLocalizedString(@"Mark as Watched", @"Mark file as watched");
259                        watchedDesc             = BRLocalizedString(@"Sapphire will save this file as watched.", @"Mark directory watched description");
260                        watchedCommand  = COMMAND_MARK_WATCHED;
261                }
262
263                if([fileMeta favoriteValue])
264                {
265                        favorite                = BRLocalizedString(@"        Not Favorite", @"Mark file as a favorite");
266                        favoriteDesc    = BRLocalizedString(@"Sapphire will remove this file from favorites.", @"Mark directory as not favorite");
267                        favoriteCommand = COMMAND_MARK_NOT_FAVORITE;
268                }
269                else
270                {
271                        favorite                = BRLocalizedString(@"        Favorite", @"Mark file as not a favorite");
272                        favoriteDesc    = BRLocalizedString(@"Sapphire will add this file as a favorite.", @"Mark directory as favorite description");
273                        favoriteCommand = COMMAND_MARK_FAVORITE;
274
275                }
276                marks = [[NSMutableArray alloc] initWithObjects:
277                        [NSDictionary dictionaryWithObjectsAndKeys:
278                                BRLocalizedString(@"Rename this file", @"Rename a file"), MARK_NAME,
279                                BRLocalizedString(@"Move a file to another name", @"Rename file description"), MARK_DESCRIPTION,
280                                [NSNumber numberWithInt:COMMAND_RENAME], MARK_COMMAND,
281                                nil],
282                        [NSDictionary dictionaryWithObjectsAndKeys:
283                                watched, MARK_NAME,
284                                watchedDesc, MARK_DESCRIPTION,
285                                [NSNumber numberWithInt:watchedCommand], MARK_COMMAND,
286                                nil],
287                        [NSDictionary dictionaryWithObjectsAndKeys:
288                                favorite, MARK_NAME,
289                                favoriteDesc, MARK_DESCRIPTION,
290                                [NSNumber numberWithInt:favoriteCommand], MARK_COMMAND,
291                                nil],
292                        nil];
293               
294                NSString *prettyName = [fileMeta prettyName];
295                if(prettyName != nil && [[fileMeta fileName] caseInsensitiveCompare:prettyName] != NSOrderedSame)
296                {
297                        [marks insertObject:
298                                [NSDictionary dictionaryWithObjectsAndKeys:
299                                        BRLocalizedString(@"Rename to Pretty Name", @"Renaming to a pretty name menu title"), MARK_NAME,
300                                        [NSString stringWithFormat:BRLocalizedString(@"Rename to \"%@\"", @"Renaming to a pretty name menu title; Parameter is new name"), prettyName], MARK_DESCRIPTION,
301                                        [NSNumber numberWithInt:COMMAND_RENAME_TO_PRETTY], MARK_COMMAND,
302                                        nil]
303                                atIndex:1];
304                }
305                if([fileMeta joinedToFile] != nil)
306                {
307                        [marks removeObjectAtIndex:0];
308                }
309                int importType = [fileMeta importTypeValue];
310                if(importType | IMPORT_TYPE_TVSHOW_MASK)
311                {
312                        [marks addObject:
313                                [NSDictionary dictionaryWithObjectsAndKeys:
314                                        BRLocalizedString(@"        Refetch TV Data", @"Mark file to re-fetch its tv data"), MARK_NAME,
315                                        BRLocalizedString(@"Tells Sapphire to refetch TV Show metadata for this file the next time an import is run.", @"Mark file to refetch tv data description"), MARK_DESCRIPTION,
316                                        [NSNumber numberWithInt:COMMAND_MARK_TO_REFETCH_TV], MARK_COMMAND,
317                                        nil]];
318                }
319                if(importType | IMPORT_TYPE_MOVIE_MASK)
320                {
321                        [marks addObject:
322                                [NSDictionary dictionaryWithObjectsAndKeys:
323                                        BRLocalizedString(@"        Refetch Movie Data", @"Mark file to re-fetch its movie data"), MARK_NAME,
324                                        BRLocalizedString(@"Tells Sapphire to refetch Movie metadata for this file the next time an import is run.", @"Mark file to refetch movie description"), MARK_DESCRIPTION,
325                                        [NSNumber numberWithInt:COMMAND_MARK_TO_REFETCH_MOVIE], MARK_COMMAND,
326                                        nil]];
327                }
328                if([fileMeta importTypeValue] != 0)
329                {
330                        [marks addObject:
331                                [NSDictionary dictionaryWithObjectsAndKeys:
332                                        BRLocalizedString(@"        Clear Metadata", @"Mark a file to delete the metadata"), MARK_NAME,
333                                        BRLocalizedString(@"Tells Sapphire to remove all metadata for this file.", @"Mark file to delete metadata description"), MARK_DESCRIPTION,
334                                        [NSNumber numberWithInt:COMMAND_MARK_TO_DELETE_METADATA], MARK_COMMAND,
335                                        nil]];
336                }
337                if([fileMeta fileClass] != FILE_CLASS_UNKNOWN)
338                {
339                        [marks addObject:
340                                [NSDictionary dictionaryWithObjectsAndKeys:
341                                        BRLocalizedString(@"        Reset Import Decisions", @"Mark a file to reset import decisions"), MARK_NAME,
342                                        BRLocalizedString(@"Tells Sapphire to forget import decisions made on this file.", @"Mark a file to reset import decisions description"), MARK_DESCRIPTION,
343                                        [NSNumber numberWithInt:COMMAND_MARK_TO_RESET_IMPORT], MARK_COMMAND,
344                                        nil]];
345                }
346                if(![joinList containsObject:fileMeta])
347                {
348                        [marks addObject:
349                                [NSDictionary dictionaryWithObjectsAndKeys:
350                                        BRLocalizedString(@"Join To Other Files", @"Join To Other Files"), MARK_NAME,
351                                        BRLocalizedString(@"Tells Sapphire you wish to add this file to a list of files to be joined. The files will be joined in the order they were added to the list.", @"Mark file to be joined description"), MARK_DESCRIPTION,
352                                        [NSNumber numberWithInt:COMMAND_MARK_TO_JOIN], MARK_COMMAND,
353                                        nil]];
354                        [marks addObject:
355                                [NSDictionary dictionaryWithObjectsAndKeys:
356                                        BRLocalizedString(@"     This File and Complete", @"     This File and Complete"), MARK_NAME,
357                                        BRLocalizedString(@"Tells Sapphire to use this file to complete the joined list.", @"Mark file and join description"), MARK_DESCRIPTION,
358                                        [NSNumber numberWithInt:COMMAND_MARK_AND_JOIN], MARK_COMMAND,
359                                        nil]];
360                }
361                if([joinList count])
362                {
363                        NSString *joinName;
364                        if(![joinList containsObject:fileMeta])
365                                joinName = BRLocalizedString(@"     Selected Files", @"     Selected Files");
366                        else
367                                joinName = BRLocalizedString(@"Join Selected Files", @"     Selected Files");
368                       
369                        [marks addObject:
370                                [NSDictionary dictionaryWithObjectsAndKeys:
371                                        joinName, MARK_NAME,
372                                        BRLocalizedString(@"Tells Sapphire to complete the file join.", @"Join Marked Files description"), MARK_DESCRIPTION,
373                                        [NSNumber numberWithInt:COMMAND_JOIN], MARK_COMMAND,
374                                        nil]];
375                        [marks addObject:
376                                [NSDictionary dictionaryWithObjectsAndKeys:
377                                        BRLocalizedString(@"     Clear", @"     Clear"), MARK_NAME,
378                                        BRLocalizedString(@"Tells Sapphire to clear the file join list.", @"clear file join list description"), MARK_DESCRIPTION,
379                                        [NSNumber numberWithInt:COMMAND_CLEAR_JOIN_MARK], MARK_COMMAND,
380                                        nil]];
381                }
382                [marks addObject:
383                        [NSDictionary dictionaryWithObjectsAndKeys:
384                                BRLocalizedString(@"Display Description", @"Marks file to only display discription"), MARK_NAME,
385                                BRLocalizedString(@"Hide all other info in preview one time", @"Display Description description"), MARK_DESCRIPTION,
386                                [NSNumber numberWithInt:COMMAND_SHOW_ONLY_SUMMARY], MARK_COMMAND,
387                                 nil]];
388                [marks addObject:
389                        [NSDictionary dictionaryWithObjectsAndKeys:
390                                BRLocalizedString(@"Move File", @"Marks this file to be moved"), MARK_NAME,
391                                BRLocalizedString(@"Move this file.  Select destination later.", @"Moving a file description"), MARK_DESCRIPTION,
392                                [NSNumber numberWithInt:COMMAND_CUT_PATH], MARK_COMMAND,
393                                nil]];
394                [marks addObject:
395                        [NSDictionary dictionaryWithObjectsAndKeys:
396                                BRLocalizedString(@"Delete File", @"Marks this file to be deleted"), MARK_NAME,
397                                BRLocalizedString(@"Deletes this file", @"Deleting a fie description"), MARK_DESCRIPTION,
398                                [NSNumber numberWithInt:COMMAND_DELETE_PATH], MARK_COMMAND,
399                                nil]];
400                // Allow cover art change for all formats except for DVD, .mkv, and .flv
401                // QTMovie is broken on the ATV, don't do it there
402                if ([SapphireFrontRowCompat usingLeopard] && allowCoverArtChange( [meta path] ) )
403                {
404                        [marks addObject:
405                                [NSDictionary dictionaryWithObjectsAndKeys:
406                                        BRLocalizedString(@"Change artwork", @"Change artwork"), MARK_NAME,
407                                        BRLocalizedString(@"Select artwork using images from the file", @"Changing artwork description"), MARK_DESCRIPTION,
408                                        [NSNumber numberWithInt:COMMAND_CHANGE_ARTWORK], MARK_COMMAND,
409                                        nil]];
410                }
411        }
412        else
413        {
414                /*Neither, so just return nil*/
415                [self autorelease];
416                return nil;
417        }
418        [[self list] setDatasource:self];
419       
420        return self;
421}
422
423- (void) dealloc
424{
425        [marks release];
426        [metaData release];
427        [super dealloc];
428}
429
430- (BRLayerController *)loadArtwork:(SapphireFileMetaData *)fileMeta
431{
432        NSInvocation *invoke = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: @selector(doChangeArtwork:)]];
433        [invoke setSelector: @selector(doChangeArtwork:)];
434        [invoke setTarget:   self];
435       
436        SapphireWaitDisplay *wait = [[SapphireWaitDisplay alloc] initWithScene: [self scene]
437                                                                                                                                         title: BRLocalizedString(@"Getting artwork selection", @"Getting artwork selection")
438                                                                                                                                invocation: invoke];
439       
440        [invoke setArgument: &fileMeta atIndex: 2];
441        return [wait autorelease];
442}
443
444- (BRLayerController *)doChangeArtwork:(SapphireFileMetaData *)fileMeta
445{
446        SapphirePosterChooser *controller = [[SapphirePosterChooser alloc] initWithScene:[self scene]];
447
448        [controller setListTitle:BRLocalizedString(@"Select cover art", @"Select cover art")];
449        [controller setMovieTitle:@" "];
450        [controller setFile:fileMeta];
451        [controller setPosterImages:[NSImage imagesFromMovie:[fileMeta path] forArraySize:10]];
452       
453        NSInvocation *invoke = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector:@selector(doChangeArtwork:)]];
454        [invoke setSelector:@selector(doChangeArtwork:)];
455        [invoke setTarget:self];
456        [invoke retainArguments];
457        [invoke setArgument:&fileMeta atIndex:2];
458        [controller setRefreshInvocation:invoke];
459       
460        return [controller autorelease];
461}
462
463- (BRLayerController *)doJoin:(SapphireWaitDisplay *)wait
464{
465        @try {
466                if(![joinList count])
467                        return nil;
468               
469                BOOL isFav = NO, isUnwatched = NO;
470                QTMovie *resultingMovie = [[QTMovie alloc] init];
471                [resultingMovie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
472               
473                NSString *savePath = [[joinList objectAtIndex:0] path];
474                BOOL hasmovExt = [[savePath pathExtension] isEqualToString:@"mov"];
475                NSString *base = [[joinList objectAtIndex:0] extensionlessPath];
476                if([[base lowercaseString] hasSuffix:@" part 1"])
477                        base = [base substringToIndex:[base length] - 7];
478                if(hasmovExt)
479                        savePath = [[base stringByAppendingString:@" Joined"] stringByAppendingPathExtension:@"mov"];
480                else
481                        savePath = [base stringByAppendingPathExtension:@"mov"];
482               
483                NSManagedObjectContext *moc = [[joinList objectAtIndex:0] managedObjectContext];
484                NSMutableString *mutSavePath = [savePath mutableCopy];
485                [mutSavePath replaceOccurrencesOfString:@":" withString:@"-" options:0 range:NSMakeRange(0, [mutSavePath length])];  //Stupid QTKit Programmers.  This bug exists in QT Player in Leopard too.
486                savePath = [mutSavePath autorelease];
487                SapphireFileMetaData *finalFile = [SapphireFileMetaData createFileWithPath:savePath inContext:moc];
488                SapphireJoinedFile *joined = [SapphireJoinedFile joinedFileForPath:savePath inContext:moc];
489                int i, count=[joinList count];
490                for(i=0;i<count;i++)
491                {
492                        SapphireFileMetaData *meta = [joinList objectAtIndex:i];
493                        isFav |= [meta favoriteValue];
494                        isUnwatched |= ![meta watchedValue];
495                        [wait setCurrentStatus:[NSString stringWithFormat:BRLocalizedString(@"Opening %@", @"parameter is filename"), [[meta path] lastPathComponent]]];
496                        NSError *error = nil;
497                        NSDictionary *openAttr = [NSDictionary dictionaryWithObjectsAndKeys:
498                                                                          [meta path], QTMovieFileNameAttribute,
499                                                                          [NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
500                                                                          nil];
501                        QTMovie *current = [[QTMovie alloc] initWithAttributes:openAttr error:&error];
502                        if(error == nil)
503                        {
504                                QTTimeRange range;
505                                range.time = [current selectionStart];
506                                range.duration = [current duration];
507                                [current setSelection:range];
508                                [resultingMovie appendSelectionFromMovie:current];
509                                [meta setJoinedToFile:joined];
510                        }
511                        else
512                        {
513                                SapphireErrorDisplayController *errorDisplay = [[SapphireErrorDisplayController alloc] initWithScene:[self scene] error:BRLocalizedString(@"Read Error", @"Short error indicating an error while reading a file in a join") longError:[error localizedDescription]];
514                                [resultingMovie release];
515                                [current release];
516                                return [errorDisplay autorelease];
517                        }
518                        [current release];
519                }
520               
521                SapphireErrorDisplayController *errorDisplay = nil;
522                [wait setCurrentStatus:[NSString stringWithFormat:BRLocalizedString(@"Saving Joined File to %@", @"parameter is save path"), [savePath lastPathComponent]]];
523                [finalFile setWatchedValue:!isUnwatched];
524                [finalFile setFavoriteValue:isFav];
525                if(![resultingMovie writeToFile:savePath withAttributes:[NSDictionary dictionary]])
526                {
527                        errorDisplay = [[SapphireErrorDisplayController alloc] initWithScene:[self scene] error:BRLocalizedString(@"Save Error", @"Short error indicating an error while saving a file in a join") longError:BRLocalizedString(@"Save Error", @"Short error indicating an error while saving a file in a join")];
528                }
529                [resultingMovie release];
530                [joinList removeAllObjects];
531                [SapphireMetaDataSupport save:moc];
532                return [errorDisplay autorelease];
533        }
534        @catch (NSException * e) {
535                [SapphireApplianceController logException:e];
536        }
537        return nil;
538}
539
540- (long)itemCount
541{
542    // return the number of items in your menu list here
543        return [marks count];
544}
545
546- (id<BRMenuItemLayer>)itemForRow:(long)row
547{
548        /*
549         // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
550         // return that object, it will be used to display the list item.
551         return ( nil );
552         */
553        if(row >= [marks count])
554                return nil;
555       
556        BRAdornedMenuItemLayer *result = nil;
557        NSDictionary *mark = [marks objectAtIndex:row];
558        NSString *name = [mark objectForKey:MARK_NAME];
559        result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:NO];
560       
561        // add text
562        [SapphireFrontRowCompat setTitle:name forMenu:result];
563                               
564        return result;
565}
566
567- (NSString *)titleForRow:(long)row
568{
569       
570        if(row >= [marks count])
571                return nil;
572       
573        NSString *result = [[marks objectAtIndex:row] objectForKey:MARK_NAME];
574        return result;
575}
576
577- (long)rowForTitle:(NSString *)title
578{
579    long result = -1;
580    long i, count = [self itemCount];
581    for(i = 0; i < count; i++)
582    {
583        if([title isEqualToString:[self titleForRow:i]])
584        {
585            result = i;
586            break;
587        }
588    }
589   
590    return result;
591}
592
593- (void)itemSelected:(long) row
594{
595    // This is called when the user presses play/pause on a list item
596        if(row >= [marks count])
597                return;
598       
599        NSManagedObjectContext *moc = [metaData managedObjectContext];
600        BRLayerController *replaceController = nil;
601        MarkCommand command = [[[marks objectAtIndex:row] objectForKey:MARK_COMMAND] intValue];
602        /*Do action on dir or file*/
603        if(isDir)
604        {
605                id <SapphireDirectory> dirMeta = (id <SapphireDirectory>)metaData;
606                SapphireCollectionDirectory *collection = nil;
607                if([dirMeta isKindOfClass:[SapphireDirectoryMetaData class]])
608                        collection = [(SapphireDirectoryMetaData *)dirMeta collectionDirectory];
609                NSString *path = [dirMeta path];
610                switch(command)
611                {
612                        case COMMAND_MARK_WATCHED:
613                                setSubtreeToWatched(dirMeta, YES);
614                                break;
615                        case COMMAND_MARK_UNWATCHED:
616                                setSubtreeToWatched(dirMeta, NO);
617                                break;
618                        case COMMAND_MARK_FAVORITE:
619                                setSubtreeToFavorite(dirMeta, YES);
620                                break;
621                        case COMMAND_MARK_NOT_FAVORITE:
622                                setSubtreeToFavorite(dirMeta, NO);
623                                break;
624                        case COMMAND_MARK_TO_REFETCH_TV:
625                                setSubtreeToReimportFromMask(dirMeta, IMPORT_TYPE_TVSHOW_MASK);
626                                break;
627                        case COMMAND_MARK_TO_REFETCH_MOVIE:
628                                setSubtreeToReimportFromMask(dirMeta, IMPORT_TYPE_MOVIE_MASK);
629                                break;
630                        case COMMAND_MARK_TO_DELETE_METADATA:
631                                setSubtreeToClearMetaData(dirMeta);
632                                break;
633                        case COMMAND_MARK_TO_RESET_IMPORT:
634                                setSubtreeToResetImportDecisions(dirMeta);
635                                break;
636                        case COMMAND_TOGGLE_SKIP:
637                                if(collection == nil)
638                                        [SapphireCollectionDirectory collectionAtPath:path mount:NO skip:YES hidden:NO manual:NO inContext:moc];
639                                else
640                                        [collection setSkipValue:![collection skipValue]];
641                                break;
642                        case COMMAND_TOGGLE_COLLECTION:
643                                if(collection == nil)
644                                        [SapphireCollectionDirectory collectionAtPath:path mount:NO skip:NO hidden:NO manual:YES inContext:moc];
645                                else
646                                        [moc deleteObject:collection];
647                                break;
648                        case COMMAND_RENAME:
649                                if([dirMeta isKindOfClass:[SapphireDirectoryMetaData class]])
650                                {
651                                        NSString *title = [NSString stringWithFormat:BRLocalizedString(@"Rename %@", @"Rename a file, directory, or collection, argument is path"), [dirMeta path]];
652                                        NSInvocation *invoke;
653                                        NSString *oldName;
654                                        if(collection == nil)
655                                        {
656                                                oldName = [[dirMeta path] lastPathComponent];
657                                                invoke = [NSInvocation invocationWithMethodSignature:[(SapphireDirectoryMetaData *)dirMeta methodSignatureForSelector:@selector(rename:)]];
658                                                [invoke setTarget:dirMeta];
659                                        }
660                                        else
661                                        {
662                                                oldName = [collection name];
663                                                if([oldName length] == 0)
664                                                        oldName = title;
665                                               
666                                                invoke = [NSInvocation invocationWithMethodSignature:[collection methodSignatureForSelector:@selector(rename:)]];
667                                                [invoke setTarget:collection];
668                                        }
669                                        [invoke setSelector:@selector(rename:)];
670                                        SapphireTextEntryController *rename = [[SapphireTextEntryController alloc] initWithScene:[self scene] title:title defaultText:oldName completionInvocation:invoke];
671                                        replaceController = [rename autorelease];
672                                }
673                                break;
674                        case COMMAND_RENAME_TO_PRETTY:
675                                doSubtreeInvocation(dirMeta, @selector(renameToPrettyName), nil);
676                                break;
677                        case COMMAND_CUT_PATH:
678                                [movingPath release];
679                                movingPath = [[dirMeta path] retain];
680                                break;
681                        case COMMAND_PASTE_PATH:
682                        {
683                                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(pasteInDir:)]];
684                                [invoke setSelector:@selector(pasteInDir:)];
685                                [invoke setTarget:self];
686                                [invoke setArgument:&dirMeta atIndex:2];
687                               
688                                SapphireWaitDisplay *wait = [[SapphireWaitDisplay alloc] initWithScene:[self scene] title:[NSString stringWithFormat:BRLocalizedString(@"Moving %@", @"parameter is file/dir that is being moved"), [movingPath lastPathComponent]] invocation:invoke];
689                               
690                                replaceController = [wait autorelease];
691                        }
692                                break;
693                        case COMMAND_DELETE_PATH:
694                        {
695                                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(deleteReturnedResult:atPath:)]];
696                                [invoke setSelector:@selector(deleteReturnedResult:atPath:)];
697                                [invoke setTarget:self];
698                                [invoke setArgument:&dirMeta atIndex:3];
699                                [invoke retainArguments];
700                               
701                                SapphireConfirmPrompt *confirm = [[SapphireConfirmPrompt alloc] initWithScene:[self scene] title:BRLocalizedString(@"Delete Directory?", @"Delete Directory Prompt Title") subtitle:[NSString stringWithFormat:BRLocalizedString(@"Are you sure you wish to delete %@?", @"parameter is file/dir that is being deleted"), [[dirMeta path] lastPathComponent]] invocation:invoke];
702                               
703                                replaceController = [confirm autorelease];
704                        }
705                }
706        }
707        else
708        {
709                SapphireFileMetaData *fileMeta = (SapphireFileMetaData *)metaData;
710                switch(command)
711                {
712                        case COMMAND_MARK_WATCHED:
713                                [fileMeta setWatchedValue:YES];
714                                [fileMeta setResumeTime:0];
715                                break;
716                        case COMMAND_MARK_UNWATCHED:
717                                [fileMeta setWatchedValue:NO];
718                                [fileMeta setResumeTime:0];
719                                break;
720                        case COMMAND_MARK_FAVORITE:
721                                [fileMeta setFavoriteValue:YES];
722                                break;
723                        case COMMAND_MARK_NOT_FAVORITE:
724                                [fileMeta setFavoriteValue:NO];
725                                break;
726                        case COMMAND_MARK_TO_REFETCH_TV:
727                                [fileMeta setToReimportFromMaskValue:IMPORT_TYPE_TVSHOW_MASK];
728                                break;
729                        case COMMAND_MARK_TO_REFETCH_MOVIE:
730                                [fileMeta setToReimportFromMaskValue:IMPORT_TYPE_MOVIE_MASK];
731                                break;
732                        case COMMAND_MARK_TO_DELETE_METADATA:
733                                [fileMeta clearMetaData];
734                                break;
735                        case COMMAND_MARK_TO_RESET_IMPORT:
736                                [fileMeta setToResetImportDecisions];
737                                break;
738                        case COMMAND_MARK_TO_JOIN:
739                                [joinList addObject:fileMeta];
740                                break;
741                        case COMMAND_CLEAR_JOIN_MARK:
742                                [joinList removeAllObjects];
743                                break;
744                        case COMMAND_MARK_AND_JOIN:
745                                [joinList addObject:fileMeta];
746                        case COMMAND_JOIN:
747                        {
748                                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(doJoin:)]];
749                                [invoke setSelector:@selector(doJoin:)];
750                                [invoke setTarget:self];
751                               
752                                SapphireWaitDisplay *wait = [[SapphireWaitDisplay alloc] initWithScene:[self scene] title:BRLocalizedString(@"Joining Files", @"Title for wait display while joining files") invocation:invoke];
753                                [invoke setArgument:&wait atIndex:2];
754                               
755                                replaceController = [wait autorelease];
756                        }
757                                break;
758                        case COMMAND_SHOW_ONLY_SUMMARY:
759                                [[SapphireSettings sharedSettings] setDisplayOnlyPlotUntil:[NSDate dateWithTimeIntervalSinceNow:5]];
760                                break;
761                        case COMMAND_RENAME:
762                        {
763                                NSString *title = [NSString stringWithFormat:BRLocalizedString(@"Rename %@", @"Rename a file, directory, or collection, argument is path"), [fileMeta path]];
764                                NSString *oldName = [fileMeta fileName];
765                               
766                                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:[fileMeta methodSignatureForSelector:@selector(rename:)]];
767                                [invoke setSelector:@selector(rename:)];
768                                [invoke setTarget:fileMeta];
769                                SapphireTextEntryController *rename = [[SapphireTextEntryController alloc] initWithScene:[self scene] title:title defaultText:oldName completionInvocation:invoke];
770                                replaceController = [rename autorelease];                               
771                        }
772                                break;
773                        case COMMAND_RENAME_TO_PRETTY:
774                        {
775                                NSString *error = [fileMeta renameToPrettyName];
776                                if(error != nil)
777                                        replaceController = [[[SapphireErrorDisplayController alloc] initWithScene:[self scene] error:BRLocalizedString(@"Error", @"Short message indicating error condition") longError:error] autorelease];
778                        }
779                                break;
780                        case COMMAND_CUT_PATH:
781                                [movingPath release];
782                                movingPath = [[fileMeta path] retain];
783                                break;                         
784                        case COMMAND_DELETE_PATH:
785                        {
786                                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(deleteReturnedResult:atPath:)]];
787                                [invoke setSelector:@selector(deleteReturnedResult:atPath:)];
788                                [invoke setTarget:self];
789                                [invoke setArgument:&fileMeta atIndex:3];
790                                [invoke retainArguments];
791                               
792                                SapphireConfirmPrompt *confirm = [[SapphireConfirmPrompt alloc] initWithScene:[self scene] title:BRLocalizedString(@"Delete File?", @"Delete File Prompt Title") subtitle:[NSString stringWithFormat:BRLocalizedString(@"Are you sure you wish to delete %@?", @"parameter is file/dir that is being deleted"), [[fileMeta path] lastPathComponent]] invocation:invoke];
793                               
794                                replaceController = [confirm autorelease];
795                        }
796                                break;
797                        case COMMAND_CHANGE_ARTWORK:
798                                replaceController = [self loadArtwork:fileMeta];
799                                break;
800                }
801        }
802        /*Save and exit*/
803        [SapphireMetaDataSupport save:moc];
804        if(replaceController != nil)
805                [[self stack] swapController:replaceController];
806        else
807                [[self stack] popController];
808}
809
810- (BRControl *)pasteInDir:(SapphireDirectoryMetaData *)dirMeta
811{
812        NSManagedObjectContext *moc = [metaData managedObjectContext];
813        NSString *errorString = nil;
814        BOOL movingDir;
815        if(![[NSFileManager defaultManager] fileExistsAtPath:movingPath isDirectory:&movingDir])
816        {
817                errorString = [NSString stringWithFormat:BRLocalizedString(@"%@ Seems to be missing", @"Could not find file; parameter is moving file"), [movingPath lastPathComponent]];
818        }
819        else if(movingDir)
820        {
821                SapphireDirectoryMetaData *dir = [SapphireDirectoryMetaData directoryWithPath:movingPath inContext:moc];
822                errorString = [dir moveToDir:dirMeta];
823        }
824        else
825        {
826                SapphireFileMetaData *file = [SapphireFileMetaData fileWithPath:movingPath inContext:moc];
827                errorString = [file moveToDir:dirMeta];
828        }
829        if(errorString != nil)
830        {
831                SapphireErrorDisplayController *error = [[SapphireErrorDisplayController alloc] initWithScene:[self scene] error:BRLocalizedString(@"Moving Error", @"Short error indicating an error while moving a file") longError:errorString];
832                return [error autorelease];
833        }
834        else
835        {
836                [movingPath release];
837                movingPath = nil;
838        }
839        [SapphireMetaDataSupport save:moc];
840        return nil;
841}
842
843- (BRControl *)deleteReturnedResult:(SapphireConfirmPromptResult)result atPath:(id <SapphireMetaData>)meta
844{
845        if(result != SapphireConfirmPromptResultOK)
846                return nil;
847       
848        @try {
849                NSManagedObjectContext *moc = [meta managedObjectContext];
850                BOOL success = [[NSFileManager defaultManager] removeFileAtPath:[meta path] handler:nil];
851                if(!success)
852                {
853                        NSString *errorString = [NSString stringWithFormat:BRLocalizedString(@"Could not delete %@.  Is the filesystem read-only?", @"Unknown error renaming file/directory; parameter is name"), [[meta path] lastPathComponent]];
854                        SapphireErrorDisplayController *error = [[SapphireErrorDisplayController alloc] initWithScene:[self scene] error:BRLocalizedString(@"Delete Error", @"Short error indicating an error while deleting a file") longError:errorString];
855                        return [error autorelease];
856                }
857                [moc deleteObject:meta];
858                [SapphireMetaDataSupport save:moc];
859                return nil;
860        }
861        @catch (NSException * e) {
862                [SapphireApplianceController logException:e];
863        }
864        return nil;
865}
866
867- (id<BRMediaPreviewController>)previewControlForItem:(long)item
868{
869        return [self previewControllerForItem:item];
870}
871
872- (id<BRMediaPreviewController>)previewControllerForItem:(long)item
873{
874    // If subclassing BRMediaMenuController, this function is called when the selection cursor
875    // passes over an item.
876                if(item >= [marks count])
877                return nil;
878        else
879        {
880                /* Get setting name & kill cushion  */
881                NSDictionary *mark = [marks objectAtIndex:item];
882                NSString *markName = [NSString stringWithFormat:@"%@ for \"%@\"",[mark objectForKey:MARK_NAME],(NSString *)[self listTitle]];
883                NSString *markDescription = [mark objectForKey:MARK_DESCRIPTION];
884                /* Construct a gerneric metadata asset for display */
885                NSMutableDictionary *markMeta=[[NSMutableDictionary alloc] init];
886                [markMeta setObject:markName forKey:META_TITLE_KEY];
887                [markMeta setObject:[NSNumber numberWithInt:FILE_CLASS_UTILITY] forKey:FILE_CLASS_KEY];
888                [markMeta setObject:markDescription forKey:META_DESCRIPTION_KEY];
889                SapphireMediaPreview *preview = [[SapphireMediaPreview alloc] initWithScene:[self scene]];
890                [preview setUtilityData:markMeta];
891                [markMeta release];
892                [preview setShowsMetadataImmediately:YES];
893                /*And go*/
894                return [preview autorelease];
895        }
896    return ( nil );
897}
898
899@end
Note: See TracBrowser for help on using the repository browser.