Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allows adding files and folders via filechooser and drag and drop #51 #82

Merged
merged 4 commits into from
Nov 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 136 additions & 30 deletions src/main/java/nsusbloader/Controllers/GamesController.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package nsusbloader.Controllers;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
Expand All @@ -40,11 +41,18 @@

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class GamesController implements Initializable {

private static final String REGEX_ONLY_NSP = ".*\\.nsp$";
private static final String REGEX_ALLFILES_TINFOIL = ".*\\.(nsp$|xci$|nsz$|xcz$)";

@FXML
private AnchorPane usbNetPane;

Expand All @@ -60,7 +68,7 @@ public class GamesController implements Initializable {
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support)

@FXML
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
private Button selectNspBtn, selectSplitNspBtn, selectFolderBtn, uploadStopBtn;
private String previouslyOpenedPath;
private Region btnUpStopImage;
private ResourceBundle resourceBundle;
Expand Down Expand Up @@ -130,16 +138,18 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
switchThemeBtn.setGraphic(btnSwitchImage);
this.switchThemeBtn.setOnAction(e->switchTheme());


uploadStopBtn.setDisable(getSelectedProtocol().equals("TinFoil"));
selectNspBtn.setOnAction(e-> selectFilesBtnAction());
selectNspBtn.getStyleClass().add("buttonSelect");

selectFolderBtn.setOnAction(e-> selectFoldersBtnAction());
selectFolderBtn.getStyleClass().add("buttonSelect");
selectFolderBtn.setTooltip(new Tooltip(resourceBundle.getString("btn_OpenFolders_tooltip")));

selectSplitNspBtn.setOnAction(e-> selectSplitBtnAction());
selectSplitNspBtn.getStyleClass().add("buttonSelect");

uploadStopBtn.setOnAction(e-> uploadBtnAction());

selectNspBtn.getStyleClass().add("buttonSelect");
uploadStopBtn.setDisable(getSelectedProtocol().equals("TinFoil"));

this.btnUpStopImage = new Region();
btnUpStopImage.getStyleClass().add("regionUpload");
Expand Down Expand Up @@ -186,32 +196,111 @@ String getNsIp(){
return nsIpTextField.getText();
}

private boolean isGoldLeaf() {
return getSelectedProtocol().equals("GoldLeaf");
}

private boolean isTinfoil() {
return getSelectedProtocol().equals("TinFoil");
}

private boolean isNSPFileFilterForGL() {
return MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL();
}

private boolean isXciNszXczSupport() {
return MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport();
}

/**
* regex for selected program and selected file filter </br>
* tinfoil + xcinszxcz </br>
* tinfoil + nsponly </br>
* goldleaf </br>
* etc..
*/
private String getRegexForFiles() {
if (isTinfoil() && isXciNszXczSupport())
return REGEX_ALLFILES_TINFOIL;
else
return REGEX_ONLY_NSP;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle #33 should be:

else if (goldleafController.getNSPFileFilterForGL())) {
    return REGEX_ONLY_NSP;
}
else 
    return ".*";

// currently only tinfoil supports all filetypes
// everything else only supports nsp
// else if (isGoldLeaf())
// return REGEX_ONLY_NSP;
// else
}

/**
* Functionality for selecting NSP button.
* */
private void selectFilesBtnAction(){
List<File> filesList;
*/
private void selectFilesBtnAction() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("btn_OpenFile"));

fileChooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));

if (getSelectedProtocol().equals("TinFoil") && MediatorControl.getInstance().getContoller().getSettingsCtrlr().getTinfoilSettings().isXciNszXczSupport())
if (isTinfoil() && isXciNszXczSupport()) {
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP/XCI/NSZ/XCZ", "*.nsp", "*.xci", "*.nsz", "*.xcz"));
else if (getSelectedProtocol().equals("GoldLeaf") && (! MediatorControl.getInstance().getContoller().getSettingsCtrlr().getGoldleafSettings().getNSPFileFilterForGL()))
} else if (isGoldLeaf() && !isNSPFileFilterForGL()) {
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Any file", "*.*"),
new FileChooser.ExtensionFilter("NSP ROM", "*.nsp")
);
else
new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
} else {
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
}

