[Play Info] Implement track rating system

The track ratings are stored in the same stats table as the play counts.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
lastfm
Christopher Snowhill 2022-06-28 01:55:30 -07:00
parent 2d7c3b51c7
commit 44fb1efc73
9 changed files with 207 additions and 78 deletions

View File

@ -25,13 +25,13 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2123">
<rect key="frame" x="0.0" y="360" width="1030" height="40"/>
<rect key="frame" x="0.0" y="361" width="1030" height="39"/>
<subviews>
<scrollView fixedFrame="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="0.0" verticalLineScroll="24" verticalPageScroll="0.0" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="206" userLabel="Scroll View - Playlist View">
<rect key="frame" x="0.0" y="0.0" width="1030" height="40"/>
<rect key="frame" x="0.0" y="0.0" width="1030" height="39"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="KWC-Ti-8KY">
<rect key="frame" x="0.0" y="0.0" width="1030" height="40"/>
<rect key="frame" x="0.0" y="0.0" width="1030" height="39"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" alternatingRowBackgroundColors="YES" autosaveName="Playlist" rowHeight="18" headerView="1517" viewBased="YES" id="207" customClass="PlaylistView">
@ -127,8 +127,8 @@
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="title" editable="NO" width="125.5" minWidth="96" maxWidth="1024" id="208">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Title">
<tableColumn identifier="rating" editable="NO" width="64" minWidth="64" maxWidth="64" id="208" userLabel="Rating">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Rating">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
@ -141,11 +141,11 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="ZCP-Dx-UBV">
<rect key="frame" x="106" y="3" width="125" height="18"/>
<rect key="frame" x="106" y="3" width="64" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="exY-Bg-Mjm">
<rect key="frame" x="0.0" y="1" width="126" height="16"/>
<rect key="frame" x="0.0" y="1" width="64" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="sdo-Sm-KPH">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -171,6 +171,50 @@
</binding>
</connections>
</tableColumn>
<tableColumn identifier="title" editable="NO" width="125.5" minWidth="96" maxWidth="1024" id="XBr-ec-D81">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Title">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="20m-a6-e24">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<sortDescriptor key="sortDescriptorPrototype" selector="caseInsensitiveCompare:" sortKey="title"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="ZHl-H1-IIC">
<rect key="frame" x="173" y="3" width="125" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="dQP-wC-mba">
<rect key="frame" x="0.0" y="1" width="126" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="VVx-99-roJ">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="dQP-wC-mba" firstAttribute="leading" secondItem="ZHl-H1-IIC" secondAttribute="leading" constant="2" id="RRE-MM-Fc6"/>
<constraint firstItem="dQP-wC-mba" firstAttribute="centerX" secondItem="ZHl-H1-IIC" secondAttribute="centerX" id="T3S-gq-Mcb"/>
<constraint firstItem="dQP-wC-mba" firstAttribute="centerY" secondItem="ZHl-H1-IIC" secondAttribute="centerY" id="auz-Po-AgT"/>
</constraints>
<connections>
<outlet property="textField" destination="dQP-wC-mba" id="slW-Fj-66g"/>
</connections>
</tableCellView>
</prototypeCellViews>
<connections>
<binding destination="218" name="value" keyPath="arrangedObjects.title" id="Qr8-tD-lGt">
<dictionary key="options">
<bool key="NSConditionallySetsEditable" value="YES"/>
</dictionary>
</binding>
</connections>
</tableColumn>
<tableColumn identifier="albumartist" editable="NO" width="150" minWidth="96" maxWidth="1024" hidden="YES" id="yGV-gP-Wl6">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Album Artist">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@ -229,7 +273,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="gpC-Oe-Rog">
<rect key="frame" x="234" y="3" width="150" height="18"/>
<rect key="frame" x="301.5" y="3" width="150" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="1WK-qN-Mgj">
@ -273,7 +317,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="1ed-gX-bct">
<rect key="frame" x="387" y="3" width="150" height="18"/>
<rect key="frame" x="454" y="3" width="150" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="nEt-s5-vRX">
@ -316,7 +360,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="hhB-nv-e78">
<rect key="frame" x="540" y="3" width="96" height="18"/>
<rect key="frame" x="607.5" y="3" width="96" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="tHy-sM-HDB">
@ -360,7 +404,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="q93-oh-i5T">
<rect key="frame" x="639" y="3" width="93" height="18"/>
<rect key="frame" x="706" y="3" width="93" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="bOi-LI-TDx">
@ -387,7 +431,7 @@
<binding destination="1689" name="fontSize" keyPath="values.fontSize" id="1921"/>
</connections>
</tableColumn>
<tableColumn identifier="genre" editable="NO" width="144" minWidth="96" maxWidth="512" id="849">
<tableColumn identifier="genre" editable="NO" width="64" minWidth="32" maxWidth="512" id="849">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Genre">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -401,11 +445,11 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="rRl-p9-Awr">
<rect key="frame" x="735" y="3" width="144" height="18"/>
<rect key="frame" x="802.5" y="3" width="64" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="yW6-2w-6mN">
<rect key="frame" x="0.0" y="1" width="144" height="16"/>
<rect key="frame" x="0.0" y="1" width="64" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="js2-sT-U4M">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -441,7 +485,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="hgh-VE-5kl">
<rect key="frame" x="882" y="3" width="39" height="18"/>
<rect key="frame" x="869.5" y="3" width="39" height="18"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="yEY-MI-d3o">
@ -2140,13 +2184,8 @@ Gw
<menuItem title="Add to Queue" id="1893">
<connections>
<action selector="toggleQueued:" target="218" id="1934"/>
<binding destination="2020" name="enabled" keyPath="selection" id="2068">
<binding destination="2020" name="enabled" keyPath="selection" id="tl0-j5-Pok">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<integer key="NSRaisesForNotApplicableKeys" value="1"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2166,12 +2205,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopAfterSelection:" target="218" id="ZRy-Mw-4cY"/>
<binding destination="2020" name="enabled" keyPath="selection" id="lrh-gy-5Z3">
<binding destination="2020" name="enabled" keyPath="selection" id="ytG-h2-5MA">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2182,12 +2217,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="searchByArtist:" target="218" id="2118"/>
<binding destination="2020" name="enabled" keyPath="selection.artist" id="2066">
<binding destination="2020" name="enabled" keyPath="selection.artist" id="gQw-pa-TIE">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2197,12 +2228,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="searchByAlbum:" target="218" id="2119"/>
<binding destination="2020" name="enabled" keyPath="selection.album" id="2067">
<binding destination="2020" name="enabled" keyPath="selection.album" id="F1G-2E-nhM">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2216,12 +2243,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reloadTags:" target="218" id="Ghx-F8-uF3"/>
<binding destination="2020" name="enabled" keyPath="selection" id="s3T-C1-yR0">
<binding destination="2020" name="enabled" keyPath="selection" id="khw-aB-pyx">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2230,13 +2253,19 @@ Gw
<menuItem title="Reset Play Count" id="5iV-dM-oX2">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="resetPlaycounts:" target="218" id="M3d-2T-ZRq"/>
<binding destination="2020" name="enabled" keyPath="selection" id="2FG-Dj-1XM">
<binding destination="2020" name="enabled" keyPath="selection" id="Ixw-08-sA9">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
</connections>
</menuItem>
<menuItem title="Remove Rating" id="PyI-lF-iuz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="removeRatings:" target="218" id="f0r-ur-bMZ"/>
<binding destination="2020" name="enabled" keyPath="selection" id="BNy-Ih-BJg">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2245,12 +2274,8 @@ Gw
<menuItem title="Show in Finder" id="1064">
<connections>
<action selector="showEntryInFinder:" target="218" id="1345"/>
<binding destination="2020" name="enabled" keyPath="selection" id="2069">
<binding destination="2020" name="enabled" keyPath="selection" id="sJT-oT-8Cw">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2260,12 +2285,8 @@ Gw
<menuItem title="Remove" id="1360">
<connections>
<action selector="remove:" target="218" id="1361"/>
<binding destination="2020" name="enabled" keyPath="selection" id="2070">
<binding destination="2020" name="enabled" keyPath="selection" id="Z62-ts-HSG">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2275,12 +2296,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="trash:" target="218" id="7Vd-Vf-Ym1"/>
<binding destination="2020" name="enabled" keyPath="selection" id="pGj-Wj-1bF">
<binding destination="2020" name="enabled" keyPath="selection" id="Knx-iC-hoo">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
@ -2291,12 +2308,8 @@ Gw
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showWindow:" target="2422" id="lET-Cq-KED"/>
<binding destination="2020" name="enabled" keyPath="selection" id="Ff1-eV-AGk">
<binding destination="2020" name="enabled" keyPath="selection" id="pj1-yp-Ojr">
<dictionary key="options">
<integer key="NSMultipleValuesPlaceholder" value="0"/>
<integer key="NSNoSelectionPlaceholder" value="0"/>
<integer key="NSNotApplicablePlaceholder" value="0"/>
<integer key="NSNullPlaceholder" value="0"/>
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="20086" systemVersion="21F79" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21223.12" systemVersion="22A5286j" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AlbumArtwork" representedClassName="AlbumArtwork" syncable="YES" codeGenerationType="class">
<attribute name="artData" optional="YES" attributeType="Binary"/>
<attribute name="artHash" optional="YES" attributeType="String"/>
@ -11,6 +11,7 @@
<attribute name="filename" optional="YES" attributeType="String"/>
<attribute name="firstSeen" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="lastPlayed" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="rating" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="title" optional="YES" attributeType="String"/>
</entity>
<entity name="PlaylistEntry" representedClassName="PlaylistEntry" syncable="YES" codeGenerationType="class">
@ -67,7 +68,7 @@
</entity>
<elements>
<element name="AlbumArtwork" positionX="0" positionY="207" width="128" height="59"/>
<element name="PlayCount" positionX="-18" positionY="171" width="128" height="134"/>
<element name="PlayCount" positionX="-18" positionY="171" width="128" height="149"/>
<element name="PlaylistEntry" positionX="-36" positionY="9" width="128" height="719"/>
<element name="SandboxToken" positionX="-18" positionY="171" width="128" height="59"/>
</elements>

