Application-wide hotkeys + feed edit modal sheet
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1968E0AE14B8E8A90E194980 /* PyHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1968EF7567E06D2A5BB3481A /* PyHandler.m */; };
|
||||
544B011A2114B41200386E5C /* FeedEdit.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B01192114B41200386E5C /* FeedEdit.m */; };
|
||||
544B011D2114EE9100386E5C /* AppHook.m in Sources */ = {isa = PBXBuildFile; fileRef = 544B011C2114EE9100386E5C /* AppHook.m */; };
|
||||
544FBD4521064AEB008A260C /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 544FBD4421064AEB008A260C /* Python.framework */; };
|
||||
544FBD4721064B2F008A260C /* getFeed.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4621064B2F008A260C /* getFeed.py */; };
|
||||
544FBD4921064DF0008A260C /* feedparser521.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4821064DF0008A260C /* feedparser521.py */; };
|
||||
@@ -23,6 +25,10 @@
|
||||
/* Begin PBXFileReference section */
|
||||
1968E7919BAA36F042FCB717 /* PyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyHandler.h; sourceTree = "<group>"; };
|
||||
1968EF7567E06D2A5BB3481A /* PyHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PyHandler.m; sourceTree = "<group>"; };
|
||||
544B01182114B41200386E5C /* FeedEdit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FeedEdit.h; sourceTree = "<group>"; };
|
||||
544B01192114B41200386E5C /* FeedEdit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FeedEdit.m; sourceTree = "<group>"; };
|
||||
544B011B2114EE9100386E5C /* AppHook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppHook.h; sourceTree = "<group>"; };
|
||||
544B011C2114EE9100386E5C /* AppHook.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppHook.m; sourceTree = "<group>"; };
|
||||
544FBD4421064AEB008A260C /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; };
|
||||
544FBD4621064B2F008A260C /* getFeed.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = getFeed.py; sourceTree = "<group>"; usesTabs = 0; };
|
||||
544FBD4821064DF0008A260C /* feedparser521.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = feedparser521.py; sourceTree = "<group>"; usesTabs = 0; };
|
||||
@@ -92,12 +98,16 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
549369F421091E6D001AF895 /* python */,
|
||||
544B011B2114EE9100386E5C /* AppHook.h */,
|
||||
544B011C2114EE9100386E5C /* AppHook.m */,
|
||||
54ACC27F21061B3B0020715F /* AppDelegate.h */,
|
||||
54ACC28021061B3B0020715F /* AppDelegate.m */,
|
||||
54ACC29321061E270020715F /* NewsController.h */,
|
||||
54ACC29421061E270020715F /* NewsController.m */,
|
||||
54ACC29621061FBA0020715F /* Preferences.h */,
|
||||
54ACC29721061FBA0020715F /* Preferences.m */,
|
||||
544B01182114B41200386E5C /* FeedEdit.h */,
|
||||
544B01192114B41200386E5C /* FeedEdit.m */,
|
||||
54ACC28521061B3C0020715F /* Assets.xcassets */,
|
||||
54ACC28721061B3C0020715F /* Main.xib */,
|
||||
54ACC28A21061B3C0020715F /* Info.plist */,
|
||||
@@ -188,9 +198,11 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54F39C2E210BE1F700AEE730 /* DBv1.xcdatamodeld in Sources */,
|
||||
544B011D2114EE9100386E5C /* AppHook.m in Sources */,
|
||||
54ACC29521061E270020715F /* NewsController.m in Sources */,
|
||||
54ACC28C21061B3C0020715F /* main.m in Sources */,
|
||||
54ACC28121061B3B0020715F /* AppDelegate.m in Sources */,
|
||||
544B011A2114B41200386E5C /* FeedEdit.m in Sources */,
|
||||
54ACC29821061FBA0020715F /* Preferences.m in Sources */,
|
||||
1968E0AE14B8E8A90E194980 /* PyHandler.m in Sources */,
|
||||
);
|
||||
|
||||
27
baRSS/AppHook.h
Normal file
27
baRSS/AppHook.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppHook : NSApplication
|
||||
|
||||
@end
|
||||
57
baRSS/AppHook.m
Normal file
57
baRSS/AppHook.m
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#import "AppHook.h"
|
||||
|
||||
static NSEventModifierFlags fnKeyFlags = NSEventModifierFlagShift | NSEventModifierFlagControl | NSEventModifierFlagOption | NSEventModifierFlagCommand | NSEventModifierFlagFunction;
|
||||
|
||||
@implementation AppHook
|
||||
- (void) sendEvent:(NSEvent *)event {
|
||||
if ([event type] == NSEventTypeKeyDown) {
|
||||
NSEventModifierFlags flags = (event.modifierFlags & fnKeyFlags); // ignore caps lock, etc.
|
||||
unichar key = [event.characters characterAtIndex:0]; // charactersIgnoringModifiers
|
||||
if (flags == NSEventModifierFlagCommand) {
|
||||
switch (key) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
case 'z': if ([self sendAction:@selector(undo:) to:nil from:self]) return; break;
|
||||
#pragma clang diagnostic pop
|
||||
case 'x': if ([self sendAction:@selector(cut:) to:nil from:self]) return; break;
|
||||
case 'c': if ([self sendAction:@selector(copy:) to:nil from:self]) return; break;
|
||||
case 'v': if ([self sendAction:@selector(paste:) to:nil from:self]) return; break;
|
||||
case 'a': if ([self sendAction:@selector(selectAll:) to:nil from:self]) return; break;
|
||||
case 'q': if ([self sendAction:@selector(terminate:) to:nil from:self]) return; break;
|
||||
case 'w': if ([self sendAction:@selector(performClose:) to:nil from:self]) return; break;
|
||||
}
|
||||
} else if (flags == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) {
|
||||
if (key == 'z') {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
if ([self sendAction:@selector(redo:) to:nil from:self])
|
||||
return;
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
}
|
||||
[super sendEvent:event];
|
||||
}
|
||||
@end
|
||||
@@ -19,22 +19,6 @@
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<treeController mode="entity" entityName="FeedConfig" fetchPredicateFormat="parent == nil" automaticallyPreparesContent="YES" childrenKeyPath="children" leafKeyPath="type" id="1oZ-Uo-mIu" customClass="NewsController">
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="managedObjectContext" keyPath="self.persistentContainer.viewContext" id="Q1f-VN-9qq"/>
|
||||
<outlet property="outlineView" destination="hKk-G1-1po" id="Z4y-uD-Zse"/>
|
||||
</connections>
|
||||
</treeController>
|
||||
<customObject id="bgB-po-1IK" customClass="Preferences">
|
||||
<connections>
|
||||
<outlet property="feedsOutline" destination="hKk-G1-1po" id="jcw-Fq-DyK"/>
|
||||
<outlet property="newsController" destination="1oZ-Uo-mIu" id="hAk-g4-Oii"/>
|
||||
<outlet property="toolbar" destination="wLj-fD-HpE" id="bMA-dd-1H1"/>
|
||||
<outlet property="viewFeeds" destination="EwH-fT-yW8" id="pmQ-as-O2V"/>
|
||||
<outlet property="viewGeneral" destination="8H4-sI-Ub8" id="lWU-Il-4in"/>
|
||||
<outlet property="window" destination="ai3-RW-O8g" id="Ncu-vV-dTy"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<menu id="tDc-nD-HS2">
|
||||
<items>
|
||||
<menuItem title="Pause Updates" id="D7r-Vb-9eO">
|
||||
@@ -70,10 +54,16 @@
|
||||
</items>
|
||||
<point key="canvasLocation" x="277" y="419"/>
|
||||
</menu>
|
||||
<window title="baRSS Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" tabbingMode="disallowed" id="ai3-RW-O8g" userLabel="Preferences">
|
||||
<treeController mode="entity" entityName="FeedConfig" fetchPredicateFormat="parent == nil" automaticallyPreparesContent="YES" childrenKeyPath="children" leafKeyPath="type" id="1oZ-Uo-mIu" customClass="NewsController">
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="managedObjectContext" keyPath="self.persistentContainer.viewContext" id="Q1f-VN-9qq"/>
|
||||
<outlet property="outlineView" destination="hKk-G1-1po" id="Z4y-uD-Zse"/>
|
||||
<outlet property="preferencesWindow" destination="ai3-RW-O8g" id="cNF-TI-ups"/>
|
||||
</connections>
|
||||
</treeController>
|
||||
<window title="baRSS Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="prefWindow" animationBehavior="default" tabbingMode="disallowed" id="ai3-RW-O8g" userLabel="Preferences" customClass="Preferences">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="131" y="159" width="320" height="327"/>
|
||||
<rect key="contentRect" x="948" y="431" width="320" height="327"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<value key="minSize" type="size" width="320" height="327"/>
|
||||
<view key="contentView" id="ct3-G7-3SQ">
|
||||
@@ -84,12 +74,12 @@
|
||||
<allowedToolbarItems>
|
||||
<toolbarItem implicitItemIdentifier="AF4483E3-0457-47B7-AE52-AC11B1545455" explicitItemIdentifier="preferencesTabGeneral" label="General" paletteLabel="General" tag="-1" image="NSPreferencesGeneral" selectable="YES" id="0qP-ah-ojT">
|
||||
<connections>
|
||||
<action selector="clickGeneral:" target="bgB-po-1IK" id="G4I-Zs-FZR"/>
|
||||
<action selector="tabGeneralClicked:" target="ai3-RW-O8g" id="OiJ-PY-QCu"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="E8527558-3D5F-4B79-99E4-675C1557D10B" explicitItemIdentifier="preferencesTabFeeds" label="Feeds" paletteLabel="Feeds" tag="-1" image="NSUserAccounts" selectable="YES" id="Av5-VA-zps">
|
||||
<connections>
|
||||
<action selector="clickFeeds:" target="bgB-po-1IK" id="Daq-b8-lpE"/>
|
||||
<action selector="tabFeedsClicked:" target="ai3-RW-O8g" id="l5x-nd-qBx"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
</allowedToolbarItems>
|
||||
@@ -98,6 +88,12 @@
|
||||
<toolbarItem reference="Av5-VA-zps"/>
|
||||
</defaultToolbarItems>
|
||||
</toolbar>
|
||||
<connections>
|
||||
<outlet property="feedDetailSheet" destination="6yF-Ii-jhG" id="ozt-yn-eEM"/>
|
||||
<outlet property="newsController" destination="1oZ-Uo-mIu" id="1HA-Vz-PBK"/>
|
||||
<outlet property="viewFeeds" destination="EwH-fT-yW8" id="aBH-fR-foa"/>
|
||||
<outlet property="viewGeneral" destination="8H4-sI-Ub8" id="PS7-gG-GJs"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-20" y="521"/>
|
||||
</window>
|
||||
<customView id="8H4-sI-Ub8" userLabel="Preferences-General">
|
||||
@@ -430,6 +426,7 @@
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<action trigger="doubleAction" selector="presentModalFeedProperties:" target="1oZ-Uo-mIu" id="zNP-kQ-Xmh"/>
|
||||
<outlet property="dataSource" destination="1oZ-Uo-mIu" id="sch-o5-yEm"/>
|
||||
<outlet property="delegate" destination="1oZ-Uo-mIu" id="Nye-dQ-vdy"/>
|
||||
</connections>
|
||||
@@ -459,7 +456,7 @@
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="addFeed:" target="1oZ-Uo-mIu" id="wR9-Np-joC"/>
|
||||
<action selector="addFeed:" target="1oZ-Uo-mIu" id="jX0-xl-p0f"/>
|
||||
<binding destination="1oZ-Uo-mIu" name="enabled" keyPath="canInsert" id="1xq-Nj-Acq"/>
|
||||
</connections>
|
||||
</button>
|
||||
@@ -514,6 +511,131 @@ CA
|
||||
<point key="canvasLocation" x="350" y="903.5"/>
|
||||
</customView>
|
||||
<userDefaultsController representsSharedInstance="YES" id="K8S-BW-Na6"/>
|
||||
<window title="Feed Detail Sheet" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="formFeedDetail" animationBehavior="default" id="6yF-Ii-jhG" customClass="FeedEdit">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<rect key="contentRect" x="131" y="159" width="400" height="153"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<value key="minSize" type="size" width="400" height="153"/>
|
||||
<value key="maxSize" type="size" width="1200" height="153"/>
|
||||
<view key="contentView" id="bH3-c8-m3D">
|
||||
<rect key="frame" x="0.0" y="0.0" width="400" height="153"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="u2j-52-0kN">
|
||||
<rect key="frame" x="18" y="114" width="103" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="URL" id="FDr-0e-igw">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9nh-vY-v6W">
|
||||
<rect key="frame" x="127" y="112" width="253" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="https://example.org/feed.rss" drawsBackground="YES" usesSingleLineMode="YES" id="VSm-J7-qAA">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Znc-BK-dhw">
|
||||
<rect key="frame" x="18" y="85" width="103" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Name" id="Uda-8X-onH">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5uB-Zy-4u6">
|
||||
<rect key="frame" x="127" y="83" width="253" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="Example Title" drawsBackground="YES" usesSingleLineMode="YES" id="vzt-hb-cGT">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sMQ-B7-WTo">
|
||||
<rect key="frame" x="127" y="54" width="86" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="30" drawsBackground="YES" usesSingleLineMode="YES" id="bNw-iS-Gfz">
|
||||
<customFormatter key="formatter" id="NEE-2h-FN9" customClass="StrictUIntFormatter"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Az1-ZL-15b">
|
||||
<rect key="frame" x="232" y="13" width="82" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="V93-O8-bjm">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
Gw
|
||||
</string>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="didTapCancelButton:" target="6yF-Ii-jhG" id="uS5-n0-iZ3"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CRz-wU-u6m">
|
||||
<rect key="frame" x="314" y="13" width="72" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Done" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="fdr-rD-bgC">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
DQ
|
||||
</string>
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="didTapDoneButton:" target="6yF-Ii-jhG" id="vK2-Ou-z3b"/>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FYV-ch-Bjd" userLabel="TimeUnit">
|
||||
<rect key="frame" x="219" y="51" width="127" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Minutes" bezelStyle="rounded" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="7DG-HF-41v" id="54G-6B-9Vg">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" showsStateColumn="NO" autoenablesItems="NO" id="FA5-Wc-aKF">
|
||||
<items>
|
||||
<menuItem title="Seconds" id="ObP-NX-RUr">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Minutes" state="on" id="7DG-HF-41v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Hours" id="buP-XT-lMO">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Days" id="wJ7-Ui-a4q">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Weeks" id="Py4-7n-CXD">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hlP-VB-yeu">
|
||||
<rect key="frame" x="18" y="56" width="103" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Refresh" id="c0W-IR-MMR">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<point key="canvasLocation" x="20" y="1225.5"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="14" height="14"/>
|
||||
|
||||
27
baRSS/FeedEdit.h
Normal file
27
baRSS/FeedEdit.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface FeedEdit : NSWindow
|
||||
|
||||
@end
|
||||
58
baRSS/FeedEdit.m
Normal file
58
baRSS/FeedEdit.m
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
// Copyright (c) 2018 Oleg Geier
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#import "FeedEdit.h"
|
||||
|
||||
@implementation FeedEdit
|
||||
|
||||
- (IBAction)didTapDoneButton:(id)sender {
|
||||
[self.parentWindow endSheet:self returnCode:NSModalResponseOK];
|
||||
}
|
||||
|
||||
- (IBAction)didTapCancelButton:(id)sender {
|
||||
[self.parentWindow endSheet:self returnCode:NSModalResponseAbort];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@interface StrictUIntFormatter : NSFormatter
|
||||
@end
|
||||
|
||||
@implementation StrictUIntFormatter
|
||||
- (NSString *)stringForObjectValue:(id)obj {
|
||||
return [NSString stringWithFormat:@"%d", [[NSString stringWithFormat:@"%@", obj] intValue]];
|
||||
}
|
||||
- (BOOL)getObjectValue:(out id _Nullable __autoreleasing *)obj forString:(NSString *)string errorDescription:(out NSString *__autoreleasing _Nullable *)error {
|
||||
*obj = [[NSNumber numberWithInt:[string intValue]] stringValue];
|
||||
return YES;
|
||||
}
|
||||
- (BOOL)isPartialStringValid:(NSString *__autoreleasing _Nonnull *)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString *__autoreleasing _Nullable *)error {
|
||||
for (NSUInteger i = 0; i < [*partialStringPtr length]; i++) {
|
||||
unichar c = [*partialStringPtr characterAtIndex:i];
|
||||
if (c < '0' || c > '9')
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
@end
|
||||
@@ -29,6 +29,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<string>AppHook</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -22,10 +22,11 @@
|
||||
|
||||
#import "NewsController.h"
|
||||
#import "PyHandler.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "Preferences.h"
|
||||
#import "DBv1+CoreDataModel.h"
|
||||
|
||||
@interface NewsController ()
|
||||
@property (weak) IBOutlet Preferences *preferencesWindow;
|
||||
@property (weak) IBOutlet NSOutlineView *outlineView;
|
||||
|
||||
@property (strong) NSArray<NSTreeNode*> *currentlyDraggedNodes;
|
||||
@@ -98,8 +99,22 @@ static NSString *dragNodeType = @"baRSS-feed-type";
|
||||
NSLog(@"all unread");
|
||||
}
|
||||
|
||||
- (IBAction)presentModalFeedProperties:(id)sender {
|
||||
self.preferencesWindow.feedDetailSheet.parentWindow = self.preferencesWindow;
|
||||
[self.preferencesWindow beginSheet:self.preferencesWindow.feedDetailSheet completionHandler:^(NSModalResponse returnCode) {
|
||||
NSLog(@"%ld", (long)returnCode);
|
||||
}];
|
||||
// if ([sender isKindOfClass:[NSOutlineView class]]) {
|
||||
// NSOutlineView *ov = sender;
|
||||
// if (ov.clickedRow == -1)
|
||||
// return; // ignore clicks on column headers and where no row was selected
|
||||
//
|
||||
// id vop = [ov itemAtRow:ov.clickedRow];
|
||||
// NSLog(@"%@", vop);
|
||||
// }
|
||||
}
|
||||
|
||||
- (IBAction)addFeed:(NSButton *)sender {
|
||||
NSLog(@"add feed");
|
||||
[self.managedObjectContext.undoManager beginUndoGrouping];
|
||||
FeedConfig *nf = [self insertSortedItemAtSelection];
|
||||
nf.type = 1;
|
||||
@@ -117,10 +132,9 @@ static NSString *dragNodeType = @"baRSS-feed-type";
|
||||
}
|
||||
|
||||
- (IBAction)addSeparator:(NSButton *)sender {
|
||||
NSLog(@"add separator");
|
||||
[self.managedObjectContext.undoManager beginUndoGrouping];
|
||||
FeedConfig *sp = [self insertSortedItemAtSelection];
|
||||
sp.name = @"-------------";
|
||||
sp.name = @"---";
|
||||
sp.type = 2;
|
||||
[self.managedObjectContext.undoManager endUndoGrouping];
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface Preferences : NSWindowController
|
||||
@interface Preferences : NSWindow
|
||||
@property (weak) IBOutlet NSWindow *feedDetailSheet;
|
||||
|
||||
@end
|
||||
|
||||
@@ -24,59 +24,45 @@
|
||||
#import "NewsController.h"
|
||||
|
||||
@interface Preferences ()
|
||||
@property (weak) IBOutlet NSToolbar *toolbar;
|
||||
@property (weak) IBOutlet NSView *viewGeneral;
|
||||
@property (weak) IBOutlet NSView *viewFeeds;
|
||||
|
||||
@property (weak) IBOutlet NewsController *newsController;
|
||||
@property (weak) IBOutlet NSOutlineView *feedsOutline;
|
||||
@end
|
||||
|
||||
@implementation Preferences
|
||||
|
||||
- (void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
if (self.window.contentView.subviews.count == 0) {
|
||||
self.window.contentView = self.viewGeneral;
|
||||
if (self.contentView.subviews.count == 0) {
|
||||
self.contentView = self.viewGeneral;
|
||||
self.toolbar.selectedItemIdentifier = self.toolbar.items.firstObject.itemIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)clickGeneral:(NSToolbarItem *)sender {
|
||||
self.window.contentView = self.viewGeneral;
|
||||
- (IBAction)tabGeneralClicked:(NSToolbarItem *)sender {
|
||||
self.contentView = self.viewGeneral;
|
||||
}
|
||||
|
||||
- (IBAction)clickFeeds:(NSToolbarItem *)sender {
|
||||
self.window.contentView = self.viewFeeds;
|
||||
- (IBAction)tabFeedsClicked:(NSToolbarItem *)sender {
|
||||
self.contentView = self.viewFeeds;
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)event {
|
||||
if (event.modifierFlags & NSEventModifierFlagCommand) {
|
||||
bool holdShift = event.modifierFlags & NSEventModifierFlagShift;
|
||||
unichar key = [event.characters characterAtIndex:0];
|
||||
switch (key) {
|
||||
case 'w': [self close]; break;
|
||||
case 'q': [NSApplication.sharedApplication terminate:self]; break;
|
||||
}
|
||||
if (self.window.contentView == self.viewFeeds) { // these only apply for NSOutlineView
|
||||
switch (key) {
|
||||
case 'z':
|
||||
if (holdShift) [self.newsController.managedObjectContext.undoManager redo];
|
||||
else [self.newsController.managedObjectContext.undoManager undo];
|
||||
[self.newsController rearrangeObjects]; // update the ordering
|
||||
break;
|
||||
case 'o': break; // open .opml file
|
||||
case 's': break; // save data or backup .opml file
|
||||
case 'c': // copy row entry
|
||||
[self.newsController copyDescriptionOfSelectedItems];
|
||||
break;
|
||||
case 'a': [self.feedsOutline selectAll:nil]; break;
|
||||
}
|
||||
}
|
||||
- (void)undo:(id)sender {
|
||||
if (self.contentView == self.viewFeeds) {
|
||||
[self.newsController.managedObjectContext.undoManager undo];
|
||||
[self.newsController rearrangeObjects]; // update the ordering
|
||||
}
|
||||
}
|
||||
|
||||
- (void)redo:(id)sender {
|
||||
if (self.contentView == self.viewFeeds) {
|
||||
[self.newsController.managedObjectContext.undoManager redo];
|
||||
[self.newsController rearrangeObjects]; // update the ordering
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender {
|
||||
[self.newsController copyDescriptionOfSelectedItems];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user