filesList = fileChooser.showOpenMultipleDialog(usbNetPane.getScene().getWindow());
List<File> filesList = fileChooser.showOpenMultipleDialog(usbNetPane.getScene().getWindow());
if (filesList != null && !filesList.isEmpty()) {
tableFilesListController.setFiles(filesList);
uploadStopBtn.setDisable(false);
previouslyOpenedPath = filesList.get(0).getParent();
}
}

/**
* Functionality for selecting folders button.
* will scan all folders recursively for nsp-files
*/
private void selectFoldersBtnAction() {
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle(resourceBundle.getString("btn_OpenFolders"));
chooser.setInitialDirectory(new File(FilesHelper.getRealFolder(previouslyOpenedPath)));

File startFolder = chooser.showDialog(usbNetPane.getScene().getWindow());

performInBackgroundAndUpdate(() -> {
final List<File> allFiles = new ArrayList<>();
collectFiles(allFiles, startFolder, getRegexForFiles());
return allFiles;
}, (files) -> {
if (!files.isEmpty()) {
tableFilesListController.setFiles(files);
uploadStopBtn.setDisable(false);
previouslyOpenedPath = startFolder.getParent();
}
});
}

/**
* used to recursively walk all directories, every file will be added to the storage list
* @param storage used to hold files
* @param startFolder where to start
* @param regex for filenames
*/
private void collectFiles(List<File> storage, File startFolder, final String regex) {
if (startFolder.isDirectory()) {
File[] files = startFolder.listFiles();
if(files != null)
for (File f : files) {
if (f.isDirectory()) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle split-files should be if (f.isDirectory() && ! f.getName().toLowerCase().matches(regex))

collectFiles(storage, f, regex);
} else if (f.getName().toLowerCase().matches(regex)) {
storage.add(f);
}
}
}
}

