source: trunk/SapphireFrappliance/SapphireImporterDataMenu.m @ 506

Revision 506, 13.2 KB checked in by gbooker, 7 years ago (diff)

This layout seems to work on both 1.1 and 2.0

Line 
1/*
2 * SapphireImporterDataMenu.m
3 * Sapphire
4 *
5 * Created by pnmerrill on Jun. 24, 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 "SapphireImporterDataMenu.h"
22#import <BackRow/BackRow.h>
23#import "SapphireMetaData.h"
24#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
25#import "SapphireImportHelper.h"
26#import "SapphireApplianceController.h"
27
28@interface BRLayerController (compatounth)
29- (NSRect)controllerFrame;  /*technically wrong; it is really a CGRect*/
30@end
31
32@interface SapphireImporterDataMenu (private)
33- (void)layoutFrame;
34- (void)setFileProgress:(NSString *)updateFileProgress;
35- (void)resetUIElements;
36- (void)pause;
37- (void)itemImportBackgrounded;
38@end
39
40@implementation SapphireImporterDataMenu
41- (id) initWithScene: (BRRenderScene *) scene metaDataCollection:(SapphireMetaDataCollection *)collection  importer:(id <SapphireImporter>)import
42{
43        if ( [super initWithScene: scene] == nil )
44                return ( nil );
45        metaCollection = [collection retain];
46        importer = [import retain];
47        [importer setImporterDataMenu:self];
48        importItems = [[NSMutableArray alloc] init];
49        /*Setup the Header Control with default contents*/
50        [self setListTitle:BRLocalizedString(@"Populate Show Data", @"Do a file metadata import")];
51
52        /*Setup the text entry control*/
53        text = [SapphireFrontRowCompat newTextControlWithScene:scene];
54        fileProgress = [SapphireFrontRowCompat newTextControlWithScene:scene];
55        currentFile = [SapphireFrontRowCompat newTextControlWithScene:scene];
56       
57        /*Setup the progress bar*/
58        bar = [SapphireFrontRowCompat newProgressBarWidgetWithScene:scene];
59        [self layoutFrame];
60       
61        [[self list] setDatasource:self];
62       
63        /*add controls*/
64        [self addControl: text];
65        [self addControl: fileProgress] ;
66        [self addControl: currentFile] ;
67        [SapphireFrontRowCompat addSublayer:bar toControl:self];
68
69    return ( self );
70}
71
72- (void) dealloc
73{
74        [text release];
75        [fileProgress release];
76        [currentFile release];
77        [bar release];
78        [metaCollection release];
79        [collectionDirectories release];
80        [importItems release];
81        [importTimer invalidate];
82        [importer setImporterDataMenu:nil];
83        [importer release];
84        [buttonTitle release];
85        [super dealloc];
86}
87
88- (void)layoutFrame
89{
90        /*title*/
91        NSRect frame = [SapphireFrontRowCompat frameOfController:self];
92        frame.origin.y += frame.size.height * 5.0f / 16.0f;
93        frame.origin.x = frame.size.width / 6.0f;
94        frame.size.height = frame.size.height / 16.0f;
95        frame.size.width = frame.size.width * 2.0f / 3.0f;
96        [bar setFrame: frame] ;
97}
98
99/*!
100 * @brief Sets the informative text
101 *
102 * @param theText The text to set
103 */
104- (void)setText:(NSString *)theText
105{
106        [SapphireFrontRowCompat setText:theText withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:text];
107       
108        NSRect master = [SapphireFrontRowCompat frameOfController:self];
109        NSSize txtSize = [SapphireFrontRowCompat textControl:text renderedSizeWithMaxSize:NSMakeSize(master.size.width * 2.0f/3.0f, master.size.height * 0.4f)];
110       
111        NSRect frame;
112        frame.origin.x = (master.size.width - txtSize.width) * 0.5f;
113        frame.origin.y = (master.size.height * 0.4f - txtSize.height) + master.size.height * 0.3f/0.8f + master.origin.y;
114        frame.size = txtSize;
115        [text setFrame:frame];
116}
117
118/*!
119 * @brief Sets the file progress string
120 *
121 * @param theFileProgress The file progress string to display
122 */
123- (void)setFileProgress:(NSString *)theFileProgress
124{
125        [SapphireFrontRowCompat setText:theFileProgress withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileProgress];
126       
127        NSRect master = [SapphireFrontRowCompat frameOfController:self];
128        NSSize progressSize = [SapphireFrontRowCompat textControl:fileProgress renderedSizeWithMaxSize:NSMakeSize(master.size.width * 1.0f/2.0f, master.size.height * 0.3f)];
129       
130        NSRect frame;
131        frame.origin.x =  (master.size.width) * 0.1f;
132        frame.origin.y = (master.size.height * 0.12f) + master.origin.y;
133        frame.size = progressSize;
134        [fileProgress setFrame:frame];
135}
136
137/*!
138 * @brief Sets the display of the current file being processed
139 *
140 * @param theCurrentFile The current file being proccessed
141 */
142- (void)setCurrentFile:(NSString *)theCurrentFile
143{
144        [SapphireFrontRowCompat setText:theCurrentFile withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:currentFile];
145       
146        NSRect master = [SapphireFrontRowCompat frameOfController:self];
147        NSSize currentFileSize = [SapphireFrontRowCompat textControl:currentFile renderedSizeWithMaxSize:NSMakeSize(master.size.width * 9.0f/10.0f, master.size.height * 0.3f)];
148       
149        NSRect frame;
150        frame.origin.x =  (master.size.width) * 0.1f;
151        frame.origin.y = (master.size.height * 0.09f) + master.origin.y;
152        frame.size = currentFileSize;
153        [currentFile setFrame:frame];
154}
155
156/*!
157 * @brief Get the list of all files to process
158 */
159- (void)getItems
160{
161        NSString *path = [collectionDirectories objectAtIndex:collectionIndex];
162        if([metaCollection skipCollection:path])
163        {
164                collectionIndex++;
165                [self performSelector:@selector(gotSubFiles:) withObject:[NSArray array] afterDelay:0.0];
166                return;
167        }
168        SapphireDirectoryMetaData *meta = [metaCollection directoryForPath:path];
169        [meta getSubFileMetasWithDelegate:self skipDirectories:[NSMutableSet setWithSet:[metaCollection skipDirectories]]];
170        collectionIndex++;
171}
172
173- (void)setButtonTitle:(NSString *)title
174{
175        if(title != nil)
176        {
177                [buttonTitle release];
178                buttonTitle = [title retain];
179        }
180        BRListControl *list = [self list];
181       
182        [list setHidden:(title == nil)];
183       
184        [list reload];
185}
186
187/*!
188 * @brief Start the import process
189 */
190- (void)import
191{
192        /*Change display*/
193        [self setButtonTitle:BRLocalizedString(@"Cancel Import", @"Cancel the import process")];
194        action = @selector(cancel);
195        [self setFileProgress:BRLocalizedString(@"Initializing...", @"The import is starting")];
196        [SapphireFrontRowCompat renderScene:[self scene]];
197        /*Initialize the import process*/
198        canceled = NO;
199        suspended = NO;
200        collectionIndex = 0;
201        [collectionDirectories release];
202        collectionDirectories = [[metaCollection collectionDirectories] retain];
203        [self getItems];
204}
205
206/*!
207 * @brief Metadata delegate method to return final list of files
208 *
209 * @param subs The files which are children of the current directory
210 */
211- (void)gotSubFiles:(NSArray *)subs
212{
213        [importItems addObjectsFromArray:subs];
214        if(collectionIndex != [collectionDirectories count])
215        {
216                [self getItems];
217                return;
218        }
219        updated = 0 ;
220        current = 0;
221        max = [importItems count];
222        if(!canceled)
223                importTimer = [NSTimer scheduledTimerWithTimeInterval:0.0f target:self selector:@selector(importNextItem:) userInfo:nil repeats:YES];
224}
225
226/*!
227 * @brief Metadata delegate method to inform on its scanning progress
228 *
229 * @param dir The current directory it is scanning
230 */
231- (void)scanningDir:(NSString *)dir
232{
233        [self setCurrentFile:[NSString stringWithFormat:BRLocalizedString(@"Scanning Directory: %@", "Current scan import process format, directory"),dir]];
234        [SapphireFrontRowCompat renderScene:[self scene]];
235}
236
237/*!
238 * @brief Ask if we should cancel the fetching of file listing
239 *
240 * @return YES if the file listing should be canceled, NO otherwise
241 */
242- (BOOL)getSubFilesCanceled
243{
244        return canceled;
245}
246
247/*!
248 * @brief Import a single item
249 *
250 * @return YES if any data was imported, NO otherwise
251 */
252- (BOOL)doImport
253{
254        BOOL ret = NO;
255        @try {
256                ImportState result = [importer importMetaData:[importItems objectAtIndex:0]];
257                switch(result)
258                {
259                        case IMPORT_STATE_UPDATED:
260                                ret = YES;
261                                break;
262                        case IMPORT_STATE_NEEDS_SUSPEND:
263                                [self pause];
264                                ret = NO;
265                                break;
266                        case IMPORT_STATE_BACKGROUND:
267                                [self itemImportBackgrounded];
268                                ret = NO;
269                                break;
270                }
271        }
272        @catch (NSException * e) {
273                [SapphireApplianceController logException:e];
274                [e raise];
275        }
276        @finally {
277                return ret;
278        }
279}
280
281/*!
282 * @brief Change the display to show the completion text
283 */
284- (void)setCompletionText
285{
286        [self setText:[importer completionText]];
287}
288
289/*!
290 * @brief Timer function to start the import of the next file
291 *
292 * @param timer The timer that triggered this
293 */
294- (void)importNextItem:(NSTimer *)timer
295{
296        if([importItems count])
297        {
298                /*Update the display*/
299                SapphireFileMetaData *fileMeta = [importItems objectAtIndex:0];
300                NSString * fileName=[[fileMeta path] lastPathComponent] ;
301                [self setCurrentFile:[NSString stringWithFormat:BRLocalizedString(@"Current File: %@", "Current TV Show import process format, filename"),fileName]];
302               
303                current++ ;
304                /*Update the imported count*/
305                if([self doImport] && !backgrounded)
306                        updated++;             
307               
308                /*Check for a suspend and reimport afterwards*/
309                if(suspended || backgrounded)
310                {
311                        backgrounded = NO;
312                        current--;
313                        return;
314                }
315               
316                /*Start with the first item*/
317                [importItems removeObjectAtIndex:0];
318        }
319        else
320                [self setCurrentFile:BRLocalizedString(@"Waiting for background import to complete", @"The import is complete, just waiting on background processes")];
321        [self setFileProgress:[NSString stringWithFormat:BRLocalizedString(@"File Progress: %0.0f / %0.0f", @"Import progress format, current and the max"), current, max,updated]];
322        [bar setPercentage:current/max * 100.0f];
323       
324        /*Check for completion*/
325        if(current == max)
326        {
327                [importTimer invalidate];
328                importTimer = nil;
329                [metaCollection writeMetaData];
330                /*Update display*/
331                [self setButtonTitle:nil];
332                action = NULL;
333                [self setListTitle:BRLocalizedString(@"Import Complete", @"The import is complete")];
334                [self setFileProgress:[NSString stringWithFormat:BRLocalizedString(@"Updated %0.0f Entries.", @"Import complete format with number updated"), updated]];
335                [self setCurrentFile:@""];
336                [self setCompletionText];
337                [SapphireFrontRowCompat renderScene:[self scene]];
338        }
339}
340
341/*!
342 * @brief Cancel the import process
343 */
344- (void)cancel
345{
346        /*Kill the timer*/
347        canceled = YES;
348        [importTimer invalidate];
349        importTimer = nil;
350        [importItems removeAllObjects];
351        [[SapphireImportHelper sharedHelper] removeObjectsWithInform:self];
352        /*Reset the display and write data*/
353        [self resetUIElements];
354        [metaCollection writeMetaData];
355}
356
357- (void)pause
358{
359        /*Kil lthe timer*/
360        suspended = YES;
361        [importTimer invalidate];
362        importTimer = nil;
363}
364
365- (void)resume
366{
367        /*Sanity checks*/
368        [importTimer invalidate];
369        /*Resume*/
370        suspended = NO;
371        importTimer = [NSTimer scheduledTimerWithTimeInterval:0.0f target:self selector:@selector(importNextItem:) userInfo:nil repeats:YES];
372}
373
374- (oneway void)informComplete:(BOOL)fileUpdated
375{
376        if(fileUpdated)
377                updated++;
378        current++;
379        [self importNextItem:nil];
380}
381
382- (void)itemImportBackgrounded
383{
384        if([importItems count] && !suspended)
385                [importItems removeObjectAtIndex:0];
386        backgrounded = YES;
387}
388
389- (void)skipNextItem
390{
391        /*Remove the next item from the queue*/
392        if([importItems count])
393                [importItems removeObjectAtIndex:0];
394        current++;
395}
396
397/*!
398 * @brief Reset the UI after an import completion or cancel
399 */
400- (void)resetUIElements
401{
402        [self setFileProgress:@" "];
403        [self setCurrentFile:@" "] ;
404        [bar setPercentage:0.0f];
405        action = @selector(import);
406        [self setListTitle:[importer initialText]];
407        [self setText:[importer informativeText]];
408        [self setButtonTitle:[importer buttonTitle]];
409}
410
411- (void)wasPushed
412{
413        [self layoutFrame];
414        [self resetUIElements];
415        [super wasPushed];
416}
417
418- (void)wasPopped
419{
420        /*Someone hit menu, so cancel*/
421        [self cancel];
422        [super wasPopped];
423}
424
425- (void) wasExhumedByPoppingController: (BRLayerController *) controller
426{
427        [importer wasExhumedByPoppingController:controller];
428        [super wasExhumedByPoppingController:controller];
429}
430
431- (BOOL)brEventAction:(BREvent *)event{
432        BREventPageUsageHash hashVal = [event pageUsageHash];
433       
434        if([(BRControllerStack *)[self stack] peekController] != self || action == NULL)
435                hashVal = 0;
436       
437        switch(hashVal)
438        {
439                case kBREventTapPlayPause:
440                case kBREventHoldPlayPause:
441                        [self performSelector:action];
442                        return YES;
443                        break;
444        }
445        return [super brEventAction:event];
446}
447
448- (long) itemCount
449{
450        return 1;
451}
452
453- (id<BRMenuItemLayer>) itemForRow: (long) row
454{
455        BRAdornedMenuItemLayer *result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:NO];
456        [SapphireFrontRowCompat setTitle:buttonTitle forMenu:result];
457       
458        return result;
459}
460
461- (NSString *) titleForRow: (long) row
462{
463       
464        if ( row >= 1 ) return ( nil );
465       
466        NSString *result = buttonTitle ;
467       
468        return [NSString stringWithFormat:@"  ????? %@", result];
469}
470
471- (long) rowForTitle: (NSString *) aTitle
472{
473    long result = -1;
474    long i, count = [self itemCount];
475    for ( i = 0; i < count; i++ )
476    {
477        if ( [aTitle isEqualToString: [self titleForRow: i]] )
478        {
479            result = i;
480            break;
481        }
482    }
483   
484    return ( result );
485}
486
487- (NSRect)listRectWithSize:(NSRect)listFrame inMaster:(NSRect)master
488{
489        listFrame.size.height = master.size.height * 3.0f / 16.0f;
490        listFrame.origin.y = master.size.height / 8.0f;
491        listFrame.size.width = master.size.width / 3.0f;
492        listFrame.origin.x = master.size.width / 3.0f;
493        return listFrame;
494}
495
496@end
Note: See TracBrowser for help on using the repository browser.