summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--macosx/Controller.h4
-rw-r--r--macosx/Controller.m98
-rw-r--r--macosx/English.lproj/MainMenu.xib94
-rw-r--r--macosx/English.lproj/Presets.xib14
-rw-r--r--macosx/HBPreset.h31
-rw-r--r--macosx/HBPreset.m71
-rw-r--r--macosx/HBPresetsManager.h15
-rw-r--r--macosx/HBPresetsManager.m94
-rw-r--r--macosx/HBPresetsViewController.h16
-rw-r--r--macosx/HBPresetsViewController.m30
-rw-r--r--macosx/HBTreeNode.h44
-rw-r--r--macosx/HBTreeNode.m95
-rw-r--r--macosx/HandBrake.xcodeproj/project.pbxproj6
13 files changed, 360 insertions, 252 deletions
diff --git a/macosx/Controller.h b/macosx/Controller.h
index 3a20d59d4..b51c7bd41 100644
--- a/macosx/Controller.h
+++ b/macosx/Controller.h
@@ -147,7 +147,8 @@ extern NSString *keyTitleTag;
/* User Preset variables here */
HBPresetsManager * presetManager;
- HBPresetsViewController * fPresetsView;
+ HBPresetsViewController * fPresetsView;
+ IBOutlet NSMenu * presetsMenu;
IBOutlet NSDrawer * fPresetDrawer;
IBOutlet NSTextField * fPresetNewName;
@@ -304,7 +305,6 @@ extern NSString *keyTitleTag;
- (IBAction)selectDefaultPreset:(id)sender;
- (IBAction)addFactoryPresets:(id)sender;
-- (IBAction)deleteFactoryPresets:(id)sender;
- (IBAction)addUserPreset:(id)sender;
-(void)sendToMetaX:(NSString *) filePath;
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 25ed16048..2f14dae36 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -10,6 +10,7 @@
#import "HBPreferencesController.h"
#import "HBDVDDetector.h"
#import "HBPresetsManager.h"
+#import "HBPreset.h"
#import "HBPreviewController.h"
#import "DockTextField.h"
#import "HBUtilities.h"
@@ -560,8 +561,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[fWindow center];
[fWindow setExcludedFromWindowsMenu:NO];
- [self checkBuiltInsForUpdates];
-
fRipIndicatorShown = NO; // initially out of view in the nib
/* For 64 bit builds, the threaded animation in the progress
@@ -577,21 +576,20 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[fScanIndicator setUsesThreadedAnimation:NO];
[fRipIndicator setUsesThreadedAnimation:NO];
-
-
-
+
+ [fPresetDrawer setDelegate:self];
+ NSSize drawerSize = NSSizeFromString([[NSUserDefaults standardUserDefaults]
+ stringForKey:@"Drawer Size"]);
+ if (drawerSize.width)
+ [fPresetDrawer setContentSize: drawerSize];
+
/* Show/Dont Show Presets drawer upon launch based
on user preference DefaultPresetsDrawerShow*/
- if( [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0 )
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"])
{
- [fPresetDrawer setDelegate:self];
- NSSize drawerSize = NSSizeFromString( [[NSUserDefaults standardUserDefaults]
- stringForKey:@"Drawer Size"] );
- if( drawerSize.width )
- [fPresetDrawer setContentSize: drawerSize];
[fPresetDrawer open];
}
-
+
/* Initially set the dvd angle widgets to hidden (dvdnav only) */
[fSrcAngleLabel setHidden:YES];
[fSrcAnglePopUp setHidden:YES];
@@ -689,6 +687,11 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[[fVideoController view] setAutoresizingMask:( NSViewWidthSizable | NSViewHeightSizable )];
[fWindow recalculateKeyViewLoop];
+
+ // Presets initialization
+ [self checkBuiltInsForUpdates];
+ [self buildPresetsMenu];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(buildPresetsMenu) name:HBPresetsChangedNotification object:nil];
}
- (void) enableUI: (BOOL) b
@@ -2082,11 +2085,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[fWindow makeKeyAndOrderFront:nil];
}
-- (BOOL) windowShouldClose: (id) sender
-{
- return YES;
-}
-
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
if( !flag ) {
@@ -5346,19 +5344,73 @@ the user is using "Custom" settings by determining the sender*/
}
#pragma mark -
-#pragma mark Manage Default Preset
+#pragma mark Preset Menu
- (IBAction)selectDefaultPreset:(id)sender
{
- [fPresetsView selectDefaultPreset];
+ [fPresetsView selectPreset:presetManager.defaultPreset];
}
-#pragma mark -
-#pragma mark Manage Built In Presets
+- (IBAction)insertFolder:(id)sender
+{
+ [fPresetsView insertFolder:sender];
+}
+
+- (IBAction)selectPresetFromMenu:(id)sender
+{
+ __block HBPreset *preset = nil;
+ __block NSInteger i = -1;
+
+ NSInteger tag = [sender tag];
+
+ [presetManager.root enumerateObjectsUsingBlock:^(id obj, NSIndexPath *idx, BOOL *stop)
+ {
+ if (i == tag)
+ {
+ preset = obj;
+ *stop = YES;
+ }
+ i++;
+ }];
+
+ [fPresetsView selectPreset:preset];
+}
-- (IBAction)deleteFactoryPresets:(id)sender
+/**
+ * Adds the presets list to the menu.
+ */
+- (void)buildPresetsMenu
{
- [presetManager deleteBuiltInPresets];
+ NSArray *menuItems = [presetsMenu.itemArray copy];
+
+ for (NSMenuItem *item in menuItems)
+ {
+ if (item.tag != -1)
+ {
+ [presetsMenu removeItem:item];
+ }
+ }
+ [menuItems release];
+
+ __block NSUInteger i = 0;
+ [presetManager.root enumerateObjectsUsingBlock:^(id obj, NSIndexPath *idx, BOOL *stop)
+ {
+ if (idx.length)
+ {
+ NSMenuItem *item = [[NSMenuItem alloc] init];
+ item.title = [obj name];
+ item.tag = i++;
+
+ if ([obj isLeaf])
+ {
+ item.action = @selector(selectPresetFromMenu:);
+ }
+ item.indentationLevel = idx.length - 1;
+
+ [presetsMenu addItem:item];
+ [item release];
+ }
+ }];
}
/* We use this method to recreate new, updated factory presets */
diff --git a/macosx/English.lproj/MainMenu.xib b/macosx/English.lproj/MainMenu.xib
index c0391d779..b078d832f 100644
--- a/macosx/English.lproj/MainMenu.xib
+++ b/macosx/English.lproj/MainMenu.xib
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F12" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1060" defaultVersion="1090" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
@@ -12,7 +12,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
- <window title="HandBrake" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="21" userLabel="MainWindow">
+ <window title="HandBrake" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="21" userLabel="MainWindow">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" unifiedTitleAndToolbar="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="41" y="572" width="966" height="558"/>
@@ -224,7 +224,7 @@
<font key="titleFont" metaFont="system"/>
</box>
<textField verticalHuggingPriority="750" id="1539">
- <rect key="frame" x="70" y="530" width="341" height="14.00000018353732"/>
+ <rect key="frame" x="70" y="530" width="330" height="14.000000183415764"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES" heightSizable="YES"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingMiddle" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" id="4906">
<font key="font" metaFont="smallSystem"/>
@@ -333,14 +333,14 @@
</textFieldCell>
</textField>
<box verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" id="3205">
- <rect key="frame" x="417" y="533" width="529" height="5"/>
+ <rect key="frame" x="406" y="533" width="540" height="5"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<font key="titleFont" metaFont="system"/>
</box>
<progressIndicator hidden="YES" verticalHuggingPriority="750" maxValue="100" bezeled="NO" controlSize="small" style="bar" id="3203">
- <rect key="frame" x="417" y="532.00000018353728" width="530" height="12"/>
+ <rect key="frame" x="406" y="532.00000017881393" width="541" height="12"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
</progressIndicator>
<button toolTip="This rearranges the header of the MP4 file to optimize it for streaming across the web." id="4579">
@@ -448,6 +448,12 @@
<action selector="showPreferencesWindow:" target="240" id="2517"/>
</connections>
</menuItem>
+ <menuItem isSeparatorItem="YES" id="bDt-OE-wyf">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Services" id="XcG-Aw-Gdb">
+ <menu key="submenu" title="Services" systemMenu="services" id="0te-ai-fgD"/>
+ </menuItem>
<menuItem isSeparatorItem="YES" id="1900">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
@@ -507,11 +513,14 @@
<action selector="addToQueue:" target="240" id="2447"/>
</connections>
</menuItem>
- <menuItem title="Add All Titles To Queue…" keyEquivalent="b" id="5897">
+ <menuItem title="Add All Titles To Queue…" keyEquivalent="B" id="5897">
<connections>
<action selector="addAllTitlesToQueue:" target="240" id="5899"/>
</connections>
</menuItem>
+ <menuItem isSeparatorItem="YES" id="Kee-pg-bfk">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
<menuItem title="Start Encoding" keyEquivalent="s" id="2444">
<connections>
<action selector="Rip:" target="240" id="2448"/>
@@ -649,43 +658,46 @@
<menuItem title="Presets" id="1948">
<menu key="submenu" title="Presets" id="1949">
<items>
- <menuItem title="New Preset…" keyEquivalent="n" id="1955">
+ <menuItem title="New Preset…" tag="-1" keyEquivalent="n" id="1955">
<connections>
- <action selector="showAddPresetPanel:" target="240" id="1956"/>
+ <action selector="showAddPresetPanel:" target="-1" id="iWH-6U-rv2"/>
</connections>
</menuItem>
- <menuItem title="Select Default Preset" id="2421">
+ <menuItem title="New Folder" tag="-1" keyEquivalent="N" id="wvb-60-cWL">
+ <connections>
+ <action selector="insertFolder:" target="-1" id="HpS-UY-h3l"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" tag="-1" id="1954">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+ </menuItem>
+ <menuItem title="Select Default Preset" tag="-1" id="2421">
<connections>
<action selector="selectDefaultPreset:" target="240" id="2422"/>
</connections>
</menuItem>
- <menuItem isSeparatorItem="YES" id="1954">
+ <menuItem isSeparatorItem="YES" tag="-1" id="CQW-qW-5C5">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
- <menuItem title="Export…" id="5188">
+ <menuItem title="Export…" tag="-1" id="5188">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="browseExportPresetFile:" target="240" id="5191"/>
</connections>
</menuItem>
- <menuItem title="Import…" id="5192">
+ <menuItem title="Import…" tag="-1" id="5192">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="browseImportPresetFile:" target="240" id="5193"/>
</connections>
</menuItem>
- <menuItem isSeparatorItem="YES" id="5qo-64-GYU">
- <modifierMask key="keyEquivalentModifierMask" command="YES"/>
- </menuItem>
- <menuItem title="Update Built-in Presets" id="1950">
+ <menuItem title="Update Built-in Presets" tag="-1" id="1950">
<connections>
<action selector="addFactoryPresets:" target="240" id="1952"/>
</connections>
</menuItem>
- <menuItem title="Delete Built-in Presets" id="1951">
- <connections>
- <action selector="deleteFactoryPresets:" target="240" id="1953"/>
- </connections>
+ <menuItem isSeparatorItem="YES" tag="-1" id="wgI-bc-Ors">
+ <modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
</items>
</menu>
@@ -766,44 +778,6 @@
</menuItem>
</items>
</menu>
- <window title="Panel" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="434" userLabel="DonePanel" customClass="NSPanel">
- <windowStyleMask key="styleMask" titled="YES" closable="YES"/>
- <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
- <rect key="contentRect" x="57" y="765" width="300" height="233"/>
- <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
- <value key="minSize" type="size" width="213" height="107"/>
- <view key="contentView" id="435">
- <rect key="frame" x="0.0" y="0.0" width="300" height="233"/>
- <autoresizingMask key="autoresizingMask"/>
- <subviews>
- <imageView id="436">
- <rect key="frame" x="83" y="82" width="134" height="134"/>
- <autoresizingMask key="autoresizingMask"/>
- <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="HandBrake.icns" id="4928"/>
- </imageView>
- <button verticalHuggingPriority="750" id="437">
- <rect key="frame" x="202" y="12" width="84" height="32"/>
- <autoresizingMask key="autoresizingMask"/>
- <buttonCell key="cell" type="push" title="Ahuh !" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="4929">
- <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
- <font key="font" metaFont="system"/>
- <string key="keyEquivalent" base64-UTF8="YES">
-DQ
-</string>
- </buttonCell>
- </button>
- <textField verticalHuggingPriority="750" id="438">
- <rect key="frame" x="82" y="60" width="134" height="17"/>
- <autoresizingMask key="autoresizingMask"/>
- <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Rip done !" id="4930">
- <font key="font" metaFont="system"/>
- <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
- <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
- </textFieldCell>
- </textField>
- </subviews>
- </view>
- </window>
<drawer trailingOffset="15" id="1841" userLabel="PresetsDrawer">
<size key="contentSize" width="240" height="550"/>
<size key="minContentSize" width="100" height="50"/>
@@ -1149,12 +1123,10 @@ DQ
<outlet property="fSubtitlesView" destination="5195" id="Ngb-0O-f4g"/>
<outlet property="fVideoView" destination="1478" id="M6c-3U-STI"/>
<outlet property="fWindow" destination="21" id="350"/>
+ <outlet property="presetsMenu" destination="1949" id="bkm-2h-uFI"/>
</connections>
</customObject>
<customObject id="4963" customClass="SUUpdater"/>
<userDefaultsController representsSharedInstance="YES" id="5676"/>
</objects>
- <resources>
- <image name="HandBrake.icns" width="128" height="128"/>
- </resources>
</document>
diff --git a/macosx/English.lproj/Presets.xib b/macosx/English.lproj/Presets.xib
index f1c070576..a151ff2d3 100644
--- a/macosx/English.lproj/Presets.xib
+++ b/macosx/English.lproj/Presets.xib
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F12" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
</dependencies>
@@ -18,7 +18,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<scrollView autohidesScrollers="YES" horizontalLineScroll="16" horizontalPageScroll="10" verticalLineScroll="16" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="uad-bt-uKD">
- <rect key="frame" x="4" y="33" width="224" height="285"/>
+ <rect key="frame" x="3" y="33" width="224" height="285"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" id="Rcx-jI-nnq">
<rect key="frame" x="1" y="1" width="222" height="283"/>
@@ -71,7 +71,7 @@
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="RAh-Ad-miy">
- <rect key="frame" x="1" y="1" width="0.0" height="16"/>
+ <rect key="frame" x="-100" y="-100" width="222" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="xU9-j2-UAo">
@@ -80,7 +80,7 @@
</scroller>
</scrollView>
<popUpButton verticalHuggingPriority="750" id="Ybq-Zt-sta">
- <rect key="frame" x="59" y="3" width="35" height="23"/>
+ <rect key="frame" x="58" y="3" width="35" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<popUpButtonCell key="cell" type="smallSquare" bezelStyle="smallSquare" imagePosition="only" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" pullsDown="YES" id="2JY-O9-FR6">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@@ -109,7 +109,7 @@
</popUpButtonCell>
</popUpButton>
<button verticalHuggingPriority="750" id="kfi-wq-mgV">
- <rect key="frame" x="4" y="3" width="24" height="23"/>
+ <rect key="frame" x="3" y="3" width="24" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" inset="3" id="OJ3-1k-3DY">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@@ -121,7 +121,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" id="b3V-8w-euU">
- <rect key="frame" x="27" y="3" width="24" height="23"/>
+ <rect key="frame" x="26" y="3" width="24" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="only" alignment="left" borderStyle="border" inset="3" id="Kb1-6u-550">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@@ -142,7 +142,7 @@
<string>isDefault</string>
</declaredKeys>
<connections>
- <binding destination="-2" name="contentArray" keyPath="presets.contents" id="9w3-Oi-cf0"/>
+ <binding destination="-2" name="contentArray" keyPath="presets.root.children" id="A8P-Hb-YE9"/>
</connections>
</treeController>
</objects>
diff --git a/macosx/HBPreset.h b/macosx/HBPreset.h
index 1c2fe22d3..73f4321c4 100644
--- a/macosx/HBPreset.h
+++ b/macosx/HBPreset.h
@@ -1,19 +1,19 @@
-//
-// HBBaseNode.h
-// PresetsView
-//
-// Created by Damiano Galassi on 14/07/14.
-// Copyright (c) 2014 Damiano Galassi. All rights reserved.
-//
+/* HBPreset.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import <Cocoa/Cocoa.h>
+#import "HBTreeNode.h"
/**
* HBPreset
- * Stores a preset dictionary
- * and implements the requited methods to work with a NSTreeController.
+ * Stores a preset dictionary.
+ *
+ * An instance of HBPreset can be an actual preset or a folder.
*/
-@interface HBPreset : NSObject <NSCopying>
+@interface HBPreset : HBTreeNode <NSCopying>
- (instancetype)initWithName:(NSString *)title content:(NSDictionary *)content builtIn:(BOOL)builtIn;
- (instancetype)initWithFolderName:(NSString *)title builtIn:(BOOL)builtIn;
@@ -25,15 +25,4 @@
@property (nonatomic, readwrite) BOOL isDefault;
@property (nonatomic, readonly) BOOL isBuiltIn;
-// NSTreeController required properties
-@property (nonatomic, retain) NSMutableArray *children;
-@property (nonatomic) BOOL isLeaf;
-
-/**
- * Executes a given block using each object in the tree, starting with the root object and continuing through the tree to the last object.
- *
- * @param block The block to apply to elements in the tree.
- */
-- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSIndexPath *idx, BOOL *stop))block;
-
@end
diff --git a/macosx/HBPreset.m b/macosx/HBPreset.m
index 05cd45552..7cf979152 100644
--- a/macosx/HBPreset.m
+++ b/macosx/HBPreset.m
@@ -1,10 +1,8 @@
-//
-// HBBaseNode.m
-// PresetsView
-//
-// Created by Damiano Galassi on 14/07/14.
-// Copyright (c) 2014 Damiano Galassi. All rights reserved.
-//
+/* HBPreset.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import "HBPreset.h"
@@ -30,7 +28,7 @@
{
_name = [title copy];
_isBuiltIn = builtIn;
- _isLeaf = NO;
+ self.isLeaf = NO;
}
return self;
}
@@ -40,10 +38,9 @@
self = [super init];
if (self)
{
- _children = [[NSMutableArray alloc] init];
_name = @"New Preset";
- _isLeaf = YES;
_presetDescription = @"";
+ self.isLeaf = YES;
}
return self;
}
@@ -53,20 +50,19 @@
[_name release];
[_content release];
[_presetDescription release];
- [_children release];
[super dealloc];
}
- (id)copyWithZone:(NSZone *)zone
{
- HBPreset *node = [[HBPreset alloc] init];
+ HBPreset *node = [[self class] allocWithZone:zone];
node->_name = [self.name copy];
node->_content = [self.content copy];
node->_presetDescription = [self.presetDescription copy];
for (HBPreset *children in self.children)
{
- [node->_children addObject:[[children copy] autorelease]];
+ [node.children addObject:[[children copy] autorelease]];
}
return node;
@@ -77,6 +73,14 @@
return self.name.hash + self.isBuiltIn + self.isLeaf;
}
+- (void)setName:(NSString *)name
+{
+ [_name autorelease];
+ _name = [name copy];
+
+ [self.delegate nodeDidChange];
+}
+
#pragma mark - KVC
- (BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError
@@ -97,45 +101,4 @@
return YES;
}
-#pragma mark - Enumeration
-
-- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSIndexPath *idx, BOOL *stop))block
-{
- BOOL stop = NO;
- NSMutableArray *queue = [[NSMutableArray alloc] init];
- NSMutableArray *indexesQueue = [[NSMutableArray alloc] init];
-
- [queue addObject:self];
- [indexesQueue addObject:[[[NSIndexPath alloc] init] autorelease]];
-
- HBPreset *node = nil;
- while ((node = [queue lastObject]) != nil)
- {
- // Get the index path of the current object
- NSIndexPath *indexPath = [indexesQueue lastObject];
-
- // Call the block
- block(node, indexPath, &stop);
-
- if (stop)
- {
- break;
- }
-
- [indexesQueue removeLastObject];
-
- for (int i = 0; i < node.children.count; i++)
- {
- [indexesQueue addObject:[indexPath indexPathByAddingIndex:i]];
- }
-
- [queue removeLastObject];
- [queue addObjectsFromArray:node.children];
-
- }
-
- [queue release];
- [indexesQueue release];
-}
-
@end
diff --git a/macosx/HBPresetsManager.h b/macosx/HBPresetsManager.h
index d7dc1efbf..74427f550 100644
--- a/macosx/HBPresetsManager.h
+++ b/macosx/HBPresetsManager.h
@@ -1,4 +1,4 @@
-/* HBPresets.h $
+/* HBPresetsManager.h $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.fr/>.
@@ -9,15 +9,20 @@
@class HBPreset;
/**
+ * Posted when a preset is changed/added/deleted.
+ */
+extern NSString *HBPresetsChangedNotification;
+
+/**
* HBPresetManager
* Manages the load/save of presets to an in memory tree.
*/
@interface HBPresetsManager : NSObject
/**
- * The root array of presets.
+ * The root of the presets tree.
*/
-@property (nonatomic, readonly, retain) NSMutableArray *contents;
+@property (nonatomic, readonly) HBPreset *root;
/**
* defaultPreset and its index path in the tree
@@ -68,7 +73,9 @@
*/
- (NSIndexPath *)indexPathOfPreset:(HBPreset *)preset;
+/**
+ * Adds back the built in presets.
+ */
- (void)generateBuiltInPresets;
-- (void)deleteBuiltInPresets;
@end
diff --git a/macosx/HBPresetsManager.m b/macosx/HBPresetsManager.m
index 88a74cdf2..4cf1b3a76 100644
--- a/macosx/HBPresetsManager.m
+++ b/macosx/HBPresetsManager.m
@@ -9,11 +9,11 @@
#import "HBUtilities.h"
-@interface HBPresetsManager ()
+NSString *HBPresetsChangedNotification = @"HBPresetsChangedNotification";
-@property (nonatomic, readonly, copy) NSURL *fileURL;
+@interface HBPresetsManager () <HBTreeNodeDelegate>
-@property (nonatomic, readonly, retain) HBPreset *root;
+@property (nonatomic, readonly, copy) NSURL *fileURL;
/* Dictionaries for individual presets ("Devices" folder) */
- (NSDictionary *)createUniversalPreset;
@@ -42,6 +42,7 @@
{
// Init the root of the tree, it won't never be shown in the UI
_root = [[HBPreset alloc] initWithFolderName:@"Root" builtIn:YES];
+ _root.delegate = self;
}
return self;
}
@@ -67,11 +68,6 @@
[super dealloc];
}
-- (NSMutableArray *)contents
-{
- return self.root.children;
-}
-
- (NSIndexPath *)indexPathOfPreset:(HBPreset *)preset
{
__block NSIndexPath *retValue = nil;
@@ -89,6 +85,13 @@
return [retValue autorelease];
}
+#pragma mark - HBTreeNode delegate
+
+- (void)nodeDidChange
+{
+ [[NSNotificationCenter defaultCenter] postNotificationName:HBPresetsChangedNotification object:nil];
+}
+
#pragma mark - Load/Save
- (BOOL)loadPresetsFromURL:(NSURL *)url
@@ -121,7 +124,7 @@
{
NSMutableArray *presetsArray = [[[NSMutableArray alloc] init] autorelease];
- for (HBPreset *node in self.contents)
+ for (HBPreset *node in self.root.children)
{
[presetsArray addObject:[self convertToDict:node]];
}
@@ -167,6 +170,11 @@
}
}
+ if (!node.isBuiltIn)
+ {
+ node.delegate = self;
+ }
+
return node;
}
@@ -226,7 +234,8 @@
HBPreset *presetNode = [[HBPreset alloc] initWithName:preset[@"PresetName"]
content:preset
builtIn:NO];
- [self insertObject:presetNode inContentsAtIndex:[self countOfContents]];
+
+ [self.root insertObject:presetNode inChildrenAtIndex:[self.root countOfChildren]];
[presetNode release];
[self savePresets];
@@ -234,9 +243,7 @@
- (void)deletePresetAtIndexPath:(NSIndexPath *)idx
{
- [self willChangeValueForKey:@"contents"];
-
- NSMutableArray *parentArray = self.contents;
+ HBPreset *parentNode = self.root;
// Find the preset parent array
// and delete it.
@@ -246,29 +253,27 @@
{
currIdx = [idx indexAtPosition:i];
- if (parentArray.count > currIdx)
+ if (parentNode.children.count > currIdx)
{
- parentArray = [(HBPreset *)[parentArray objectAtIndex:currIdx] children];
+ parentNode = [parentNode.children objectAtIndex:currIdx];
}
}
currIdx = [idx indexAtPosition:i];
- if (parentArray.count > currIdx)
+ if (parentNode.children.count > currIdx)
{
- if ([[parentArray objectAtIndex:currIdx] isDefault])
+ if ([[parentNode.children objectAtIndex:currIdx] isDefault])
{
- [parentArray removeObjectAtIndex:currIdx];
+ [parentNode removeObjectFromChildrenAtIndex:currIdx];
// Try to select a new default preset
[self selectNewDefault];
}
else
{
- [parentArray removeObjectAtIndex:currIdx];
+ [parentNode removeObjectFromChildrenAtIndex:currIdx];
}
}
-
- [self didChangeValueForKey:@"contents"];
}
/**
@@ -323,29 +328,6 @@
}
}
-#pragma mark -
-#pragma mark KVC
-
-- (NSUInteger)countOfContents
-{
- return [self.contents count];
-}
-
-- (HBPreset *)objectInContentsAtIndex:(NSUInteger)index
-{
- return [self.contents objectAtIndex:index];
-}
-
-- (void)insertObject:(HBPreset *)presetObject inContentsAtIndex:(NSUInteger)index;
-{
- [self.contents insertObject:presetObject atIndex:index];
-}
-
-- (void)removeObjectFromContentsAtIndex:(NSUInteger)index
-{
- [self.contents removeObjectAtIndex: index];
-}
-
#pragma mark - Built In Generation
- (void)loadPresetsForType:(NSString *)type fromSel:(SEL[])selArray length:(int)len
@@ -363,7 +345,7 @@
[presetNode release];
}
- [self.contents insertObject:folderNode atIndex:0];
+ [self.root insertObject:folderNode inChildrenAtIndex:0];
[folderNode release];
}
@@ -392,17 +374,8 @@
SEL regularPresets[] = { @selector(createNormalPreset),
@selector(createHighProfilePreset)};
- [self willChangeValueForKey:@"contents"];
- NSMutableIndexSet *indexes = [[NSMutableIndexSet alloc] init];
- [self.contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
- if ([obj isBuiltIn])
- {
- [indexes addIndex:idx];
- }
- }];
- [self.contents removeObjectsAtIndexes:indexes];
- [indexes release];
-
+ [self deleteBuiltInPresets];
+
[self loadPresetsForType:@"Regular" fromSel:regularPresets length:2];
[self loadPresetsForType:@"Devices" fromSel:devicesPresets length:10];
@@ -411,25 +384,24 @@
[self selectNewDefault];
}
- [self didChangeValueForKey:@"contents"];
[HBUtilities writeToActivityLog: "built in presets updated to build number: %d", [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]];
}
- (void)deleteBuiltInPresets
{
- [self willChangeValueForKey:@"contents"];
+ [self willChangeValueForKey:@"root"];
NSMutableArray *nodeToRemove = [[NSMutableArray alloc] init];
- for (HBPreset *node in self.contents)
+ for (HBPreset *node in self.root.children)
{
if (node.isBuiltIn)
{
[nodeToRemove addObject:node];
}
}
- [self.contents removeObjectsInArray:nodeToRemove];
+ [self.root.children removeObjectsInArray:nodeToRemove];
[nodeToRemove release];
- [self didChangeValueForKey:@"contents"];
+ [self didChangeValueForKey:@"root"];
}
#pragma mark -
diff --git a/macosx/HBPresetsViewController.h b/macosx/HBPresetsViewController.h
index b0e78034c..6b3de5f08 100644
--- a/macosx/HBPresetsViewController.h
+++ b/macosx/HBPresetsViewController.h
@@ -1,10 +1,8 @@
-//
-// HBPresetsViewController.h
-// PresetsView
-//
-// Created by Damiano Galassi on 14/07/14.
-// Copyright (c) 2014 Damiano Galassi. All rights reserved.
-//
+/* HBPresetsViewController.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import <Cocoa/Cocoa.h>
#import "HBViewValidation.h"
@@ -26,7 +24,9 @@
@property (nonatomic, readwrite, assign) id<HBPresetsViewControllerDelegate> delegate;
- (void)deselect;
-- (void)selectDefaultPreset;
+- (void)selectPreset:(HBPreset *)preset;
+
+- (IBAction)insertFolder:(id)sender;
@property (nonatomic, readonly) HBPreset *selectedPreset;
@property (nonatomic, readonly) NSUInteger indexOfSelectedItem;
diff --git a/macosx/HBPresetsViewController.m b/macosx/HBPresetsViewController.m
index 768dd1aa7..e49586212 100644
--- a/macosx/HBPresetsViewController.m
+++ b/macosx/HBPresetsViewController.m
@@ -1,10 +1,8 @@
-//
-// HBPresetsViewController.m
-// PresetsView
-//
-// Created by Damiano Galassi on 14/07/14.
-// Copyright (c) 2014 Damiano Galassi. All rights reserved.
-//
+/* HBPresetsViewController.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import "HBPresetsViewController.h"
#import "HBPresetsManager.h"
@@ -114,6 +112,8 @@
{
if ([self.treeController canRemove])
{
+ // Save the current selection path and apply it again after the deletion
+ NSIndexPath *currentSelection = [self.treeController selectionIndexPath];
/* Alert user before deleting preset */
NSAlert *alert = [NSAlert alertWithMessageText:@"Warning!"
defaultButton:@"OK"
@@ -128,6 +128,7 @@
{
[self.presets deletePresetAtIndexPath:[self.treeController selectionIndexPath]];
}
+ [self.treeController setSelectionIndexPath:currentSelection];
}
}
@@ -136,7 +137,7 @@
NSIndexPath *selectionIndexPath = [self.treeController selectionIndexPath];
if (!selectionIndexPath)
{
- selectionIndexPath = [NSIndexPath indexPathWithIndex:self.presets.contents.count];
+ selectionIndexPath = [NSIndexPath indexPathWithIndex:self.presets.root.children.count];
}
HBPreset *selectedNode = [[self.treeController selectedObjects] firstObject];
@@ -162,9 +163,9 @@
[self.treeController setSelectionIndexPath:nil];
}
-- (void)selectDefaultPreset
+- (void)selectPreset:(HBPreset *)preset
{
- NSIndexPath *idx = [self.presets indexPathOfPreset:self.presets.defaultPreset];
+ NSIndexPath *idx = [self.presets indexPathOfPreset:preset];
if (idx)
{
@@ -338,6 +339,13 @@
for (idx = ([newNodes count] - 1); idx >= 0; idx--)
{
[self.treeController moveNode:newNodes[idx] toIndexPath:indexPath];
+
+ // Call manually this because the NSTreeController doesn't call
+ // the KVC accessors method for the root node.
+ if (indexPath.length == 1)
+ {
+ [self.presets performSelector:@selector(nodeDidChange)];
+ }
}
// keep the moved nodes selected
@@ -375,7 +383,7 @@
{
// drop at the top root level
if (index == -1) // drop area might be ambibuous (not at a particular location)
- indexPath = [NSIndexPath indexPathWithIndex:self.presets.contents.count]; // drop at the end of the top level
+ indexPath = [NSIndexPath indexPathWithIndex:self.presets.root.children.count]; // drop at the end of the top level
else
indexPath = [NSIndexPath indexPathWithIndex:index]; // drop at a particular place at the top level
}
diff --git a/macosx/HBTreeNode.h b/macosx/HBTreeNode.h
new file mode 100644
index 000000000..a7eb0ca7d
--- /dev/null
+++ b/macosx/HBTreeNode.h
@@ -0,0 +1,44 @@
+/* HBTreeNode.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import <Foundation/Foundation.h>
+
+/**
+ * Notify a delegate that something changed in the tree.
+ * KVO observing a tree looked complicated an expensive, so this is a lightweight
+ * way to track the changes we need to know.
+ */
+@protocol HBTreeNodeDelegate <NSObject>
+
+- (void)nodeDidChange;
+
+@end
+
+/**
+ * HBTreeNode
+ */
+@interface HBTreeNode : NSObject
+
+// NSTreeController required properties
+@property (nonatomic, readonly) NSMutableArray *children;
+@property (nonatomic) BOOL isLeaf;
+
+@property (nonatomic, assign) id<HBTreeNodeDelegate> delegate;
+
+/**
+ * Executes a given block using each object in the tree, starting with the root object and continuing through the tree to the last object.
+ *
+ * @param block The block to apply to elements in the tree.
+ */
+- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSIndexPath *idx, BOOL *stop))block;
+
+// KVC Accessor Methods
+- (NSUInteger)countOfChildren;
+- (id)objectInChildrenAtIndex:(NSUInteger)index;
+- (void)insertObject:(id)presetObject inChildrenAtIndex:(NSUInteger)index;
+- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index;
+
+@end
diff --git a/macosx/HBTreeNode.m b/macosx/HBTreeNode.m
new file mode 100644
index 000000000..28be2c1fd
--- /dev/null
+++ b/macosx/HBTreeNode.m
@@ -0,0 +1,95 @@
+/* HBTreeNode.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import "HBTreeNode.h"
+
+@implementation HBTreeNode
+
+- (instancetype)init
+{
+ self = [super init];
+ if (self) {
+ _children = [[NSMutableArray alloc] init];
+ _isLeaf = YES;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [_children release];
+ [super dealloc];
+}
+
+- (NSUInteger)countOfChildren
+{
+ return self.children.count;
+}
+
+- (id)objectInChildrenAtIndex:(NSUInteger)index
+{
+ return [self.children objectAtIndex:index];
+}
+
+- (void)insertObject:(id)presetObject inChildrenAtIndex:(NSUInteger)index
+{
+ [self.children insertObject:presetObject atIndex:index];
+ [presetObject setDelegate:self.delegate];
+
+ [self.delegate nodeDidChange];
+}
+
+- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index
+{
+ [self.children removeObjectAtIndex:index];
+ [self.delegate nodeDidChange];
+}
+
+#pragma mark - Enumeration
+
+- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSIndexPath *idx, BOOL *stop))block
+{
+ BOOL stop = NO;
+ NSMutableArray *queue = [[NSMutableArray alloc] init];
+ NSMutableArray *indexesQueue = [[NSMutableArray alloc] init];
+
+ [queue addObject:self];
+ [indexesQueue addObject:[[[NSIndexPath alloc] init] autorelease]];
+
+ HBTreeNode *node = nil;
+ while ((node = [queue lastObject]) != nil)
+ {
+ // Get the index path of the current object
+ NSIndexPath *indexPath = [indexesQueue lastObject];
+
+ // Call the block
+ block(node, indexPath, &stop);
+
+ if (stop)
+ {
+ break;
+ }
+
+ [indexesQueue removeLastObject];
+
+ for (NSInteger i = node.children.count - 1; i >= 0; i--)
+ {
+ [indexesQueue addObject:[indexPath indexPathByAddingIndex:i]];
+ }
+
+ [queue removeLastObject];
+
+ for (id childNode in [node.children reverseObjectEnumerator])
+ {
+ [queue addObject:childNode];
+ }
+ }
+
+ [queue release];
+ [indexesQueue release];
+}
+
+@end
diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj
index 01ffb42e3..c2e14bebb 100644
--- a/macosx/HandBrake.xcodeproj/project.pbxproj
+++ b/macosx/HandBrake.xcodeproj/project.pbxproj
@@ -131,6 +131,7 @@
A9CF25F41990D64E0023F727 /* HBPreset.m in Sources */ = {isa = PBXBuildFile; fileRef = A9CF25F31990D64E0023F727 /* HBPreset.m */; };
A9CF25F71990D6820023F727 /* HBPresetsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9CF25F61990D6820023F727 /* HBPresetsViewController.m */; };
A9D1E41718262364002F6424 /* HBPreviewGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D1E41618262364002F6424 /* HBPreviewGenerator.m */; };
+ A9D488A51996270300E9B1BA /* HBTreeNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D488A41996270300E9B1BA /* HBTreeNode.m */; };
A9DC6C52196F04F6002AE6B4 /* HBSubtitlesController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9DC6C50196F04F6002AE6B4 /* HBSubtitlesController.m */; };
A9DC6C56196F0517002AE6B4 /* Subtitles.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9DC6C54196F0517002AE6B4 /* Subtitles.xib */; };
A9E1467B16BC2ABD00C307BC /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9E1467A16BC2ABD00C307BC /* QuartzCore.framework */; };
@@ -352,6 +353,8 @@
A9CF25F51990D6820023F727 /* HBPresetsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPresetsViewController.h; sourceTree = "<group>"; };
A9CF25F61990D6820023F727 /* HBPresetsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPresetsViewController.m; sourceTree = "<group>"; };
A9D1E41618262364002F6424 /* HBPreviewGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPreviewGenerator.m; sourceTree = "<group>"; };
+ A9D488A31996270300E9B1BA /* HBTreeNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBTreeNode.h; sourceTree = "<group>"; };
+ A9D488A41996270300E9B1BA /* HBTreeNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBTreeNode.m; sourceTree = "<group>"; };
A9DC6C4F196F04F6002AE6B4 /* HBSubtitlesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBSubtitlesController.h; sourceTree = SOURCE_ROOT; };
A9DC6C50196F04F6002AE6B4 /* HBSubtitlesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBSubtitlesController.m; sourceTree = SOURCE_ROOT; };
A9DC6C55196F0517002AE6B4 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Subtitles.xib; sourceTree = "<group>"; };
@@ -759,6 +762,8 @@
273F20A214ADBE670021BE6D /* HBPresetsManager.m */,
A9CF25F21990D64E0023F727 /* HBPreset.h */,
A9CF25F31990D64E0023F727 /* HBPreset.m */,
+ A9D488A31996270300E9B1BA /* HBTreeNode.h */,
+ A9D488A41996270300E9B1BA /* HBTreeNode.m */,
A932E271198834130047D13E /* HBAudioSettings.h */,
A932E272198834130047D13E /* HBAudioSettings.m */,
A9F4728B1976BAA70009EC65 /* HBSubtitlesSettings.h */,
@@ -1040,6 +1045,7 @@
A91726E7197291BC00D1AFEF /* HBChapterTitlesController.m in Sources */,
A932E26F198833920047D13E /* HBAudioDefaultsController.m in Sources */,
46AB433515F98A2B009C0961 /* DockTextField.m in Sources */,
+ A9D488A51996270300E9B1BA /* HBTreeNode.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};