/**
* Functionality for selecting Split NSP button.
* */
Expand Down Expand Up @@ -324,25 +413,27 @@ private void handleDragOver(DragEvent event){
* Drag-n-drop support (drop consumer)
* */
@FXML
private void handleDrop(DragEvent event){
List<File> filesDropped = event.getDragboard().getFiles();
SettingsController settingsController = MediatorControl.getInstance().getContoller().getSettingsCtrlr();
SettingsBlockTinfoilController tinfoilSettings = settingsController.getTinfoilSettings();
SettingsBlockGoldleafController goldleafController = settingsController.getGoldleafSettings();

if (getSelectedProtocol().equals("TinFoil") && tinfoilSettings.isXciNszXczSupport())
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches("(.*\\.nsp$)|(.*\\.xci$)|(.*\\.nsz$)|(.*\\.xcz$)"));
else if (getSelectedProtocol().equals("GoldLeaf") && (! goldleafController.getNSPFileFilterForGL()))
filesDropped.removeIf(file -> (file.isDirectory() && ! file.getName().toLowerCase().matches(".*\\.nsp$")));
else
filesDropped.removeIf(file -> ! file.getName().toLowerCase().matches(".*\\.nsp$"));
private void handleDrop(DragEvent event) {
final String regex = getRegexForFiles();

if ( ! filesDropped.isEmpty() )
tableFilesListController.setFiles(filesDropped);
List<File> files = event.getDragboard().getFiles();

event.setDropCompleted(true);
event.consume();
performInBackgroundAndUpdate(() -> {
List<File> allFiles = new ArrayList<>();
if (files != null && files.size() != 0) {
files.stream().filter(File::isDirectory).forEach(f -> collectFiles(allFiles, f, regex));
files.stream().filter(f -> f.getName().toLowerCase().matches(regex)).forEach(allFiles::add);
}
return allFiles;
}, allFiles -> {
if (!allFiles.isEmpty())
tableFilesListController.setFiles(allFiles);

event.setDropCompleted(true);
event.consume();
});
}

/**
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
* Called from mediator
Expand Down Expand Up @@ -384,6 +475,21 @@ public void disableUploadStopBtn(boolean disable){
else
uploadStopBtn.setDisable(false);
}

/**
* Utility function to perform a task in the background and pass the results to a task on the javafx-ui-thread
* @param background performed in background
* @param update performed with results on ui-thread
*/
private <T> void performInBackgroundAndUpdate(Supplier<T> background, Consumer<T> update) {
new Thread(() -> {
final T result = background.get();
Platform.runLater(() -> {
update.accept(result);
});
}).start();
}

/**
* Get 'Recent' path
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/GamesTab.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
<SVGPath content="M 8,0 C 6.8954305,0 6,0.8954305 6,2 v 16 c 0,1.1 0.89,2 2,2 h 12 c 1.104569,0 2,-0.895431 2,-2 V 2 C 22,0.90484721 21.089844,0 20,0 Z m 2.1,1.2 h 7.8 C 18,1.20208 18,1.2002604 18,1.3 v 0.1 c 0,0.095833 0,0.097917 -0.1,0.1 H 10.1 C 10,1.5057292 10,1.5036458 10,1.4 V 1.3 C 10,1.20026 10,1.1981771 10.1,1.2 Z M 8,2 h 12 c 0.303385,0 0.5,0.2044271 0.5,0.5 v 12 C 20.5,14.789959 20.29836,15 20,15 H 8 C 7.7044271,15 7.5,14.803385 7.5,14.5 V 2.5 C 7.5,2.2083333 7.7122396,2 8,2 Z M 2,4 v 18 c 0,1.104569 0.8954305,2 2,2 H 20 V 22 H 4 V 4 Z m 8,12 h 8 l -4,3 z" fill="#289de8" />
</graphic>
</Button>
<Button fx:id="selectFolderBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenFolders">
<graphic>
<SVGPath content="M 2.4003906,2 C 1.0683906,2 0,3.1125 0,4.5 v 15 c -1.7556433e-8,1.380871 1.0747547,2.500225 2.4003906,2.5 H 21.599609 C 22.925245,22.000225 24,20.880871 24,19.5 V 7 C 24,5.6125 22.919609,4.5 21.599609,4.5 H 12 L 9.5996094,2 Z" fill="#289de8" />
</graphic>
</Button>
<Button fx:id="selectSplitNspBtn" contentDisplay="TOP" mnemonicParsing="false" prefHeight="60.0" text="%btn_OpenSplitFile">
<graphic>
<SVGPath content="M 2.4003906 2 C 1.0683906 2 0 3.1125 0 4.5 L 0 19.5 A 2.4 2.5 0 0 0 2.4003906 22 L 21.599609 22 A 2.4 2.5 0 0 0 24 19.5 L 24 7 C 24 5.6125 22.919609 4.5 21.599609 4.5 L 12 4.5 L 9.5996094 2 L 2.4003906 2 z M 13.193359 10.962891 C 14.113498 10.962891 14.814236 11.348741 15.296875 12.123047 C 15.779514 12.89388 16.021484 13.935113 16.021484 15.244141 C 16.021484 16.556641 15.779514 17.598741 15.296875 18.373047 C 14.814236 19.14388 14.113498 19.529297 13.193359 19.529297 C 12.276693 19.529297 11.575955 19.14388 11.089844 18.373047 C 10.607205 17.598741 10.365234 16.556641 10.365234 15.244141 C 10.365234 13.935113 10.607205 12.89388 11.089844 12.123047 C 11.575955 11.348741 12.276693 10.962891 13.193359 10.962891 z M 19.589844 10.962891 C 20.509983 10.962891 21.21072 11.348741 21.693359 12.123047 C 22.175998 12.89388 22.417969 13.935113 22.417969 15.244141 C 22.417969 16.556641 22.175998 17.598741 21.693359 18.373047 C 21.21072 19.14388 20.509983 19.529297 19.589844 19.529297 C 18.673177 19.529297 17.970486 19.14388 17.484375 18.373047 C 17.001736 17.598741 16.761719 16.556641 16.761719 15.244141 C 16.761719 13.935113 17.001736 12.89388 17.484375 12.123047 C 17.970486 11.348741 18.673177 10.962891 19.589844 10.962891 z M 13.193359 11.769531 C 12.613498 11.769531 12.173177 12.092448 11.871094 12.738281 C 11.56901 13.380642 11.417969 14.195964 11.417969 15.185547 C 11.417969 15.411241 11.423611 15.655599 11.4375 15.916016 C 11.451389 16.176432 11.511068 16.528212 11.615234 16.972656 L 14.412109 12.591797 C 14.235026 12.26888 14.042318 12.052517 13.833984 11.941406 C 13.629123 11.826823 13.415582 11.769531 13.193359 11.769531 z M 19.589844 11.769531 C 19.009983 11.769531 18.567708 12.092448 18.265625 12.738281 C 17.963542 13.380642 17.8125 14.195964 17.8125 15.185547 C 17.8125 15.411241 17.820095 15.655599 17.833984 15.916016 C 17.847873 16.176432 17.907552 16.528212 18.011719 16.972656 L 20.808594 12.591797 C 20.63151 12.26888 20.438802 12.052517 20.230469 11.941406 C 20.025608 11.826823 19.812066 11.769531 19.589844 11.769531 z M 14.761719 13.556641 L 11.984375 17.962891 C 12.133681 18.216363 12.305556 18.406684 12.5 18.535156 C 12.694444 18.660156 12.91276 18.722656 13.152344 18.722656 C 13.812066 18.722656 14.280816 18.355252 14.558594 17.619141 C 14.836372 16.879557 14.974609 16.059462 14.974609 15.160156 C 14.974609 14.604601 14.90408 14.07053 14.761719 13.556641 z M 21.15625 13.556641 L 18.380859 17.962891 C 18.530165 18.216363 18.70204 18.406684 18.896484 18.535156 C 19.090929 18.660156 19.307292 18.722656 19.546875 18.722656 C 20.206597 18.722656 20.675347 18.355252 20.953125 17.619141 C 21.230903 16.879557 21.371094 16.059462 21.371094 15.160156 C 21.371094 14.604601 21.298611 14.07053 21.15625 13.556641 z" fill="#289de8" />
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/locale.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
btn_OpenFile=Select files
btn_OpenFolders=Select folder
btn_Upload=Upload to NS
btn_OpenFolders_tooltip=Select a folder to be scanned.\nThis folder and all of its subfolders will be scanned.\nAll matching files will be added to the list.
tab3_Txt_EnteredAsMsg1=You have been entered as:
tab3_Txt_EnteredAsMsg2=You should be root or have configured 'udev' rules for this user to avoid any issues.
tab3_Txt_FilesToUploadTitle=Files to upload:
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/locale_de_DE.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
btn_OpenFile=.NSP Dateien ausw\u00E4hlen
btn_OpenFolders=Ordner ausw\u00E4hlen
btn_Upload=Hochladen zu NS
btn_OpenFolders_tooltip=W\u00E4hle einen Ordner aus.\nDieser Ordner und alle seine Unterordner werden durchsucht.\nAlle passenden Dateien werden dann zur Liste hinzugef\u00FCgt.
tab3_Txt_EnteredAsMsg1=Du wurdest eingelassen als:
tab3_Txt_EnteredAsMsg2=Du brauchst root oder konfigurierte 'udev'-Regeln um Probleme zu vermeiden.
tab3_Txt_FilesToUploadTitle=Dateien zum Hochladen:
Expand Down Expand Up @@ -42,6 +44,7 @@ tab2_Cb_AllowXciNszXcz=Erlaube XCI- NSZ- XCZ-Dateien-Verwendung f\u00FCr Tinfoil
tab2_Lbl_AllowXciNszXczDesc=Von einigen Drittanbietern verwendet, welche XCI/NSZ/XCZ unterst\u00FCtzen, nutzt Tinfoil Transfer Protocol. Nicht \u00E4ndern, wenn unsicher.
tab2_Lbl_Language=Sprache
windowBodyRestartToApplyLang=Bitte die Applikation neustarten um die Einstellungen zu \u00FCbernehmen.
btn_OpenSplitFile=Split-NSP ausw�hlen
tab2_Cb_GLshowNspOnly=Nur *.nsp in GoldLeaf zeigen.
btn_Cancel=Abbrechen

2 changes: 2 additions & 0 deletions src/main/resources/locale_en_US.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
btn_OpenFile=Select files
btn_OpenFolders=Select folder
btn_Upload=Upload to NS
btn_OpenFolders_tooltip=Select a folder to be scanned.\nThis folder and all of its subfolders will be scanned.\nAll matching files will be added to the list.
tab3_Txt_EnteredAsMsg1=You have been entered as:
tab3_Txt_EnteredAsMsg2=You should be root or have configured 'udev' rules for this user to avoid any issues.
tab3_Txt_FilesToUploadTitle=Files to upload:
Expand Down