ignoreHiddenFiles and Finder display

Hi Jules,

Currently when using ignoreHiddenFiles when displaying the main osx volume using DirectoryIterator, it do not display the same child that the finder does.
It display files like mach and mach.sym which are I suppose hidden.

Is this a bug ?

Thanks,

I think it’s just hiding files that start with a ‘.’ - maybe that’s not really the best approach on the mac…

it’s not enough.

I use to do things like that:

FSRef ref;
OSStatus status = FSPathMakeRef((const UInt8*)path, &ref, NULL);
if (status == noErr)
{
  FSCatalogInfo catalogInfo;
  FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL);
   // replace FolderInfo by FileInfo when it's a file not a directory
   if ( ((FolderInfo*)&catalogInfo.finderInfo)->finderFlags & kIsInvisible)
   {
              // the file or dir is invisible
   }
 }

HTH
[/code]

Ok, I’ll see if I can find a neat place to add that.

Great! This was annoying us too.

Somehow, this doesn’t work for me. What could I be doing wrong?

I modified getNextMatch() in FindFileStruct in juce_mac_Files.cpp this way:

[code]if (isHidden != 0)
{
*isHidden = (de->d_name[0] == ‘.’); // the oldfashioned way

					if (!(*isHidden))
					{
						FSRef ref; 
						OSStatus status = FSPathMakeRef((const UInt8*)((const char*)path), &ref, NULL);
								
						if (status == noErr)
						{
							FSCatalogInfo catalogInfo; 
							FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL);
									
							if (isDir !=0)
							{
								if (*isDir)
								{
									if ( ((FolderInfo*)&catalogInfo.finderInfo)->finderFlags & kIsInvisible) (*isHidden)=true;
								}
								else
								{
									if ( ((FileInfo*)&catalogInfo.finderInfo)->finderFlags & kIsInvisible) (*isHidden)=true;
								}
							}
						}
					}
				}

[/code]

Beware that on mac, some file are not shown in the Finder but still are not set as not visible.

Which file are you having trouble with ?

Sorry - I’ve already written stuff to do all this, but haven’t checked it in yet…

[quote=“otristan”]Beware that on mac, some file are not shown in the Finder but still are not set as not visible.

Which file are you having trouble with ?[/quote]

For instance /dev, it is not shown in the Finder and so I don’t want it to be shown in my application - otherwise the “normal” user thinks “What is going on here ?”.

Jules, even with latest JUCE version from the SVN, directories like /etc or /dev still get shown even when using File::ignoreHiddenFiles . How can I make JUCE hide the directories that the Finder hides?

I don’t know, TBH. The latest version uses the “hidden file” bit of the “finder flags”, so if that doesn’t work, I’m really not sure what they expect you to do. Could just be that Finder itself is hard-wired to avoid the unix root paths.

But if that doesn’t change the situation it’s perhaps best to keep the old “.” files approach, because the new one seems to be much slower… ?

When do you notice it being slower? I’d have thought it wouldn’t make much difference.

In my app I have a TreeView showing files, and it connects to some database I programmed that scans for MP3’s. And if you have thousands of files the difference becomes noticeable. I use DirectoryIterator’s for the purpose.
I guess it’s normal that interfacing to the OS takes more time than just checking for a “.” at the beginning of a String anyway.
Also searching for only the directories in a directory became much slower. You can nearly see the TreeView building itself up.

ok guys.

I’ve asked on the carbon ML, and this is what I’ve come up with.

It sill display dev and net folder (I’ve asked back why) but still better and faster that the old solution.

static bool juce_isHiddenFile (const String& path) throw()
{
	FSRef ref;
	OSStatus err = FSPathMakeRefWithOptions((const UInt8*) path.toUTF8(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0);
	if (err == noErr)
	{
		LSItemInfoRecord info;
		err = LSCopyItemInfoForRef(&ref, kLSRequestBasicFlagsOnly, &info);
		if (err == noErr)
		{
			return ((info.flags & kLSItemInfoIsInvisible) != 0);
		}
	}
	return false;
}

HTH

[/code]

Ok, that looks a bit more sensible. Will probably be even slower to scan though.

Hi Jules,

Just checked the trunk and the old version is still in place.
So it still doesn’t detect etc, tmp and var as hidden.

Could you change the implementation of juce_isHiddenFile with this ?

static bool juce_isHiddenFile (const String& path)
{
#if JUCE_IOS
    return File (path).getFileName().startsWithChar ('.');
#else
  FSRef ref;
  OSStatus err = FSPathMakeRefWithOptions((const UInt8*) path.toUTF8(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0);
  if (err == noErr)
  {
    LSItemInfoRecord info;
    err = LSCopyItemInfoForRef(&ref, kLSRequestBasicFlagsOnly, &info);
    if (err == noErr)
    {
      return ((info.flags & kLSItemInfoIsInvisible) != 0);
    }
  }
  return false;
#endif
}

For what it worth, it’s been two years I use this code without any issue.
Just trying to get my fixes into the trunk :slight_smile:

Thanks,

All those old Carbon functions won’t be around much longer - it’d need to be done with Cocoa to make it into the official build!

I’ve asked the question to cocoa dev and here are there answers

[quote]FSPathMakeRefWithOptions() and LSCopyItemInfoForRef() are both available on 64-bit Mac OS. You can use that code as-is. (How can you tell? Find the function in the Mac OS SDK documentation. Functions that were dropped for 32-bit say “Availability: Not available to 64-bit applications”.)

The Cocoa equivalent might be -[NSURL getResourceValue:forKey:error:], with the NSURLIsHidden key. I don’t know if that’s identical to kLSItemInfoIsInvisible, though.[/quote]

[quote]
So what? The UI parts of Carbon didn’t make it to 64 bits, but as far as I know, FSPathMakeRefWithOptions and LSCopyItemInfoForRef are fine.
Note that CarbonCore.framework is within CoreServices.framework.[/quote]

So it seems that those function are fine for the cocoa port and 64 bits.

I think it’s actually pretty easy to do in cocoa, and works the same on iOS too:

[code]static bool juce_isHiddenFile (const String& path)
{
NSNumber* hidden = nil;

return [[NSURL fileURLWithPath: juceStringToNS (path)]
            getResourceValue: &hidden forKey: NSURLIsHiddenKey error: nil]
        && [hidden boolValue];

}
[/code]