How to implement 'Reveal in Finder'


#1

Does anyone know what i need to do be able to open a Finder dialog from within my application. So it shows a new Finder window with my file selected.
Is there a Juce utility function that lets me do this.

I know there is file.startAsProcess(); but that wouldn’t work as it try to open my file instead of just locating it.


#2

for windows : strVectorItemPath is juce::String.


if (strVectorItemPath.isNotEmpty())
         {
            juce::File projectFile(strVectorItemPath);
            if (projectFile.exists())
            {
               //This code is opens the file location and highlights/select the file in explorer.
               strVectorItemPath = strVectorItemPath.replace(T("/"), T("\\")); // just in case the path has unix style separator
               juce::String file = "/select," + strVectorItemPath;
               ShellExecute(NULL,"open","explorer", file.toUTF8(), NULL, SW_SHOWNORMAL);
            }
         } 

for mac : fileToOpen is char

NSString * path = [NSString stringWithCString:fileToOpen encoding:NSASCIIStringEncoding];
	if( path != 0L && [path length] != 0 )
	{
		if([ [ NSFileManager defaultManager] fileExistsAtPath : path] == YES)
		{
			NSString *parentDirectoryPath = [path stringByDeletingLastPathComponent];
			if (parentDirectoryPath != 0L)
			{
				BOOL operationStatus =  [ [NSWorkspace sharedWorkspace] openFile:parentDirectoryPath];
				
				if (operationStatus)
					operationStatus =[[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath:parentDirectoryPath];
			}
		}
	} 

#3

Well, that’s the enormously complex way of doing it.

But personally I think I’d go for:


#4

But that wouldn’t highlight the file


#5

ah, right! Well yes, if highlighting the file is important, then that’s a good solution!

It’s a good candidate for something to add to the library, actually.


#6

It would be an honour if it would make it to juce. :slight_smile:

This is the version of code Justin had shared with me for pc.

bool revealFile(const File &sourceFile)
{
jassert(sourceFile.exists());
if (!sourceFile.exists())   
return false;
// use the full path to explorer for security
   TCHAR winDir[MAX_PATH];
   uint32 len = GetSystemDirectory(winDir, MAX_PATH);
   
   // Need enough space to add the trailing backslash!
   if (!len || len > MAX_PATH - 2)
      return false;
   winDir[len]   = L'\\';
   winDir[++len] = L'\0';
   
      
   juce::String explorerParams;
   
   explorerParams << L"/select,";
    explorerParams << (L'\"');
    explorerParams << (sourceFile.getFullPathName());
   explorerParams << (L'\"');
   
   
   HINSTANCE result;

    if ((result=::ShellExecute(NULL, _T("open"),_T("explorer.exe"), (const TCHAR*)explorerParams,
                        winDir, SW_SHOWNORMAL)) <= (HINSTANCE) 32)
        return false;
   
    return true;
} 

and my mac version of code

bool revealFile(const File &sourceFile)
{
	BOOL operationStatus = NO;
	NSString * path = [NSString stringWithCString:sourceFile.toUTF8() encoding:NSASCIIStringEncoding];
	if( path != 0L && [path length] != 0 )
	{
		if([ [ NSFileManager defaultManager] fileExistsAtPath : path] == YES)
		{
			NSString *parentDirectoryPath = [path stringByDeletingLastPathComponent];
			if (parentDirectoryPath != 0L)
			{
				BOOL operationStatus =  [ [NSWorkspace sharedWorkspace] openFile:parentDirectoryPath];
				
				if (operationStatus)
					operationStatus =[[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath:parentDirectoryPath];
			}
		}
	} 
	return operationStatus;
}

If I get time I would put in juce and try it.


#7
 explorerParams << L"/select,";
    explorerParams << (L'\"');
    explorerParams << (sourceFile.getFullPathName());
   explorerParams << (L'\"'); 

Add a /n, so…

explorerParams << L"/n,/select,";

This is so you get two windows opening up should you select two files in the same folder.

And I’ve got an add on the mac…just make sure you have a ScopedReleasePool at the top! :slight_smile:

Justin


#8

I will do the easy part of the work keep you informed. :smiley: . You do the correction part of it.

How can I forget that :oops: .


#9

Sorry to be picky Vishvesh! :smiley:

NSString stringWithCString:sourceFile.toUTF8() encoding:NSASCIIStringEncoding

Throws alarms up to me.

Julian has a nice juceStringToNS in mac_native_headers that’ll keep everything all unicode friendly.


#10

I know that :slight_smile: .

The code I posted was my version of code which I had used outside of juce. I will be posting the version of code which can sit inside juce. Got the mac version running currently I am testing the windows version. After it’s done I would personally send you the post URL for code review :wink:.


#11

Here is the code( Justin, Jules and gekkie100 )

For mac with juceStringToNS :smiley: .

bool File::revealFile() const throw()
{
	const ScopedAutoReleasePool pool;
	BOOL operationStatus = NO;
	NSString * path = juceStringToNS (getFullPathName());
	if( path != 0L && [path length] != 0 )
	{
		if([ [ NSFileManager defaultManager] fileExistsAtPath : path] == YES)
		{
			NSString *parentDirectoryPath = [path stringByDeletingLastPathComponent];
			if (parentDirectoryPath != 0L)
			{
				BOOL operationStatus =  [ [NSWorkspace sharedWorkspace] openFile:parentDirectoryPath];
				
				if (operationStatus)
					operationStatus =[[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath:parentDirectoryPath];
			}
		}
	}
	return operationStatus; 
}

for windows : with original comments :smiley:

bool File::RevealFile()  const throw()
{
	bool operationStatus = false;
	if (!fullPath.isEmpty() && sourceFile.exists())
	{
		// use the full path to explorer for security 
		TCHAR winDir[MAX_PATH]; 
		uint32 len = GetSystemDirectory(winDir, MAX_PATH); 
    
		// Need enough space to add the trailing backslash! 
		if (len || !(len > MAX_PATH - 2)) 
		{
			winDir[len]   = L'\\'; 
			winDir[++len] = L'\0'; 
  
			juce::String explorerParams; 
			explorerParams << L"/select,"; 
			explorerParams << (L'\"'); 
			explorerParams << (getFullPathName()); 
			explorerParams << (L'\"'); 
			HINSTANCE result; 

			if ((result=::ShellExecute(NULL, _T("open"),_T("explorer.exe"), (const TCHAR*)explorerParams, 
                        winDir, SW_SHOWNORMAL)) <= (HINSTANCE) 32) 
				operationStatus = true; 
		}
	}
    return operationStatus; 
}

P.S. : Justin, will you be kind enough to review it. :wink:


#12

Thanx a lot!


#13

It’s always a pleasure. :slight_smile:


#14

Just for closure: File::revealToUser