View File

@ -143,6 +143,7 @@ typedef NS_ENUM(NSInteger, URLOrigin) {
// Reset playcount of selection
- (IBAction)resetPlaycounts:(id _Nullable)sender;
- (IBAction)removeRatings:(id _Nullable)sender;
// Play statistics
- (void)updatePlayCountForTrack:(PlaylistEntry *_Nonnull)pe;
@ -153,4 +154,6 @@ typedef NS_ENUM(NSInteger, URLOrigin) {
- (void)insertObjectsUnsynced:(NSArray *_Nullable)objects atArrangedObjectIndexes:(NSIndexSet *_Nullable)indexes;
- (void)tableView:(NSTableView *)view didClickRow:(NSInteger)clickedRow column:(NSInteger)clickedColumn atPoint:(NSPoint)cellPoint;
@end

View File

@ -47,7 +47,7 @@ static void *playlistControllerContext = &playlistControllerContext;
+ (void)initialize {
cellIdentifiers = @[@"index", @"status", @"title", @"albumartist", @"artist",
@"album", @"length", @"year", @"genre", @"track", @"path",
@"filename", @"codec"];
@"filename", @"codec", @"rating"];
NSValueTransformer *repeatNoneTransformer =
[[RepeatModeTransformer alloc] initWithMode:RepeatModeNoRepeat];
@ -282,6 +282,26 @@ static void *playlistControllerContext = &playlistControllerContext;
}
}
- (void)ratingUpdatedWithEntry:(PlaylistEntry *)pe rating:(CGFloat)rating {
if(pe && !pe.deLeted) {
PlayCount *pc = pe.playCountItem;
if(!pc) {
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
pc.count = 0;
pc.firstSeen = [NSDate date];
pc.album = pe.album;
pc.artist = pe.artist;
pc.title = pe.title;
pc.filename = pe.filenameFragment;
}
pc.rating = rating;
[self commitPersistentStore];
}
}
- (void)resetPlayCountForTrack:(PlaylistEntry *)pe {
PlayCount *pc = pe.playCountItem;
@ -290,6 +310,14 @@ static void *playlistControllerContext = &playlistControllerContext;
}
}
- (void)removeRatingForTrack:(PlaylistEntry *)pe {
PlayCount *pc = pe.playCountItem;
if(pc) {
pc.rating = 0;
}
}
- (void)updatePlaylistIndexes {
NSArray *arranged = [self arrangedObjects];
NSUInteger n = [arranged count];
@ -379,6 +407,8 @@ static void *playlistControllerContext = &playlistControllerContext;
PlaylistEntry *pe = [[self arrangedObjects] objectAtIndex:row];
float fontSize = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] floatForKey:@"fontSize"];
BOOL cellRating = NO;
if(pe) {
cellIdentifier = [tableColumn identifier];
@ -440,6 +470,21 @@ static void *playlistControllerContext = &playlistControllerContext;
case 12:
if([pe codec]) cellText = pe.codec;
break;
case 13:
{
NSString *filledStar = @"★";
NSString *emptyStar = @"☆";
NSUInteger rating = (NSUInteger)ceil(pe.rating);
if(rating < 0)
rating = 0;
else if(rating > 5)
rating = 5;
cellText = [@"" stringByPaddingToLength:rating withString:filledStar startingAtIndex:0];
cellText = [cellText stringByPaddingToLength:5 withString:emptyStar startingAtIndex:0];
cellRating = YES;
break;
}
}
}
@ -486,6 +531,26 @@ static void *playlistControllerContext = &playlistControllerContext;
return view;
}
- (void)tableView:(NSTableView *)view didClickRow:(NSInteger)clickedRow column:(NSInteger)clickedColumn atPoint:(NSPoint)cellPoint {
NSTableColumn *column = [view tableColumns][clickedColumn];
NSString *cellIdentifier = [column identifier];
NSUInteger index = [cellIdentifiers indexOfObject:cellIdentifier];
if(index == 13) {
NSInteger rating = ((CGFloat)ceil(cellPoint.x * 5.0 / 64.0));
if(rating < 1) rating = 1;
else if(rating > 5) rating = 5;
PlaylistEntry *pe = [[self arrangedObjects] objectAtIndex:clickedRow];
[self ratingUpdatedWithEntry:pe rating:rating];
NSIndexSet *refreshRow = [NSIndexSet indexSetWithIndex:clickedRow];
NSIndexSet *refreshColumn = [NSIndexSet indexSetWithIndex:clickedColumn];
[self.tableView reloadDataForRowIndexes:refreshRow columnIndexes:refreshColumn];
}
}
- (void)updateRowSize {
[self.tableView reloadData];
if(currentEntry != nil) [self.tableView scrollRowToVisible:currentEntry.index];
@ -1737,4 +1802,26 @@ static void *playlistControllerContext = &playlistControllerContext;
}
}
- (IBAction)removeRatings:(id)sender {
NSArray *selectedobjects = [self selectedObjects];
if([selectedobjects count]) {
for(PlaylistEntry *pe in selectedobjects) {
[self removeRatingForTrack:pe];
}
[self commitPersistentStore];
NSMutableIndexSet *refreshSet = [[NSMutableIndexSet alloc] init];
for(PlaylistEntry *pe in selectedobjects) {
if(pe.index >= 0 && pe.index < NSNotFound) {
[refreshSet addIndex:pe.index];
}
}
// Refresh entire row to refresh tooltips
unsigned long columns = [[self.tableView tableColumns] count];
[self.tableView reloadDataForRowIndexes:refreshSet columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, columns)]];
}
}
@end

