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

Revision 1273, 38.3 KB checked in by gbooker, 5 years ago (diff)

Now a mark menu item moves files to their auto sort path

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