[vlc-commits] [Git][videolan/vlc][master] macosx: Add header view in favourites library view

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Jan 26 11:59:01 UTC 2026



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
b29f736c by Claudio Cambra at 2026-01-26T11:43:13+00:00
macosx: Add header view in favourites library view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -


12 changed files:

- modules/gui/macosx/Makefile.am
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h → modules/gui/macosx/library/VLCLibraryGroupHeaderDelegate.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
- modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesDataSource.h
- modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesDataSource.m
- modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesTableViewDelegate.m
- modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesViewController.h
- modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesViewController.m


Changes:

=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -172,6 +172,7 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/VLCLibraryDataTypes.m \
 	gui/macosx/library/VLCLibraryNameCache.h \
 	gui/macosx/library/VLCLibraryNameCache.m \
+	gui/macosx/library/VLCLibraryGroupHeaderDelegate.h \
 	gui/macosx/library/VLCLibraryHeroView.h \
 	gui/macosx/library/VLCLibraryHeroView.m \
 	gui/macosx/library/VLCLibraryImageCache.h \
@@ -278,7 +279,6 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.h \
 	gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.m \
 	gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h \
-	gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h \
 	gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.h \
 	gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.m \


=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -1881,8 +1881,15 @@ static NSString *genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
                       withMediaItems:(NSArray<VLCMediaLibraryMediaItem *> *)mediaItems
 {
 
+    NSString *detailString;
+    if (mediaItems.count == 1) {
+        detailString = _NS("1 item");
+    } else {
+        detailString = [NSString stringWithFormat:_NS("%lu items"), (unsigned long)mediaItems.count];
+    }
+
     self = [self initWithDisplayString:displayString
-               withPrimaryDetailString:[NSString stringWithFormat:@"%lu items", (unsigned long)mediaItems.count]
+               withPrimaryDetailString:detailString
               withSecondaryDetailString:@""];
     if (self) {
         _mediaItems = mediaItems;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h → modules/gui/macosx/library/VLCLibraryGroupHeaderDelegate.h
=====================================
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * VLCLibraryAudioDataSourceHeaderDelegate.h: MacOS X interface module
+ * VLCLibraryGroupHeaderDelegate.h: MacOS X interface module
  *****************************************************************************
  * Copyright (C) 2025 VLC authors and VideoLAN
  *
@@ -22,18 +22,16 @@
 
 #import <Cocoa/Cocoa.h>
 
- at class VLCLibraryAudioDataSource;
 @class VLCLibraryRepresentedItem;
 
 NS_ASSUME_NONNULL_BEGIN
 
- at protocol VLCLibraryAudioDataSourceHeaderDelegate <NSObject>
+ at protocol VLCLibraryGroupHeaderDelegate <NSObject>
 
-- (void)audioDataSource:(VLCLibraryAudioDataSource *)dataSource
-    updateHeaderForTableView:(NSTableView *)tableView
-         withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
-               fallbackTitle:(NSString *)fallbackTitle
-              fallbackDetail:(NSString *)fallbackDetail;
+- (void)updateHeaderForTableView:(NSTableView *)tableView
+            withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+                  fallbackTitle:(NSString *)fallbackTitle
+                 fallbackDetail:(NSString *)fallbackDetail;
 
 @end
 


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
=====================================
@@ -24,7 +24,7 @@
 
 #import "library/VLCLibraryCollectionViewDataSource.h"
 #import "library/VLCLibraryTableViewDataSource.h"
-#import "library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h"
+#import "library/VLCLibraryGroupHeaderDelegate.h"
 
 #include "views/iCarousel/iCarousel.h"
 
@@ -71,7 +71,7 @@ extern NSString * const VLCLibraryAudioDataSourceDisplayedCollectionChangedNotif
 @property (readwrite, weak) NSCollectionView *collectionView;
 @property (readwrite, weak) iCarousel *carouselView;
 @property (readwrite, weak) NSTableView *gridModeListTableView;
- at property (readwrite, weak, nullable) id<VLCLibraryAudioDataSourceHeaderDelegate> headerDelegate;
+ at property (readwrite, weak, nullable) id<VLCLibraryGroupHeaderDelegate> headerDelegate;
 
 @property (nonatomic, readwrite, assign) VLCAudioLibrarySegment audioLibrarySegment;
 @property (readwrite, strong) VLCLibraryAudioGroupDataSource *audioGroupDataSource;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
=====================================
@@ -731,11 +731,10 @@ NSString * const VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification
         fallbackDetail = selectedItem.primaryDetailString;
     }
 
-    [self.headerDelegate audioDataSource:self
-                updateHeaderForTableView:tableView
-                     withRepresentedItem:representedItem
-                           fallbackTitle:fallbackTitle
-                          fallbackDetail:fallbackDetail];
+    [self.headerDelegate updateHeaderForTableView:tableView
+                              withRepresentedItem:representedItem
+                                    fallbackTitle:fallbackTitle
+                                   fallbackDetail:fallbackDetail];
 }
 
 - (void)tableView:(NSTableView * const)tableView selectRowIndices:(NSIndexSet * const)indices


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.h
=====================================
@@ -25,7 +25,7 @@
 #import "library/VLCLibrarySegment.h"
 #import "library/VLCLibraryAbstractMediaLibrarySegmentViewController.h"
 #import "library/VLCLibraryItemPresentingCapable.h"
