From 6108cc8d4f001d565a2623b0a88e63de061dcaf3 Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Mon, 29 Apr 2024 17:41:07 -0400 Subject: [PATCH] HiddenFilePathFilter: Fix hidden sequences Fixes #5810 When checking a path that has the `#` character for frame substitutions, `HiddenFilePathFilter` would always treat it as hidden. The file with `#` does not exist, so the Windows API would return `INVALID_FILE_ATTRIBUTES` whose value is `-1`. `FILE_ATTRIBUTE_HIDDEN` has a value of `2`. `-1 & 2 = 2`, so sequences would always be considered hidden. --- Changes.md | 4 ++ python/GafferTest/HiddenFilePathFilterTest.py | 51 +++++++++++++++++++ src/Gaffer/HiddenFilePathFilter.cpp | 23 +++++++-- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/Changes.md b/Changes.md index acc25aa8c8f..7673465ef6b 100644 --- a/Changes.md +++ b/Changes.md @@ -1,6 +1,10 @@ 1.3.16.x (relative to 1.3.16.1) ======== +Fixes +----- + +- File Browser : Windows only : Fixed bug in `HiddenFilePathFilter` that caused sequences to be treated as though they are hidden files (#5810). 1.3.16.1 (relative to 1.3.16.0) diff --git a/python/GafferTest/HiddenFilePathFilterTest.py b/python/GafferTest/HiddenFilePathFilterTest.py index 946341d674f..0751eb9afd6 100644 --- a/python/GafferTest/HiddenFilePathFilterTest.py +++ b/python/GafferTest/HiddenFilePathFilterTest.py @@ -39,6 +39,8 @@ import subprocess import unittest +import IECore + import Gaffer import GafferTest @@ -72,6 +74,55 @@ def test( self ) : self.assertEqual( p.children(), [ visibleFile ] ) + def testSequence( self ) : + + hiddenSequence = IECore.FileSequence( ( self.temporaryDirectory() / ".hidden.#.txt 1-3" ).as_posix() ) + visibleSequence = IECore.FileSequence( ( self.temporaryDirectory() / "visible.#.txt 1-3" ).as_posix() ) + + for frame in range( 3 ) : + hiddenFile = Gaffer.FileSystemPath( hiddenSequence.fileNameForFrame( frame ) ) + with open( hiddenFile.nativeString(), "w", encoding = "utf-8" ) as f : + f.write( "Hidden sequence") + if os.name == "nt" : + subprocess.check_call( [ "attrib", "+H", hiddenFile.nativeString() ] ) + + visibleFile = Gaffer.FileSystemPath( visibleSequence.fileNameForFrame( frame ) ) + with open( visibleFile.nativeString(), "w", encoding = "utf-8" ) as f : + f.write( "Visible sequence" ) + + p = Gaffer.FileSystemPath( pathlib.Path( hiddenSequence.fileName ).parent, None, True ) + + self.assertEqual( + sorted( [ str( i ) for i in p.children() ] ), + sorted( + [ hiddenSequence.fileNameForFrame( i ) for i in range( 3 ) ] + + [ visibleSequence.fileNameForFrame( i ) for i in range( 3 ) ] + + [ hiddenSequence.fileName, visibleSequence.fileName ] + ) + ) + + h = Gaffer.HiddenFilePathFilter() + p.setFilter( h ) + + self.assertEqual( + sorted( [ str( i ) for i in p.children() ] ), + sorted( + [ hiddenSequence.fileNameForFrame( i ) for i in range( 3 ) ] + + [ hiddenSequence.fileName ] + ) + ) + + h.setInverted( True ) + + self.assertEqual( + sorted( [ str( i ) for i in p.children() ] ), + sorted( + [ visibleSequence.fileNameForFrame( i ) for i in range( 3 ) ] + + [ visibleSequence.fileName ] + ) + ) + + if __name__ == "__main__": unittest.main() diff --git a/src/Gaffer/HiddenFilePathFilter.cpp b/src/Gaffer/HiddenFilePathFilter.cpp index 764871c0799..5a112d98e9d 100644 --- a/src/Gaffer/HiddenFilePathFilter.cpp +++ b/src/Gaffer/HiddenFilePathFilter.cpp @@ -39,6 +39,8 @@ #include "Gaffer/Path.h" +#include "IECore/FileSequenceFunctions.h" + #ifdef _MSC_VER #include @@ -46,6 +48,7 @@ #endif using namespace Gaffer; +using namespace IECore; IE_CORE_DEFINERUNTIMETYPED( HiddenFilePathFilter ); @@ -105,10 +108,24 @@ bool HiddenFilePathFilter::remove( PathPtr path ) const } return invert( true ); #else - DWORD fileAttributes = GetFileAttributes( path->string().c_str() ); - if( fileAttributes & FILE_ATTRIBUTE_HIDDEN ) + if( const auto filePath = runTimeCast( path.get() ) ) { - return invert( false ); + std::string file; + if( const auto sequence = filePath->fileSequence() ) + { + std::vector frames; + sequence->getFrameList()->asList( frames ); + file = sequence->fileNameForFrame( frames[0] ); + } + else + { + file = path->string(); + } + DWORD fileAttributes = GetFileAttributes( file.c_str() ); + if( fileAttributes & FILE_ATTRIBUTE_HIDDEN ) + { + return invert( false ); + } } return invert( true ); #endif