2014-07-28 16:01:46 -04:00
package net.filebot ;
2014-07-29 02:40:35 -04:00
import static java.util.Arrays.* ;
2014-07-29 05:33:19 -04:00
import static java.util.Collections.* ;
2016-08-16 15:36:01 -04:00
import static java.util.stream.Collectors.* ;
2016-03-09 15:36:28 -05:00
import static net.filebot.Logging.* ;
2014-07-29 02:40:35 -04:00
import static net.filebot.Settings.* ;
2015-09-15 03:04:36 -04:00
import static net.filebot.similarity.Normalization.* ;
2014-07-29 02:45:15 -04:00
import static net.filebot.util.ui.SwingUI.* ;
2014-07-28 16:01:46 -04:00
2014-08-10 02:31:47 -04:00
import java.awt.Desktop ;
2014-07-28 16:01:46 -04:00
import java.awt.Dialog ;
import java.awt.FileDialog ;
import java.awt.Frame ;
2015-03-24 07:23:24 -04:00
import java.awt.event.ActionEvent ;
2014-07-28 16:01:46 -04:00
import java.io.File ;
2016-08-16 15:11:56 -04:00
import java.io.IOException ;
2014-08-10 04:35:53 -04:00
import java.util.Collection ;
2017-02-12 07:08:54 -05:00
import java.util.LinkedHashMap ;
2014-07-29 02:40:35 -04:00
import java.util.List ;
2014-07-29 05:33:19 -04:00
import java.util.concurrent.Callable ;
import java.util.concurrent.FutureTask ;
2014-08-10 02:31:47 -04:00
import java.util.logging.Level ;
2014-07-28 16:01:46 -04:00
import javax.swing.JFileChooser ;
2017-03-06 07:52:04 -05:00
import net.filebot.platform.mac.MacAppUtilities ;
2016-08-16 15:11:56 -04:00
import net.filebot.util.FileUtilities ;
2014-07-29 04:43:54 -04:00
import net.filebot.util.FileUtilities.ExtensionFileFilter ;
2014-07-28 16:01:46 -04:00
public class UserFiles {
2016-08-16 15:11:56 -04:00
public static void trash ( File file ) throws IOException {
// use system trash if possible
2018-09-20 09:39:53 -04:00
if ( Desktop . isDesktopSupported ( ) & & Desktop . getDesktop ( ) . isSupported ( Desktop . Action . MOVE_TO_TRASH ) ) {
2017-10-16 11:53:39 -04:00
try {
if ( Desktop . getDesktop ( ) . moveToTrash ( file ) ) {
2016-08-16 15:11:56 -04:00
return ;
}
2017-10-16 11:53:39 -04:00
debug . log ( Level . WARNING , message ( " Failed to move file to trash " , file ) ) ;
} catch ( Exception e ) {
debug . log ( Level . WARNING , e : : toString ) ;
2016-08-16 15:11:56 -04:00
}
}
// delete permanently if necessary
if ( file . exists ( ) ) {
FileUtilities . delete ( file ) ;
}
}
2014-08-10 04:35:53 -04:00
public static void revealFiles ( Collection < File > files ) {
2017-10-16 11:53:39 -04:00
// try to reveal file in folder
if ( Desktop . getDesktop ( ) . isSupported ( Desktop . Action . BROWSE_FILE_DIR ) ) {
2017-02-12 07:08:54 -05:00
files . stream ( ) . collect ( groupingBy ( File : : getParentFile , LinkedHashMap : : new , toList ( ) ) ) . forEach ( ( parent , children ) - > {
2014-08-10 04:35:53 -04:00
try {
2017-10-16 11:53:39 -04:00
Desktop . getDesktop ( ) . browseFileDirectory ( children . get ( children . size ( ) - 1 ) ) ;
2014-08-10 04:35:53 -04:00
} catch ( Exception e ) {
2016-08-16 15:11:56 -04:00
debug . log ( Level . WARNING , e : : toString ) ;
2014-08-10 04:35:53 -04:00
}
} ) ;
2016-08-16 15:11:56 -04:00
return ;
2014-08-10 02:31:47 -04:00
}
2016-08-16 15:11:56 -04:00
// if we can't reveal the file in folder, just reveal the parent folder
files . stream ( ) . map ( it - > it . getParentFile ( ) ) . distinct ( ) . forEach ( it - > {
try {
Desktop . getDesktop ( ) . open ( it ) ;
} catch ( Exception e ) {
debug . log ( Level . WARNING , e : : toString ) ;
}
} ) ;
2014-08-10 02:31:47 -04:00
}
2014-07-29 02:40:35 -04:00
private static FileChooser defaultFileChooser = getPreferredFileChooser ( ) ;
2014-07-28 16:01:46 -04:00
2014-07-29 02:40:35 -04:00
public static void setDefaultFileChooser ( FileChooser fileChooser ) {
defaultFileChooser = fileChooser ;
2014-07-28 16:01:46 -04:00
}
2015-03-24 07:23:24 -04:00
public static List < File > showLoadDialogSelectFiles ( boolean folderMode , boolean multiSelection , File defaultFile , ExtensionFileFilter filter , String title , ActionEvent evt ) {
String defaultFileKey = ( ( folderMode & & filter = = null ) | | ! ( folderMode & & filter ! = null & & isShiftOrAltDown ( evt ) ) ) ? KEY_OPEN_FOLDER : KEY_OPEN_FILE ;
List < File > files = defaultFileChooser . showLoadDialogSelectFiles ( defaultFileKey = = KEY_OPEN_FOLDER , multiSelection , getFileChooserDefaultFile ( defaultFileKey , defaultFile ) , filter , title , evt ) ;
2014-07-29 04:43:54 -04:00
if ( files . size ( ) > 0 ) {
2014-08-10 03:34:32 -04:00
setFileChooserDefaultFile ( defaultFileKey , files . get ( 0 ) ) ;
2014-07-29 04:43:54 -04:00
}
return files ;
2014-07-29 02:40:35 -04:00
}
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
public static File showSaveDialogSelectFile ( boolean folderMode , File defaultFile , String title , ActionEvent evt ) {
File file = defaultFileChooser . showSaveDialogSelectFile ( folderMode , getFileChooserDefaultFile ( KEY_SAVE , defaultFile ) , title , evt ) ;
2014-07-29 04:43:54 -04:00
if ( file ! = null ) {
setFileChooserDefaultFile ( KEY_SAVE , file ) ;
}
return file ;
2014-07-29 02:40:35 -04:00
}
2015-03-24 07:23:24 -04:00
public static File showOpenDialogSelectFolder ( File defaultFile , String title , ActionEvent evt ) {
List < File > folder = defaultFileChooser . showLoadDialogSelectFiles ( true , false , defaultFile , null , title , evt ) ;
2014-07-29 02:40:35 -04:00
return folder . size ( ) > 0 ? folder . get ( 0 ) : null ;
}
2014-07-29 05:50:57 -04:00
private static final String PREF_KEY_PREFIX = " dialog. " ;
private static final String KEY_OPEN_FILE = " open.file " ;
private static final String KEY_OPEN_FOLDER = " open.folder " ;
private static final String KEY_SAVE = " save.file " ;
2014-07-29 04:43:54 -04:00
2014-11-07 11:05:56 -05:00
protected static File getFileChooserDefaultFile ( String key , File userValue ) {
2014-07-29 04:43:54 -04:00
if ( userValue ! = null & & userValue . getParentFile ( ) ! = null )
return userValue ;
2014-11-07 11:05:56 -05:00
String path = Settings . forPackage ( UserFiles . class ) . get ( PREF_KEY_PREFIX + key ) ;
2014-07-29 04:43:54 -04:00
if ( path = = null | | path . isEmpty ( ) )
return userValue ;
if ( userValue ! = null & & userValue . getParentFile ( ) = = null )
return new File ( new File ( path ) . getParentFile ( ) , userValue . getName ( ) ) ;
return new File ( path ) ;
}
protected static void setFileChooserDefaultFile ( String name , File file ) {
Settings . forPackage ( UserFiles . class ) . put ( PREF_KEY_PREFIX + name , file . getPath ( ) ) ;
}
2014-07-29 02:40:35 -04:00
public enum FileChooser {
Swing {
2014-08-08 12:44:35 -04:00
2014-07-29 02:40:35 -04:00
@Override
2015-03-24 07:23:24 -04:00
public List < File > showLoadDialogSelectFiles ( boolean folderMode , boolean multiSelection , File defaultFile , ExtensionFileFilter filter , String title , ActionEvent evt ) {
2014-07-29 02:40:35 -04:00
JFileChooser chooser = new JFileChooser ( ) ;
2014-08-08 12:44:35 -04:00
chooser . setDialogTitle ( title ) ;
2014-07-29 04:43:54 -04:00
chooser . setMultiSelectionEnabled ( multiSelection ) ;
chooser . setFileSelectionMode ( folderMode & & filter = = null ? JFileChooser . DIRECTORIES_ONLY : JFileChooser . FILES_AND_DIRECTORIES ) ;
2014-11-07 11:05:56 -05:00
if ( defaultFile ! = null ) {
2014-12-29 06:47:26 -05:00
if ( defaultFile . isFile ( ) ) {
2014-11-07 11:05:56 -05:00
chooser . setSelectedFile ( defaultFile ) ;
2014-12-29 06:47:26 -05:00
} else if ( defaultFile . getParentFile ( ) ! = null & & defaultFile . getParentFile ( ) . isDirectory ( ) ) {
2014-11-07 11:05:56 -05:00
chooser . setCurrentDirectory ( defaultFile . getParentFile ( ) ) ;
}
}
2014-11-07 11:43:19 -05:00
if ( filter ! = null & & ! filter . acceptAny ( ) ) {
2015-09-15 03:04:36 -04:00
chooser . setFileFilter ( new javax . swing . filechooser . FileNameExtensionFilter ( truncateText ( filter . toString ( ) , 80 ) , filter . extensions ( ) ) ) ;
2014-07-29 02:40:35 -04:00
}
2015-03-24 07:23:24 -04:00
if ( chooser . showOpenDialog ( getWindow ( evt . getSource ( ) ) ) = = JFileChooser . APPROVE_OPTION ) {
2014-07-29 02:40:35 -04:00
if ( chooser . getSelectedFiles ( ) . length > 0 )
return asList ( chooser . getSelectedFiles ( ) ) ;
if ( chooser . getSelectedFile ( ) ! = null )
return asList ( chooser . getSelectedFile ( ) ) ;
}
return asList ( new File [ 0 ] ) ;
2014-07-28 16:01:46 -04:00
}
2014-07-29 02:40:35 -04:00
@Override
2015-03-24 07:23:24 -04:00
public File showSaveDialogSelectFile ( boolean folderMode , File defaultFile , String title , ActionEvent evt ) {
2014-07-29 02:40:35 -04:00
JFileChooser chooser = new JFileChooser ( ) ;
2014-08-08 12:44:35 -04:00
chooser . setDialogTitle ( title ) ;
2014-07-29 02:40:35 -04:00
chooser . setMultiSelectionEnabled ( false ) ;
2014-07-29 04:43:54 -04:00
chooser . setFileSelectionMode ( folderMode ? JFileChooser . DIRECTORIES_ONLY : JFileChooser . FILES_AND_DIRECTORIES ) ;
chooser . setSelectedFile ( defaultFile ) ;
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
if ( chooser . showSaveDialog ( getWindow ( evt . getSource ( ) ) ) ! = JFileChooser . APPROVE_OPTION ) {
2014-07-29 02:40:35 -04:00
return null ;
}
return chooser . getSelectedFile ( ) ;
}
} ,
2014-07-28 16:01:46 -04:00
2014-07-29 02:40:35 -04:00
AWT {
2014-08-08 12:44:35 -04:00
2014-07-29 02:40:35 -04:00
@Override
2015-03-24 07:23:24 -04:00
public List < File > showLoadDialogSelectFiles ( boolean folderMode , boolean multiSelection , File defaultFile , ExtensionFileFilter filter , String title , ActionEvent evt ) {
FileDialog fileDialog = createFileDialog ( evt , title , FileDialog . LOAD , folderMode ) ;
2014-08-08 12:44:35 -04:00
fileDialog . setTitle ( title ) ;
2014-07-29 04:43:54 -04:00
fileDialog . setMultipleMode ( multiSelection ) ;
2014-11-07 11:05:56 -05:00
2014-07-29 04:43:54 -04:00
if ( defaultFile ! = null ) {
2014-08-08 12:44:35 -04:00
if ( folderMode & & defaultFile . isDirectory ( ) ) {
fileDialog . setDirectory ( defaultFile . getPath ( ) ) ;
2014-11-10 15:39:27 -05:00
} else if ( defaultFile . getParentFile ( ) ! = null & & defaultFile . getParentFile ( ) . isDirectory ( ) ) {
fileDialog . setDirectory ( defaultFile . getParentFile ( ) . getPath ( ) ) ;
2014-08-08 12:44:35 -04:00
fileDialog . setFile ( defaultFile . getName ( ) ) ;
}
2014-07-29 04:43:54 -04:00
}
2014-07-28 16:01:46 -04:00
2014-11-07 11:05:56 -05:00
if ( filter ! = null ) {
fileDialog . setFilenameFilter ( filter ) ;
}
2014-07-29 04:43:54 -04:00
fileDialog . setVisible ( true ) ;
2014-07-29 02:40:35 -04:00
return asList ( fileDialog . getFiles ( ) ) ;
}
@Override
2015-03-24 07:23:24 -04:00
public File showSaveDialogSelectFile ( boolean folderMode , File defaultFile , String title , ActionEvent evt ) {
FileDialog fileDialog = createFileDialog ( evt , title , FileDialog . SAVE , folderMode ) ;
2014-08-08 12:44:35 -04:00
fileDialog . setTitle ( title ) ;
2014-07-29 04:43:54 -04:00
fileDialog . setMultipleMode ( false ) ;
2014-07-29 02:40:35 -04:00
if ( defaultFile ! = null ) {
2014-12-29 06:47:26 -05:00
if ( defaultFile . getParentFile ( ) ! = null & & defaultFile . getParentFile ( ) . isDirectory ( ) ) {
2014-07-29 02:40:35 -04:00
fileDialog . setDirectory ( defaultFile . getParentFile ( ) . getPath ( ) ) ;
}
fileDialog . setFile ( defaultFile . getName ( ) ) ;
2014-07-28 16:01:46 -04:00
}
2014-07-29 04:43:54 -04:00
fileDialog . setVisible ( true ) ;
2014-07-29 02:40:35 -04:00
File [ ] files = fileDialog . getFiles ( ) ;
return files . length > 0 ? files [ 0 ] : null ;
}
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
public FileDialog createFileDialog ( ActionEvent evt , String title , int mode , boolean fileDialogForDirectories ) {
2014-07-29 04:43:54 -04:00
// By default, the AWT File Dialog lets you choose a file. Under certain circumstances, however, it may be proper for you to choose a directory instead. If that is the case, set this property to allow for directory selection in a file dialog.
2014-07-29 02:40:35 -04:00
System . setProperty ( " apple.awt.fileDialogForDirectories " , String . valueOf ( fileDialogForDirectories ) ) ;
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
if ( evt . getSource ( ) instanceof Frame ) {
return new FileDialog ( ( Frame ) evt . getSource ( ) , title , mode ) ;
2014-07-28 16:01:46 -04:00
}
2015-03-24 07:23:24 -04:00
if ( evt . getSource ( ) instanceof Dialog ) {
return new FileDialog ( ( Dialog ) evt . getSource ( ) , title , mode ) ;
2014-07-29 02:40:35 -04:00
}
Frame [ ] frames = Frame . getFrames ( ) ;
return new FileDialog ( frames . length > 0 ? frames [ 0 ] : null , title , mode ) ;
2014-07-28 16:01:46 -04:00
}
2014-07-29 05:33:19 -04:00
} ,
2014-11-07 08:26:54 -05:00
COCOA {
@Override
2015-03-24 07:23:24 -04:00
public List < File > showLoadDialogSelectFiles ( boolean folderMode , boolean multiSelection , File defaultFile , ExtensionFileFilter filter , String title , ActionEvent evt ) {
2014-11-07 08:26:54 -05:00
// directly use NSOpenPanel for via Objective-C bridge for FILES_AND_DIRECTORIES mode
if ( folderMode & & filter ! = null ) {
2015-05-07 13:01:11 -04:00
// call native NSOpenPanel openPanel via Objective-C bridge
return MacAppUtilities . NSOpenPanel_openPanel_runModal ( title , true , true , true , filter . acceptAny ( ) ? null : filter . extensions ( ) ) ;
2014-11-07 08:26:54 -05:00
}
// default to AWT implementation
2015-03-24 07:23:24 -04:00
return AWT . showLoadDialogSelectFiles ( folderMode , multiSelection , defaultFile , filter , title , evt ) ;
2014-11-07 08:26:54 -05:00
}
@Override
2015-03-24 07:23:24 -04:00
public File showSaveDialogSelectFile ( boolean folderMode , File defaultFile , String title , ActionEvent evt ) {
2014-11-07 08:26:54 -05:00
// default to AWT implementation
2015-03-24 07:23:24 -04:00
return AWT . showSaveDialogSelectFile ( folderMode , defaultFile , title , evt ) ;
2014-11-07 08:26:54 -05:00
}
} ,
2014-07-29 05:33:19 -04:00
JavaFX {
@Override
2015-03-24 07:23:24 -04:00
public List < File > showLoadDialogSelectFiles ( final boolean folderMode , final boolean multiSelection , final File defaultFile , final ExtensionFileFilter filter , final String title , final ActionEvent evt ) {
2014-07-29 05:33:19 -04:00
return runAndWait ( new Callable < List < File > > ( ) {
@Override
public List < File > call ( ) throws Exception {
2014-07-29 05:50:57 -04:00
// show DirectoryChooser
if ( folderMode ) {
javafx . stage . DirectoryChooser directoryChooser = new javafx . stage . DirectoryChooser ( ) ;
directoryChooser . setTitle ( title ) ;
2014-12-29 06:47:26 -05:00
if ( defaultFile ! = null & & defaultFile . isDirectory ( ) ) {
2014-07-29 05:50:57 -04:00
directoryChooser . setInitialDirectory ( defaultFile ) ;
}
File file = directoryChooser . showDialog ( null ) ;
if ( file ! = null )
return singletonList ( file ) ;
else
return emptyList ( ) ;
}
// show FileChooser
2014-07-29 05:33:19 -04:00
javafx . stage . FileChooser fileChooser = new javafx . stage . FileChooser ( ) ;
fileChooser . setTitle ( title ) ;
2014-11-07 11:43:19 -05:00
if ( filter ! = null & & ! filter . acceptAny ( ) ) {
2014-07-29 05:33:19 -04:00
String [ ] globFilter = filter . extensions ( ) ;
for ( int i = 0 ; i < globFilter . length ; i + + ) {
globFilter [ i ] = " *. " + globFilter [ i ] ;
}
fileChooser . getExtensionFilters ( ) . add ( new javafx . stage . FileChooser . ExtensionFilter ( filter . toString ( ) , globFilter ) ) ;
}
2014-11-10 15:39:27 -05:00
2014-07-29 05:33:19 -04:00
if ( defaultFile ! = null ) {
2014-11-10 15:39:27 -05:00
if ( defaultFile . getParentFile ( ) ! = null & & defaultFile . getParentFile ( ) . isDirectory ( ) ) {
2014-07-29 05:33:19 -04:00
fileChooser . setInitialDirectory ( defaultFile . getParentFile ( ) ) ;
2014-11-10 15:39:27 -05:00
fileChooser . setInitialFileName ( defaultFile . getName ( ) ) ;
2014-07-29 05:33:19 -04:00
}
}
if ( multiSelection ) {
List < File > files = fileChooser . showOpenMultipleDialog ( null ) ;
if ( files ! = null )
return files ;
} else {
File file = fileChooser . showOpenDialog ( null ) ;
if ( file ! = null )
return singletonList ( file ) ;
}
return emptyList ( ) ;
}
} ) ;
}
@Override
2015-03-24 07:23:24 -04:00
public File showSaveDialogSelectFile ( final boolean folderMode , final File defaultFile , final String title , final ActionEvent evt ) {
2014-07-29 05:33:19 -04:00
return runAndWait ( new Callable < File > ( ) {
@Override
public File call ( ) throws Exception {
javafx . stage . FileChooser fileChooser = new javafx . stage . FileChooser ( ) ;
fileChooser . setTitle ( title ) ;
if ( defaultFile ! = null ) {
2014-12-29 06:47:26 -05:00
if ( defaultFile . getParentFile ( ) ! = null & & defaultFile . getParentFile ( ) . isDirectory ( ) ) {
2014-07-29 05:33:19 -04:00
fileChooser . setInitialDirectory ( defaultFile . getParentFile ( ) ) ;
}
fileChooser . setInitialFileName ( defaultFile . getName ( ) ) ;
}
return fileChooser . showSaveDialog ( null ) ;
}
} ) ;
}
public < T > T runAndWait ( Callable < T > c ) {
try {
// run on FX Thread
FutureTask < T > task = new FutureTask < T > ( c ) ;
2016-08-10 15:54:27 -04:00
invokeJavaFX ( task ) ;
2014-07-29 05:33:19 -04:00
return task . get ( ) ;
} catch ( Exception e ) {
throw new RuntimeException ( e ) ;
}
}
2014-07-29 02:40:35 -04:00
} ;
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
public abstract List < File > showLoadDialogSelectFiles ( boolean folderMode , boolean multiSelection , File defaultFile , ExtensionFileFilter filter , String title , ActionEvent evt ) ;
2014-07-28 16:01:46 -04:00
2015-03-24 07:23:24 -04:00
public abstract File showSaveDialogSelectFile ( boolean folderMode , File defaultFile , String title , ActionEvent evt ) ;
2014-07-28 16:01:46 -04:00
}
}