View File

@ -72,6 +72,8 @@
@property(nonatomic, readonly) NSString *_Nonnull playCount;
@property(nonatomic, readonly) NSString *_Nonnull playCountInfo;
@property(nonatomic, readonly) float rating;
- (void)setMetadata:(NSDictionary *_Nonnull)metadata;
@end

View File

@ -560,4 +560,14 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path) {
return @"";
}
@dynamic rating;
- (float)rating {
PlayCount *pc = self.playCountItem;
if(pc) {
return pc.rating;
} else {
return 0;
}
}
@end

View File

@ -111,15 +111,28 @@
}
- (BOOL)acceptsFirstMouse:(NSEvent *)mouseDownEvent {
return NO;
return YES;
}
- (void)mouseDown:(NSEvent *)e {
[super mouseDown:e];
if([e type] == NSEventTypeLeftMouseDown && [e clickCount] == 2 &&
[[self selectedRowIndexes] count] == 1) {
[playbackController play:self];
if([e type] == NSEventTypeLeftMouseDown) {
if([e clickCount] == 1) {
NSPoint globalLocation = [e locationInWindow];
NSPoint localLocation = [self convertPoint:globalLocation fromView:nil];
NSInteger clickedRow = [self rowAtPoint:localLocation];
NSInteger clickedColumn = [self columnAtPoint:localLocation];
if(clickedRow != -1 && clickedColumn != -1) {
NSView *cellView = [self viewAtColumn:clickedColumn row:clickedRow makeIfNecessary:YES];
NSPoint cellPoint = [cellView convertPoint:localLocation fromView:self];
[playlistController tableView:self didClickRow:clickedRow column:clickedColumn atPoint:cellPoint];
}
} else if([e clickCount] == 2 && [[self selectedRowIndexes] count] == 1) {
[playbackController play:self];
}
}
}

View File

@ -101,8 +101,8 @@
/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "197"; */
"197.title" = "Zoom";
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "208"; */
"208.headerCell.title" = "Title";
/* Class = "NSTableColumn"; headerCell.title = "Rating"; ObjectID = "208"; */
"208.headerCell.title" = "Rating";
/* Class = "NSTableColumn"; headerCell.title = "#"; ObjectID = "209"; */
"209.headerCell.title" = "#";

View File

@ -101,8 +101,8 @@
/* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "197"; */
"197.title" = "Zoom";
/* Class = "NSTableColumn"; headerCell.title = "Title"; ObjectID = "208"; */
"208.headerCell.title" = "Title";
/* Class = "NSTableColumn"; headerCell.title = "Rating"; ObjectID = "208"; */
"208.headerCell.title" = "Rating";
/* Class = "NSTableColumn"; headerCell.title = "#"; ObjectID = "209"; */
"209.headerCell.title" = "#";