-#import "library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h"
+#import "library/VLCLibraryGroupHeaderDelegate.h"
 
 @class VLCLibraryAudioDataSource;
 @class VLCLibraryAudioGroupDataSource;
@@ -37,7 +37,7 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
- at interface VLCLibraryAudioViewController : VLCLibraryAbstractMediaLibrarySegmentViewController<VLCLibraryItemPresentingCapable, VLCLibraryAudioDataSourceHeaderDelegate>
+ at interface VLCLibraryAudioViewController : VLCLibraryAbstractMediaLibrarySegmentViewController<VLCLibraryItemPresentingCapable, VLCLibraryGroupHeaderDelegate>
 
 @property (readonly, weak) NSView *audioLibraryView;
 @property (readonly, weak) NSSplitView *audioLibrarySplitView;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
=====================================
@@ -587,11 +587,10 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = @"VLCLibraryPlaceholderAudi
     [self.libraryWindow hideLoadingOverlay];
 }
 
-- (void)audioDataSource:(VLCLibraryAudioDataSource *)dataSource
-updateHeaderForTableView:(NSTableView *)tableView
-    withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
-          fallbackTitle:(NSString *)fallbackTitle
-         fallbackDetail:(NSString *)fallbackDetail
+- (void)updateHeaderForTableView:(NSTableView *)tableView
+            withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+                  fallbackTitle:(NSString *)fallbackTitle
+                 fallbackDetail:(NSString *)fallbackDetail
 {
     if (tableView != self.audioCollectionSelectionTableView &&
         tableView != self.audioGroupSelectionTableView &&


=====================================
modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesDataSource.h
=====================================
@@ -24,6 +24,7 @@
 
 #import "library/VLCLibraryCollectionViewDataSource.h"
 #import "library/VLCLibraryMasterDetailViewTableViewDataSource.h"
+#import "library/VLCLibraryGroupHeaderDelegate.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -47,9 +48,11 @@ typedef NS_ENUM(NSUInteger, VLCLibraryFavoritesSection) {
 @property (readwrite, weak) NSCollectionView *collectionView;
 @property (readwrite, weak) NSTableView *masterTableView;
 @property (readwrite, weak) NSTableView *detailTableView;
+ at property (readwrite, weak, nullable) id<VLCLibraryGroupHeaderDelegate> headerDelegate;
 
 - (void)reloadData;
 - (NSInteger)rowForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem;
+- (void)updateHeaderForMasterSelection;
 
 @end
 


=====================================
modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesDataSource.m
=====================================
@@ -31,6 +31,7 @@
 #import "library/VLCLibraryDataTypes.h"
 #import "library/VLCLibraryRepresentedItem.h"
 #import "library/VLCLibraryTableCellView.h"
+#import "library/VLCLibraryGroupHeaderDelegate.h"
 #import "library/audio-library/VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.h"
 
 #import "views/VLCImageView.h"
@@ -278,11 +279,12 @@ NSString * const VLCLibraryFavoritesDataSourceDisplayedCollectionChangedNotifica
     _allFavoritesArray = [self.libraryModel listOfLibraryItemsOfParentType:VLCMediaLibraryParentGroupTypeAllFavorites];
 
     [self updateVisibleSectionMapping];
-    
+
     [_flattenedRowMappings removeAllObjects];
 
-    const NSInteger selectedRow = self.masterTableView.selectedRow;
+    [self updateHeaderForMasterSelection];
 
+    const NSInteger selectedRow = self.masterTableView.selectedRow;
     if (self.masterTableView.dataSource == self) {
         [self.masterTableView reloadData];
         if (selectedRow != -1 && selectedRow < [self.masterTableView numberOfRows]) {
@@ -378,6 +380,55 @@ NSString * const VLCLibraryFavoritesDataSourceDisplayedCollectionChangedNotifica
     return NSNotFound;
 }
 
+- (void)updateHeaderForMasterSelection
+{
+    VLCLibraryRepresentedItem *representedItem = nil;
+    NSString *fallbackTitle = nil;
+    NSString *fallbackDetail = nil;
+
+    if (self.masterTableView.selectedRow >= 0) {
+        const VLCLibraryFavoritesSection section = [self sectionForVisibleIndex:self.masterTableView.selectedRow];
+        id<VLCMediaLibraryItemProtocol> const groupDescriptor = [self createGroupDescriptorForSection:section];
+        fallbackDetail = groupDescriptor.primaryDetailString;
+        const VLCMediaLibraryParentGroupType parentType = [self parentTypeForSection:section];
+        representedItem = [[VLCLibraryRepresentedItem alloc] initWithItem:groupDescriptor parentType:parentType];
+
+        switch (section) {
+            case VLCLibraryFavoritesSectionVideoMedia:
+                fallbackTitle = _NS("Favorite Videos");
+                break;
+            case VLCLibraryFavoritesSectionAudioMedia:
+                fallbackTitle = _NS("Favorite Audio");
+                break;
+            case VLCLibraryFavoritesSectionAlbums:
+                fallbackTitle = _NS("Favorite Albums");
+                break;
+            case VLCLibraryFavoritesSectionArtists:
+                fallbackTitle = _NS("Favorite Artists");
+                break;
+            case VLCLibraryFavoritesSectionGenres:
+                fallbackTitle = _NS("Favorite Genres");
+                break;
+            default:
+                break;
+        }
+    } else {
+        fallbackTitle = _NS("Favorites");
+        NSUInteger totalCount = 0;
+        totalCount += _favoriteVideoMediaArray.count;
+        totalCount += _favoriteAudioMediaArray.count;
+        totalCount += _favoriteAlbumsArray.count;
+        totalCount += _favoriteArtistsArray.count;
+        totalCount += _favoriteGenresArray.count;
+        fallbackDetail = [NSString stringWithFormat:@"%lu items", (unsigned long)totalCount];
+    }
+
+    [self.headerDelegate updateHeaderForTableView:self.detailTableView
+                              withRepresentedItem:representedItem
+                                    fallbackTitle:fallbackTitle
+                                   fallbackDetail:fallbackDetail];
+}
+
 - (VLCMediaLibraryParentGroupType)currentParentType
 {
     if (self.masterTableView.selectedRow > -1) {


=====================================
modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesTableViewDelegate.m
=====================================
@@ -29,9 +29,25 @@
 #import "library/VLCLibraryTableCellViewProtocol.h"
 #import "library/VLCLibraryTableViewDataSource.h"
 #import "library/audio-library/VLCLibraryAlbumTableCellView.h"
+#import "library/favorites-library/VLCLibraryFavoritesDataSource.h"
 
 @implementation VLCLibraryFavoritesTableViewDelegate
 
+- (void)tableViewSelectionDidChange:(NSNotification *)notification
+{
+    [super tableViewSelectionDidChange:notification];
+
+    NSTableView * const tableView = (NSTableView *)notification.object;
+    if (![tableView.dataSource isKindOfClass:VLCLibraryFavoritesDataSource.class]) {
+        return;
+    }
+
+    VLCLibraryFavoritesDataSource * const favoritesDataSource = (VLCLibraryFavoritesDataSource *)tableView.dataSource;
+    if (tableView == favoritesDataSource.masterTableView) {
+        [favoritesDataSource updateHeaderForMasterSelection];
+    }
+}
+
 - (NSView *)tableView:(NSTableView *)tableView
    viewForTableColumn:(NSTableColumn *)tableColumn
                   row:(NSInteger)row
@@ -84,4 +100,4 @@
     return tableView.rowHeight;
 }
 
- at end
\ No newline at end of file
+ at end


=====================================
modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesViewController.h
=====================================
@@ -29,6 +29,7 @@
 @class VLCLibraryCollectionView;
 @class VLCLibraryWindow;
 @class VLCLibraryFavoritesDataSource;
+ at class VLCLibraryAudioGroupTableHeaderView;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -44,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readonly, strong) NSTableView *favoritesLibraryGroupsTableView;
 
 @property (readwrite, strong) VLCLibraryFavoritesDataSource *libraryFavoritesDataSource;
+ at property (readwrite, strong) VLCLibraryAudioGroupTableHeaderView *favoritesHeaderView;
 
 - (instancetype)initWithLibraryWindow:(VLCLibraryWindow *)libraryWindow;
 - (void)presentFavoritesView;


=====================================
modules/gui/macosx/library/favorites-library/VLCLibraryFavoritesViewController.m
=====================================
@@ -45,9 +45,12 @@
 #import "library/favorites-library/VLCLibraryFavoritesTableViewDelegate.h"
 #import "library/audio-library/VLCLibraryAlbumTableCellView.h"
 #import "library/audio-library/VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.h"
+#import "library/VLCLibraryGroupHeaderDelegate.h"
+#import "library/audio-library/VLCLibraryAudioGroupTableHeaderView.h"
+#import "library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h"
 #import "main/VLCMain.h"
 
- at interface VLCLibraryFavoritesViewController ()
+ at interface VLCLibraryFavoritesViewController () <VLCLibraryGroupHeaderDelegate>
 {
     VLCLibraryFavoritesTableViewDelegate *_favoritesLibraryTableViewDelegate;
     VLCLibraryTwoPaneSplitViewDelegate *_splitViewDelegate;
@@ -104,9 +107,25 @@
 {
     self.favoritesLibrarySplitView.delegate = _splitViewDelegate;
 
+    CGFloat headerHeight = VLCLibraryAudioGroupTableHeaderViewHeight;
+    if (@available(macOS 26.0, *)) {
+        headerHeight += VLCLibraryUIUnits.largeSpacing * 2.f;
+    }
+
+    const NSRect headerFrame = NSMakeRect(0.f,
+                                          0.f,
+                                          self.favoritesLibraryGroupSelectionTableView.bounds.size.width,
+                                          headerHeight);
+    _favoritesHeaderView = [[VLCLibraryAudioGroupTableHeaderView alloc] initWithFrame:headerFrame];
+    _favoritesHeaderView.autoresizingMask = NSViewWidthSizable;
+
+    self.favoritesLibraryGroupSelectionTableView.headerView = self.favoritesHeaderView;
+
     NSTableColumn * const groupsColumn = [[NSTableColumn alloc] initWithIdentifier:@"groups"];
     NSTableColumn * const selectedGroupColumn = [[NSTableColumn alloc] initWithIdentifier:@"selectedGroup"];
     
+    selectedGroupColumn.headerCell = [VLCLibraryAudioGroupTableHeaderCell new];
+
     [self.favoritesLibraryGroupsTableView addTableColumn:groupsColumn];
     [self.favoritesLibraryGroupSelectionTableView addTableColumn:selectedGroupColumn];
 
@@ -126,7 +145,6 @@
                                                 forIdentifier:VLCAudioLibraryCellIdentifier];
     
     self.favoritesLibraryGroupsTableView.headerView = nil;
-    self.favoritesLibraryGroupSelectionTableView.headerView = nil;
     
     self.favoritesLibraryGroupsTableView.rowHeight = VLCLibraryUIUnits.mediumTableViewRowHeight;
     self.favoritesLibraryGroupSelectionTableView.rowHeight = VLCLibraryUIUnits.mediumTableViewRowHeight;
@@ -206,6 +224,7 @@
     self.libraryFavoritesDataSource.collectionView = self.favoritesLibraryCollectionView;
     self.libraryFavoritesDataSource.masterTableView = self.favoritesLibraryGroupsTableView;
     self.libraryFavoritesDataSource.detailTableView = self.favoritesLibraryGroupSelectionTableView;
+    self.libraryFavoritesDataSource.headerDelegate = self;
     
     self.favoritesLibraryCollectionView.dataSource = self.libraryFavoritesDataSource;
     
@@ -433,4 +452,20 @@
     }
 }
 
+#pragma mark - VLCLibraryGroupHeaderDelegate
+
+- (void)updateHeaderForTableView:(NSTableView *)tableView
+            withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+                  fallbackTitle:(NSString *)fallbackTitle
+                 fallbackDetail:(NSString *)fallbackDetail
+{
+    if (tableView != self.favoritesLibraryGroupSelectionTableView) {
+        return;
+    }
+
+    [self.favoritesHeaderView updateWithRepresentedItem:representedItem
+                                          fallbackTitle:fallbackTitle
+                                         fallbackDetail:fallbackDetail];
+}
+
 @end



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/b29f736cdd90c1dd24df599acd52e24dd1a7ecb5

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/b29f736cdd90c1dd24df599acd52e24dd1a7ecb5
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list