diff --git a/src/GeneralPrefsVC.mm b/src/GeneralPrefsVC.mm index 46085286bb4637211a491206ad0273d479a72e4f..2cf7cdd0e326de6618f200698582652cbf1dc00a 100644 --- a/src/GeneralPrefsVC.mm +++ b/src/GeneralPrefsVC.mm @@ -36,12 +36,14 @@ @interface GeneralPrefsVC () @property (assign) IBOutlet NSTextField *historyChangedLabel; @property (assign) IBOutlet NSView *advancedGeneralSettings; +@property (unsafe_unretained) IBOutlet NSButton *startUpButton; @end @implementation GeneralPrefsVC @synthesize historyChangedLabel; @synthesize advancedGeneralSettings; +@synthesize startUpButton; - (void)loadView { @@ -49,6 +51,8 @@ [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:Preferences::HistoryLimit options:NSKeyValueObservingOptionNew context:NULL]; [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:Preferences::ShowAdvanced options:NSKeyValueObservingOptionNew context:NULL]; + [startUpButton setState:[self isLaunchAtStartup]]; + [advancedGeneralSettings setHidden:![[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ShowAdvanced]]; } @@ -68,4 +72,70 @@ } } +#pragma mark - Startup API + +// MIT license by Brian Dunagan +- (BOOL)isLaunchAtStartup { + // See if the app is currently in LoginItems. + LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; + // Store away that boolean. + BOOL isInList = itemRef != nil; + // Release the reference if it exists. + if (itemRef != nil) CFRelease(itemRef); + + return isInList; +} + +- (IBAction)toggleLaunchAtStartup:(id)sender { + // Toggle the state. + BOOL shouldBeToggled = ![self isLaunchAtStartup]; + // Get the LoginItems list. + LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + if (loginItemsRef == nil) return; + if (shouldBeToggled) { + // Add the app to the LoginItems list. + CFURLRef appUrl = (CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL); + if (itemRef) CFRelease(itemRef); + } + else { + // Remove the app from the LoginItems list. + LSSharedFileListItemRef itemRef = [self itemRefInLoginItems]; + LSSharedFileListItemRemove(loginItemsRef,itemRef); + if (itemRef != nil) CFRelease(itemRef); + } + CFRelease(loginItemsRef); +} + +- (LSSharedFileListItemRef)itemRefInLoginItems { + LSSharedFileListItemRef itemRef = nil; + NSURL *itemUrl = nil; + + // Get the app's URL. + NSURL *appUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; + // Get the LoginItems list. + LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); + if (loginItemsRef == nil) return nil; + // Iterate over the LoginItems. + NSArray *loginItems = (NSArray *)LSSharedFileListCopySnapshot(loginItemsRef, nil); + for (int currentIndex = 0; currentIndex < [loginItems count]; currentIndex++) { + // Get the current LoginItem and resolve its URL. + LSSharedFileListItemRef currentItemRef = (LSSharedFileListItemRef)[loginItems objectAtIndex:currentIndex]; + if (LSSharedFileListItemResolve(currentItemRef, 0, (CFURLRef *) &itemUrl, NULL) == noErr) { + // Compare the URLs for the current LoginItem and the app. + if ([itemUrl isEqual:appUrl]) { + // Save the LoginItem reference. + itemRef = currentItemRef; + } + } + } + // Retain the LoginItem reference. + if (itemRef != nil) CFRetain(itemRef); + // Release the LoginItems lists. + [loginItems release]; + CFRelease(loginItemsRef); + + return itemRef; +} + @end diff --git a/ui/GeneralPrefs.xib b/ui/GeneralPrefs.xib index 362972e214f17211e791d6af98d3b46e395cb008..9bdead4fb3ee6cb6318cf4c7ed5ba141c456ade2 100644 --- a/ui/GeneralPrefs.xib +++ b/ui/GeneralPrefs.xib @@ -8,6 +8,7 @@ <connections> <outlet property="advancedGeneralSettings" destination="VH6-yw-pgr" id="lSD-RY-Puf"/> <outlet property="historyChangedLabel" destination="Gyi-ID-Z3v" id="aoO-Fh-UCQ"/> + <outlet property="startUpButton" destination="1Nr-L4-fcd" id="veu-Hi-c7L"/> <outlet property="view" destination="c22-O7-iKe" id="kqH-6G-Ohq"/> </connections> </customObject> @@ -54,7 +55,7 @@ </connections> </button> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fC0-ce-Yiz"> - <rect key="frame" x="38" y="452" width="54" height="17"/> + <rect key="frame" x="38" y="423" width="54" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="History" id="DSD-yl-noX"> <font key="font" metaFont="systemBold"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> @@ -62,21 +63,21 @@ </textFieldCell> </textField> <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DgD-2y-4g5"> - <rect key="frame" x="56" y="425" width="195" height="18"/> + <rect key="frame" x="56" y="396" width="195" height="18"/> <buttonCell key="cell" type="check" title="Keep my history for at least" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="3Pb-Ec-zl5"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="system"/> </buttonCell> </button> <stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QmA-ZI-ZL5"> - <rect key="frame" x="302" y="419" width="19" height="27"/> + <rect key="frame" x="302" y="390" width="19" height="27"/> <stepperCell key="cell" continuous="YES" alignment="left" maxValue="100" doubleValue="30" id="30B-YQ-Opa"/> <connections> <binding destination="Sz0-vm-i3t" name="value" keyPath="values.history_limit" id="c2j-mK-kYa"/> </connections> </stepper> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tHZ-7Q-5iP"> - <rect key="frame" x="257" y="422" width="40" height="22"/> + <rect key="frame" x="257" y="393" width="40" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" title="30" drawsBackground="YES" id="JvS-c4-OeT"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -87,7 +88,7 @@ </connections> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nah-Jm-ZYB"> - <rect key="frame" x="324" y="426" width="33" height="17"/> + <rect key="frame" x="324" y="397" width="33" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="days" id="e5K-l0-Nfw"> <font key="font" metaFont="system"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> @@ -95,7 +96,7 @@ </textFieldCell> </textField> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="U84-le-Iy4"> - <rect key="frame" x="58" y="388" width="122" height="19"/> + <rect key="frame" x="58" y="359" width="122" height="19"/> <buttonCell key="cell" type="roundRect" title="Clear History" bezelStyle="roundedRect" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cd5-9L-Bbb"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="cellTitle"/> @@ -105,7 +106,7 @@ </connections> </button> <textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gyi-ID-Z3v"> - <rect key="frame" x="361" y="422" width="167" height="17"/> + <rect key="frame" x="361" y="393" width="167" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="(Applied on application restart)" id="OTl-vx-S43"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> @@ -120,18 +121,28 @@ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> </textFieldCell> </textField> + <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Nr-L4-fcd"> + <rect key="frame" x="204" y="455" width="136" height="18"/> + <buttonCell key="cell" type="check" title="Launch on Startup" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="O2C-xR-mHF"> + <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <connections> + <action selector="toggleLaunchAtStartup:" target="-2" id="Rky-YK-2yk"/> + </connections> + </button> <customView hidden="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VH6-yw-pgr"> - <rect key="frame" x="20" y="20" width="859" height="361"/> + <rect key="frame" x="20" y="171" width="859" height="181"/> <subviews> <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kAy-G5-0gJ"> - <rect key="frame" x="65" y="296" width="104" height="18"/> + <rect key="frame" x="65" y="116" width="104" height="18"/> <buttonCell key="cell" type="check" title="Using STUN" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="J3i-Kd-ufy"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="system"/> </buttonCell> </button> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sMR-LQ-v1D"> - <rect key="frame" x="166" y="294" width="216" height="22"/> + <rect key="frame" x="166" y="114" width="216" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="Server url..." drawsBackground="YES" id="MzH-CP-Tf3"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -139,7 +150,7 @@ </textFieldCell> </textField> <matrix verticalHuggingPriority="750" fixedFrame="YES" allowsEmptySelection="NO" autorecalculatesCellSize="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vSL-q3-yQ7"> - <rect key="frame" x="67" y="241" width="320" height="38"/> + <rect key="frame" x="67" y="61" width="320" height="38"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <size key="cellSize" width="216" height="18"/> <size key="intercellSpacing" width="4" height="2"/> @@ -161,7 +172,7 @@ </cells> </matrix> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zjo-JQ-eys"> - <rect key="frame" x="87" y="200" width="187" height="22"/> + <rect key="frame" x="87" y="20" width="187" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="mWy-F0-AW6"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -169,7 +180,7 @@ </textFieldCell> </textField> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8Tf-sb-mk9"> - <rect key="frame" x="316" y="200" width="63" height="22"/> + <rect key="frame" x="316" y="20" width="63" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="u2t-ps-CAH"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -177,7 +188,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="asH-TC-Vjh"> - <rect key="frame" x="280" y="203" width="30" height="17"/> + <rect key="frame" x="280" y="23" width="30" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Port" id="mfD-5d-YAO"> <font key="font" metaFont="system"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> @@ -185,7 +196,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rcn-X4-Z0S"> - <rect key="frame" x="30" y="203" width="55" height="17"/> + <rect key="frame" x="30" y="23" width="55" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Address" id="mDR-e7-DwU"> <font key="font" metaFont="system"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> @@ -193,7 +204,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="v1V-gL-Qea"> - <rect key="frame" x="18" y="324" width="87" height="17"/> + <rect key="frame" x="18" y="144" width="87" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="STUN server" id="5BD-IL-feS"> <font key="font" metaFont="systemBold"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> @@ -201,7 +212,7 @@ </textFieldCell> </textField> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Tlg-3Y-SwP"> - <rect key="frame" x="564" y="294" width="216" height="22"/> + <rect key="frame" x="564" y="114" width="216" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="Server url..." drawsBackground="YES" id="5IL-CF-xNE"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -209,7 +220,7 @@ </textFieldCell> </textField> <matrix verticalHuggingPriority="750" fixedFrame="YES" allowsEmptySelection="NO" autorecalculatesCellSize="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Jxr-u3-BHN"> - <rect key="frame" x="465" y="241" width="320" height="38"/> + <rect key="frame" x="465" y="61" width="320" height="38"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <size key="cellSize" width="216" height="18"/> <size key="intercellSpacing" width="4" height="2"/> @@ -231,7 +242,7 @@ </cells> </matrix> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="orf-tH-Ryt"> - <rect key="frame" x="485" y="200" width="187" height="22"/> + <rect key="frame" x="485" y="20" width="187" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="DxB-Pf-IB5"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -239,7 +250,7 @@ </textFieldCell> </textField> <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="L7A-C3-OaS"> - <rect key="frame" x="714" y="200" width="63" height="22"/> + <rect key="frame" x="714" y="20" width="63" height="22"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="qBg-Z7-cPZ"> <font key="font" metaFont="system"/> <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/> @@ -247,7 +258,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cy7-Hu-7rs"> - <rect key="frame" x="678" y="203" width="30" height="17"/> + <rect key="frame" x="678" y="23" width="30" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Port" id="Kby-vh-BDl"> <font key="font" metaFont="system"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> @@ -255,7 +266,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qwZ-OU-p2U"> - <rect key="frame" x="428" y="203" width="55" height="17"/> + <rect key="frame" x="428" y="23" width="55" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Address" id="fsN-LH-LkL"> <font key="font" metaFont="system"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> @@ -263,7 +274,7 @@ </textFieldCell> </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IVO-Du-c46"> - <rect key="frame" x="416" y="324" width="88" height="17"/> + <rect key="frame" x="416" y="144" width="88" height="17"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="TURN server" id="RdV-YO-mtx"> <font key="font" metaFont="systemBold"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> @@ -271,7 +282,7 @@ </textFieldCell> </textField> <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="H4W-dK-kUO"> - <rect key="frame" x="463" y="296" width="104" height="18"/> + <rect key="frame" x="463" y="116" width="104" height="18"/> <buttonCell key="cell" type="check" title="Using TURN" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="jr8-R1-kiL"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="system"/>