A lot of small updates. Finishing split-merge functions.
This commit is contained in:
parent
ca061cd1f2
commit
3d3fb56f9e
16 changed files with 416 additions and 266 deletions
|
@ -3,6 +3,7 @@ package nsusbloader.COM.NET;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import nsusbloader.NSLDataTypes.EFileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
import nsusbloader.ModelControllers.LogPrinter;
|
import nsusbloader.ModelControllers.LogPrinter;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
import nsusbloader.COM.Helpers.NSSplitReader;
|
import nsusbloader.COM.Helpers.NSSplitReader;
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
|
||||||
else
|
else
|
||||||
this.extras = "";
|
this.extras = "";
|
||||||
this.switchIP = switchIP;
|
this.switchIP = switchIP;
|
||||||
this.logPrinter = new LogPrinter();
|
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
|
||||||
this.nspMap = new HashMap<>();
|
this.nspMap = new HashMap<>();
|
||||||
this.nspFileSizes = new HashMap<>();
|
this.nspFileSizes = new HashMap<>();
|
||||||
// Filter and remove empty/incorrect split-files
|
// Filter and remove empty/incorrect split-files
|
||||||
|
|
|
@ -3,6 +3,7 @@ package nsusbloader.COM.USB;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import nsusbloader.ModelControllers.LogPrinter;
|
import nsusbloader.ModelControllers.LogPrinter;
|
||||||
import nsusbloader.NSLDataTypes.EFileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
import org.usb4java.*;
|
import org.usb4java.*;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ public class UsbCommunications extends Task<Void> {
|
||||||
this.nspMap = new LinkedHashMap<>();
|
this.nspMap = new LinkedHashMap<>();
|
||||||
for (File f: nspList)
|
for (File f: nspList)
|
||||||
nspMap.put(f.getName(), f);
|
nspMap.put(f.getName(), f);
|
||||||
this.logPrinter = new LogPrinter();
|
this.logPrinter = new LogPrinter(EModule.USB_NET_TRANSFERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@ import javafx.concurrent.Task;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.stage.DirectoryChooser;
|
import javafx.stage.DirectoryChooser;
|
||||||
|
@ -14,6 +15,7 @@ import nsusbloader.AppPreferences;
|
||||||
import nsusbloader.COM.NET.NETCommunications;
|
import nsusbloader.COM.NET.NETCommunications;
|
||||||
import nsusbloader.COM.USB.UsbCommunications;
|
import nsusbloader.COM.USB.UsbCommunications;
|
||||||
import nsusbloader.MediatorControl;
|
import nsusbloader.MediatorControl;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.ServiceWindow;
|
import nsusbloader.ServiceWindow;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -25,6 +27,8 @@ import java.util.ResourceBundle;
|
||||||
public class FrontController implements Initializable {
|
public class FrontController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private Pane specialPane;
|
private Pane specialPane;
|
||||||
|
@FXML
|
||||||
|
private AnchorPane usbNetPane;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
|
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
|
||||||
|
@ -35,7 +39,7 @@ public class FrontController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private Button switchThemeBtn;
|
private Button switchThemeBtn;
|
||||||
@FXML
|
@FXML
|
||||||
public NSTableViewController tableFilesListController; // Accessible from Mediator
|
public NSTableViewController tableFilesListController; // Accessible from Mediator (for drag-n-drop support)
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
|
private Button selectNspBtn, selectSplitNspBtn, uploadStopBtn;
|
||||||
|
@ -167,7 +171,7 @@ public class FrontController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************************************/
|
/*-****************************************************************************************************************-*/
|
||||||
/**
|
/**
|
||||||
* Functionality for selecting NSP button.
|
* Functionality for selecting NSP button.
|
||||||
* */
|
* */
|
||||||
|
@ -290,30 +294,30 @@ public class FrontController implements Initializable {
|
||||||
* Called from mediator
|
* Called from mediator
|
||||||
* TODO: remove shitcoding practices
|
* TODO: remove shitcoding practices
|
||||||
* */
|
* */
|
||||||
public void notifyTransmissionStarted(boolean isTransmissionStarted){
|
public void notifyTransmThreadStarted(boolean isActive, EModule type){
|
||||||
if (isTransmissionStarted) {
|
if (! type.equals(EModule.USB_NET_TRANSFERS)){
|
||||||
|
usbNetPane.setDisable(isActive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isActive) {
|
||||||
selectNspBtn.setDisable(true);
|
selectNspBtn.setDisable(true);
|
||||||
selectSplitNspBtn.setDisable(true);
|
selectSplitNspBtn.setDisable(true);
|
||||||
uploadStopBtn.setOnAction(e-> stopBtnAction());
|
btnUpStopImage.getStyleClass().clear();
|
||||||
|
|
||||||
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
|
|
||||||
|
|
||||||
btnUpStopImage.getStyleClass().remove("regionUpload");
|
|
||||||
btnUpStopImage.getStyleClass().add("regionStop");
|
btnUpStopImage.getStyleClass().add("regionStop");
|
||||||
|
|
||||||
|
uploadStopBtn.setOnAction(e-> stopBtnAction());
|
||||||
|
uploadStopBtn.setText(resourceBundle.getString("btn_Stop"));
|
||||||
uploadStopBtn.getStyleClass().remove("buttonUp");
|
uploadStopBtn.getStyleClass().remove("buttonUp");
|
||||||
uploadStopBtn.getStyleClass().add("buttonStop");
|
uploadStopBtn.getStyleClass().add("buttonStop");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectNspBtn.setDisable(false);
|
selectNspBtn.setDisable(false);
|
||||||
selectSplitNspBtn.setDisable(false);
|
selectSplitNspBtn.setDisable(false);
|
||||||
uploadStopBtn.setOnAction(e-> uploadBtnAction());
|
btnUpStopImage.getStyleClass().clear();
|
||||||
|
|
||||||
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
|
|
||||||
|
|
||||||
btnUpStopImage.getStyleClass().remove("regionStop");
|
|
||||||
btnUpStopImage.getStyleClass().add("regionUpload");
|
btnUpStopImage.getStyleClass().add("regionUpload");
|
||||||
|
|
||||||
|
uploadStopBtn.setOnAction(e-> uploadBtnAction());
|
||||||
|
uploadStopBtn.setText(resourceBundle.getString("btn_Upload"));
|
||||||
uploadStopBtn.getStyleClass().remove("buttonStop");
|
uploadStopBtn.getStyleClass().remove("buttonStop");
|
||||||
uploadStopBtn.getStyleClass().add("buttonUp");
|
uploadStopBtn.getStyleClass().add("buttonUp");
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,10 @@ public class NSLMainController implements Initializable {
|
||||||
public FrontController getFrontCtrlr(){
|
public FrontController getFrontCtrlr(){
|
||||||
return FrontTabController;
|
return FrontTabController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SplitMergeController getSmCtrlr(){
|
||||||
|
return SplitMergeTabController;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Save preferences before exit
|
* Save preferences before exit
|
||||||
* */
|
* */
|
||||||
|
|
|
@ -3,15 +3,14 @@ package nsusbloader.Controllers;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.RadioButton;
|
|
||||||
import javafx.scene.control.ToggleGroup;
|
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.DirectoryChooser;
|
import javafx.stage.DirectoryChooser;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import nsusbloader.AppPreferences;
|
import nsusbloader.AppPreferences;
|
||||||
import nsusbloader.MediatorControl;
|
import nsusbloader.MediatorControl;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.ServiceWindow;
|
import nsusbloader.ServiceWindow;
|
||||||
import nsusbloader.Utilities.SplitMergeTool;
|
import nsusbloader.Utilities.SplitMergeTool;
|
||||||
|
|
||||||
|
@ -22,6 +21,9 @@ import java.util.ResourceBundle;
|
||||||
public class SplitMergeController implements Initializable {
|
public class SplitMergeController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private ToggleGroup splitMergeTogGrp;
|
private ToggleGroup splitMergeTogGrp;
|
||||||
|
@FXML
|
||||||
|
private VBox smToolPane;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private RadioButton splitRad, mergeRad;
|
private RadioButton splitRad, mergeRad;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -31,16 +33,23 @@ public class SplitMergeController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private Label fileFolderLabelLbl,
|
private Label fileFolderLabelLbl,
|
||||||
fileFolderActualPathLbl,
|
fileFolderActualPathLbl,
|
||||||
saveToPathLbl;
|
saveToPathLbl,
|
||||||
|
statusLbl;
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
private Region convertRegion;
|
private Region convertRegion;
|
||||||
|
private Task<Boolean> smTask;
|
||||||
|
private Thread smThread;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
convertRegion = new Region();
|
convertRegion = new Region();
|
||||||
convertBtn.setGraphic(convertRegion);
|
convertBtn.setGraphic(convertRegion);
|
||||||
|
|
||||||
splitRad.setOnAction((actionEvent -> {
|
splitRad.setOnAction((actionEvent -> {
|
||||||
|
statusLbl.setText("");
|
||||||
convertRegion.getStyleClass().clear();
|
convertRegion.getStyleClass().clear();
|
||||||
convertRegion.getStyleClass().add("regionSplitToOne");
|
convertRegion.getStyleClass().add("regionSplitToOne");
|
||||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
|
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_File"));
|
||||||
|
@ -49,6 +58,7 @@ public class SplitMergeController implements Initializable {
|
||||||
convertBtn.setDisable(true);
|
convertBtn.setDisable(true);
|
||||||
}));
|
}));
|
||||||
mergeRad.setOnAction((actionEvent -> {
|
mergeRad.setOnAction((actionEvent -> {
|
||||||
|
statusLbl.setText("");
|
||||||
convertRegion.getStyleClass().clear();
|
convertRegion.getStyleClass().clear();
|
||||||
convertRegion.getStyleClass().add("regionOneToSplit");
|
convertRegion.getStyleClass().add("regionOneToSplit");
|
||||||
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
|
fileFolderLabelLbl.setText(resourceBundle.getString("tabSplMrg_Txt_Folder"));
|
||||||
|
@ -74,6 +84,7 @@ public class SplitMergeController implements Initializable {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
selectFileFolderBtn.setOnAction(actionEvent -> {
|
selectFileFolderBtn.setOnAction(actionEvent -> {
|
||||||
|
statusLbl.setText("");
|
||||||
if (splitRad.isSelected()) {
|
if (splitRad.isSelected()) {
|
||||||
FileChooser fc = new FileChooser();
|
FileChooser fc = new FileChooser();
|
||||||
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
fc.setTitle(resourceBundle.getString("tabSplMrg_Btn_SelectFile"));
|
||||||
|
@ -102,51 +113,75 @@ public class SplitMergeController implements Initializable {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
convertBtn.setOnAction(actionEvent -> {
|
convertBtn.setOnAction(actionEvent -> setConvertBtnAction());
|
||||||
if (MediatorControl.getInstance().getTransferActive()) {
|
|
||||||
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), resourceBundle.getString("windowBodyPleaseFinishTransfersFirst"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitRad.isSelected()){
|
|
||||||
updateProcess(true);
|
|
||||||
Task<Void> task = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
|
||||||
task.setOnSucceeded(workerStateEvent -> this.updateProcess(false));
|
|
||||||
Thread thread = new Thread(task);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
updateProcess(true);
|
|
||||||
Task<Void> task = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
|
||||||
task.setOnSucceeded(workerStateEvent -> this.updateProcess(false));
|
|
||||||
Thread thread = new Thread(task);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProcess(boolean isStart){
|
public void notifySmThreadStarted(boolean isStart, EModule type){
|
||||||
|
if (! type.equals(EModule.SPLIT_MERGE_TOOL)){
|
||||||
|
smToolPane.setDisable(isStart);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (isStart){
|
if (isStart){
|
||||||
MediatorControl.getInstance().getContoller().logArea.clear();
|
MediatorControl.getInstance().getContoller().logArea.clear();
|
||||||
MediatorControl.getInstance().setTransferActive(true); // TODO: remove & rewrite to interrupt function
|
|
||||||
convertBtn.setDisable(true);// TODO: remove & rewrite to interrupt function
|
|
||||||
splitRad.setDisable(true);
|
splitRad.setDisable(true);
|
||||||
mergeRad.setDisable(true);
|
mergeRad.setDisable(true);
|
||||||
selectFileFolderBtn.setDisable(true);
|
selectFileFolderBtn.setDisable(true);
|
||||||
changeSaveToBtn.setDisable(true);
|
changeSaveToBtn.setDisable(true);
|
||||||
|
|
||||||
|
convertBtn.setOnAction(e -> stopBtnAction());
|
||||||
|
convertBtn.setText(resourceBundle.getString("btn_Stop"));
|
||||||
|
convertRegion.getStyleClass().clear();
|
||||||
|
convertRegion.getStyleClass().add("regionStop");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MediatorControl.getInstance().setTransferActive(false);
|
|
||||||
convertBtn.setDisable(false);// TODO: remove & rewrite to interrupt function
|
|
||||||
splitRad.setDisable(false);
|
splitRad.setDisable(false);
|
||||||
mergeRad.setDisable(false);
|
mergeRad.setDisable(false);
|
||||||
selectFileFolderBtn.setDisable(false);
|
selectFileFolderBtn.setDisable(false);
|
||||||
changeSaveToBtn.setDisable(false);
|
changeSaveToBtn.setDisable(false);
|
||||||
|
|
||||||
|
convertBtn.setOnAction(e -> setConvertBtnAction());
|
||||||
|
convertBtn.setText(resourceBundle.getString("tabSplMrg_Btn_Convert"));
|
||||||
|
convertRegion.getStyleClass().clear();
|
||||||
|
if (splitRad.isSelected())
|
||||||
|
convertRegion.getStyleClass().add("regionSplitToOne");
|
||||||
|
else
|
||||||
|
convertRegion.getStyleClass().add("regionOneToSplit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's button listener when convert-process in progress
|
||||||
|
* */
|
||||||
|
private void stopBtnAction(){
|
||||||
|
if (smThread != null && smThread.isAlive())
|
||||||
|
smTask.cancel(false);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* It's button listener when convert-process NOT in progress
|
||||||
|
* */
|
||||||
|
private void setConvertBtnAction(){
|
||||||
|
if (MediatorControl.getInstance().getTransferActive()) {
|
||||||
|
ServiceWindow.getErrorNotification(resourceBundle.getString("windowTitleError"), resourceBundle.getString("windowBodyPleaseFinishTransfersFirst"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitRad.isSelected())
|
||||||
|
smTask = SplitMergeTool.splitFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
||||||
|
else
|
||||||
|
smTask = SplitMergeTool.mergeFile(fileFolderActualPathLbl.getText(), saveToPathLbl.getText());
|
||||||
|
smTask.setOnCancelled(event -> statusLbl.setText(resourceBundle.getString("failure_txt")));
|
||||||
|
smTask.setOnSucceeded(event -> {
|
||||||
|
if (smTask.getValue())
|
||||||
|
statusLbl.setText(resourceBundle.getString("done_txt"));
|
||||||
|
else
|
||||||
|
statusLbl.setText(resourceBundle.getString("failure_txt"));
|
||||||
|
});
|
||||||
|
smThread = new Thread(smTask);
|
||||||
|
smThread.setDaemon(true);
|
||||||
|
smThread.start();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Save application settings on exit
|
||||||
|
* */
|
||||||
public void updatePreferencesOnExit(){
|
public void updatePreferencesOnExit(){
|
||||||
if (splitRad.isSelected())
|
if (splitRad.isSelected())
|
||||||
AppPreferences.getInstance().setSplitMergeType(0);
|
AppPreferences.getInstance().setSplitMergeType(0);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package nsusbloader;
|
package nsusbloader;
|
||||||
|
|
||||||
import nsusbloader.Controllers.NSLMainController;
|
import nsusbloader.Controllers.NSLMainController;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class MediatorControl {
|
public class MediatorControl {
|
||||||
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
|
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
|
||||||
private NSLMainController applicationController;
|
private NSLMainController mainCtrler;
|
||||||
|
|
||||||
public static MediatorControl getInstance(){
|
public static MediatorControl getInstance(){
|
||||||
return MediatorControlHold.INSTANCE;
|
return MediatorControlHold.INSTANCE;
|
||||||
|
@ -16,13 +17,14 @@ public class MediatorControl {
|
||||||
private static final MediatorControl INSTANCE = new MediatorControl();
|
private static final MediatorControl INSTANCE = new MediatorControl();
|
||||||
}
|
}
|
||||||
public void setController(NSLMainController controller){
|
public void setController(NSLMainController controller){
|
||||||
this.applicationController = controller;
|
this.mainCtrler = controller;
|
||||||
}
|
}
|
||||||
public NSLMainController getContoller(){ return this.applicationController; }
|
public NSLMainController getContoller(){ return this.mainCtrler; }
|
||||||
|
|
||||||
public synchronized void setTransferActive(boolean state) {
|
public synchronized void setBgThreadActive(boolean isActive, EModule appModuleType) {
|
||||||
isTransferActive.set(state);
|
isTransferActive.set(isActive);
|
||||||
applicationController.getFrontCtrlr().notifyTransmissionStarted(state);
|
mainCtrler.getFrontCtrlr().notifyTransmThreadStarted(isActive, appModuleType);
|
||||||
|
mainCtrler.getSmCtrlr().notifySmThreadStarted(isActive, appModuleType);
|
||||||
}
|
}
|
||||||
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
|
public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package nsusbloader.ModelControllers;
|
package nsusbloader.ModelControllers;
|
||||||
|
|
||||||
import nsusbloader.NSLDataTypes.EFileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -14,11 +15,11 @@ public class LogPrinter {
|
||||||
private BlockingQueue<Double> progressQueue;
|
private BlockingQueue<Double> progressQueue;
|
||||||
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
|
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
|
||||||
|
|
||||||
public LogPrinter(){
|
public LogPrinter(EModule whoIsAsking){
|
||||||
this.msgQueue = new LinkedBlockingQueue<>();
|
this.msgQueue = new LinkedBlockingQueue<>();
|
||||||
this.progressQueue = new LinkedBlockingQueue<>();
|
this.progressQueue = new LinkedBlockingQueue<>();
|
||||||
this.statusMap = new HashMap<>();
|
this.statusMap = new HashMap<>();
|
||||||
this.msgConsumer = new MessagesConsumer(this.msgQueue, this.progressQueue, this.statusMap);
|
this.msgConsumer = new MessagesConsumer(whoIsAsking, this.msgQueue, this.progressQueue, this.statusMap);
|
||||||
this.msgConsumer.start();
|
this.msgConsumer.start();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +43,8 @@ public class LogPrinter {
|
||||||
default:
|
default:
|
||||||
msgQueue.put(message);
|
msgQueue.put(message);
|
||||||
}
|
}
|
||||||
}catch (InterruptedException ie){
|
}
|
||||||
|
catch (InterruptedException ie){
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import javafx.scene.control.TextArea;
|
||||||
import nsusbloader.Controllers.NSTableViewController;
|
import nsusbloader.Controllers.NSTableViewController;
|
||||||
import nsusbloader.MediatorControl;
|
import nsusbloader.MediatorControl;
|
||||||
import nsusbloader.NSLDataTypes.EFileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -20,10 +21,12 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
private final ProgressBar progressBar;
|
private final ProgressBar progressBar;
|
||||||
private final HashMap<String, EFileStatus> statusMap;
|
private final HashMap<String, EFileStatus> statusMap;
|
||||||
private final NSTableViewController tableViewController;
|
private final NSTableViewController tableViewController;
|
||||||
|
private final EModule appModuleType;
|
||||||
|
|
||||||
private boolean isInterrupted;
|
private boolean isInterrupted;
|
||||||
|
|
||||||
MessagesConsumer(BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
|
MessagesConsumer(EModule appModuleType, BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
|
||||||
|
this.appModuleType = appModuleType;
|
||||||
this.isInterrupted = false;
|
this.isInterrupted = false;
|
||||||
|
|
||||||
this.msgQueue = msgQueue;
|
this.msgQueue = msgQueue;
|
||||||
|
@ -38,7 +41,7 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
progressBar.setProgress(0.0);
|
progressBar.setProgress(0.0);
|
||||||
|
|
||||||
progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
|
progressBar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
|
||||||
MediatorControl.getInstance().setTransferActive(true);
|
MediatorControl.getInstance().setBgThreadActive(true, appModuleType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +63,7 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
|
if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
|
||||||
MediatorControl.getInstance().setTransferActive(false);
|
MediatorControl.getInstance().setBgThreadActive(false, appModuleType);
|
||||||
progressBar.setProgress(0.0);
|
progressBar.setProgress(0.0);
|
||||||
|
|
||||||
if (statusMap.size() > 0)
|
if (statusMap.size() > 0)
|
||||||
|
|
7
src/main/java/nsusbloader/NSLDataTypes/EModule.java
Normal file
7
src/main/java/nsusbloader/NSLDataTypes/EModule.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package nsusbloader.NSLDataTypes;
|
||||||
|
|
||||||
|
public enum EModule {
|
||||||
|
USB_NET_TRANSFERS,
|
||||||
|
SPLIT_MERGE_TOOL,
|
||||||
|
RCM
|
||||||
|
}
|
|
@ -2,205 +2,284 @@ package nsusbloader.Utilities;
|
||||||
|
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import nsusbloader.ModelControllers.LogPrinter;
|
import nsusbloader.ModelControllers.LogPrinter;
|
||||||
|
import nsusbloader.NSLDataTypes.EModule;
|
||||||
import nsusbloader.NSLDataTypes.EMsgType;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class SplitMergeTool {
|
public class SplitMergeTool {
|
||||||
// TODO: ADD ABILITY TO INTERRUPT PROCESS
|
|
||||||
|
|
||||||
public static Task<Void> splitFile(String filePath, String saveToPath){
|
public static Task<Boolean> splitFile(String filePath, String saveToPath){
|
||||||
LogPrinter logPrinter = new LogPrinter();
|
return new SplitTask(filePath, saveToPath);
|
||||||
return new Task<Void>() {
|
|
||||||
@Override
|
|
||||||
protected Void call() {
|
|
||||||
File file = new File(filePath);
|
|
||||||
File folder = new File(saveToPath+File.separator+"!_"+file.getName());
|
|
||||||
|
|
||||||
logPrinter.print("Split file: "+filePath, EMsgType.INFO);
|
|
||||||
|
|
||||||
for (int i = 0; i < 50; i++){
|
|
||||||
if (! folder.mkdir()){
|
|
||||||
if (folder.exists()){
|
|
||||||
logPrinter.print("Trying to create a good new folder...", EMsgType.WARNING);
|
|
||||||
folder = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else { // folder not created and not exists - return
|
|
||||||
logPrinter.print("Folder "+folder.getAbsolutePath()+" could not be created. Not enough rights or something like that?", EMsgType.FAIL);
|
|
||||||
logPrinter.close();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logPrinter.print("Save results to: "+folder.getAbsolutePath(), EMsgType.INFO);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
|
||||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
|
||||||
|
|
||||||
BufferedOutputStream fragmentBos;
|
|
||||||
|
|
||||||
long counter;
|
|
||||||
|
|
||||||
long originalFileLen = file.length();
|
|
||||||
|
|
||||||
double chunkPercent = (4194240.0 / (originalFileLen / 100.0) / 100.0);
|
|
||||||
long totalSizeCnt = 0;
|
|
||||||
|
|
||||||
byte[] chunk;
|
|
||||||
int readBytesCnt;
|
|
||||||
|
|
||||||
main_loop:
|
|
||||||
for (int i = 0; ; i++){
|
|
||||||
fragmentBos = new BufferedOutputStream(
|
|
||||||
new FileOutputStream(new File(folder.getAbsolutePath()+File.separator+String.format("%02d", i)))
|
|
||||||
);
|
|
||||||
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
while (counter < 1024){ // 0xffff0000 total
|
|
||||||
chunk = new byte[4194240];
|
|
||||||
|
|
||||||
if ((readBytesCnt = bis.read(chunk)) < 4194240){
|
|
||||||
if (readBytesCnt > 0)
|
|
||||||
fragmentBos.write(chunk, 0, readBytesCnt);
|
|
||||||
fragmentBos.close();
|
|
||||||
logPrinter.updateProgress(1.0);
|
|
||||||
break main_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragmentBos.write(chunk);
|
|
||||||
|
|
||||||
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
|
||||||
counter++; // NOTE: here we have some redundancy of variables. It has to be fixed one day.
|
|
||||||
totalSizeCnt++;
|
|
||||||
}
|
|
||||||
fragmentBos.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bis.close();
|
|
||||||
|
|
||||||
//=============== let's check what we have ==============
|
|
||||||
logPrinter.print("Original file size: "+originalFileLen, EMsgType.INFO);
|
|
||||||
long totalChunksSize = 0;
|
|
||||||
File[] chunkFileArr = folder.listFiles();
|
|
||||||
|
|
||||||
if (chunkFileArr == null) {
|
|
||||||
logPrinter.print("Unable to check results. It means that something went wrong.", EMsgType.FAIL);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Arrays.sort(chunkFileArr);
|
|
||||||
for (File chunkFile : chunkFileArr) {
|
|
||||||
logPrinter.print("Chunk " + chunkFile.getName() + " size: " + chunkFile.length(), EMsgType.INFO);
|
|
||||||
totalChunksSize += chunkFile.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
logPrinter.print("Total chunks size: " + totalChunksSize, EMsgType.INFO);
|
|
||||||
|
|
||||||
if (originalFileLen != totalChunksSize)
|
|
||||||
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
|
|
||||||
else
|
|
||||||
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
|
|
||||||
}
|
|
||||||
logPrinter.print("Split task complete!", EMsgType.INFO);
|
|
||||||
logPrinter.close();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: CHECK IF FILE WE'RE ABOUT TO CREATE IS EXISTS !!!
|
public static Task<Boolean> mergeFile(String filePath, String saveToPath){
|
||||||
// TODO: not here: Add RECENT on current session level selection of the 'Select file/select folder' ? Already done ?
|
return new MergeTask(filePath, saveToPath);
|
||||||
|
}
|
||||||
public static Task<Void> mergeFile(String filePath, String saveToPath){
|
}
|
||||||
LogPrinter logPrinter = new LogPrinter();
|
|
||||||
|
class SplitTask extends Task<Boolean>{
|
||||||
return new Task<Void>() {
|
|
||||||
@Override
|
private LogPrinter logPrinter;
|
||||||
protected Void call() {
|
private String saveToPath;
|
||||||
logPrinter.print("Merge file: "+filePath, EMsgType.INFO);
|
private String filePath;
|
||||||
|
|
||||||
File folder = new File(filePath);
|
SplitTask(String filePath, String saveToPath){
|
||||||
|
this.filePath = filePath;
|
||||||
long cnkTotalSize = 0;
|
this.saveToPath = saveToPath;
|
||||||
|
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
|
||||||
File[] chunkFiles = folder.listFiles((file, s) -> s.matches("^[0-9][0-9]$"));
|
}
|
||||||
|
|
||||||
if (chunkFiles == null){
|
@Override
|
||||||
logPrinter.print("Selected folder doesn't have any chunks. Nothing to do here.", EMsgType.FAIL);
|
protected Boolean call() {
|
||||||
logPrinter.close();
|
File file = new File(filePath);
|
||||||
return null;
|
File folder = new File(saveToPath+File.separator+"!_"+file.getName());
|
||||||
}
|
|
||||||
|
logPrinter.print("Split file: "+filePath, EMsgType.INFO);
|
||||||
Arrays.sort(chunkFiles);
|
|
||||||
|
for (int i = 0; ; i++){
|
||||||
logPrinter.print("Next files will be merged in following order: ", EMsgType.INFO);
|
if (this.isCancelled()){
|
||||||
for (File cnk : chunkFiles){
|
logPrinter.print("Split task interrupted!", EMsgType.PASS);
|
||||||
logPrinter.print(" "+cnk.getName(), EMsgType.INFO);
|
logPrinter.close();
|
||||||
cnkTotalSize += cnk.length();
|
return false;
|
||||||
}
|
}
|
||||||
|
if (! folder.mkdir()){
|
||||||
double chunkPercent = (4194240.0 / (cnkTotalSize / 100.0) / 100.0);
|
if (folder.exists()){
|
||||||
long totalSizeCnt = 0;
|
if (i >= 50){
|
||||||
|
logPrinter.print("Can't create new file.", EMsgType.FAIL);
|
||||||
File resultFile = new File(saveToPath+File.separator+"!_"+folder.getName());
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
|
}
|
||||||
try {
|
logPrinter.print("Trying to create a good new folder...", EMsgType.WARNING);
|
||||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile));
|
folder = new File(saveToPath+File.separator+"!_"+i+"_"+file.getName());
|
||||||
|
continue;
|
||||||
BufferedInputStream bis;
|
}
|
||||||
byte[] chunk;
|
else { // folder not created and not exists - return
|
||||||
int readBytesCnt;
|
logPrinter.print("Folder "+folder.getAbsolutePath()+" could not be created. Not enough rights or something like that?", EMsgType.FAIL);
|
||||||
|
logPrinter.close();
|
||||||
for (File cnk : chunkFiles){
|
return false;
|
||||||
bis = new BufferedInputStream(new FileInputStream(cnk));
|
}
|
||||||
while (true){
|
}
|
||||||
chunk = new byte[4194240];
|
logPrinter.print("Save results to: "+folder.getAbsolutePath(), EMsgType.INFO);
|
||||||
readBytesCnt = bis.read(chunk);
|
break;
|
||||||
|
}
|
||||||
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
|
||||||
totalSizeCnt++;
|
try{
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
||||||
if (readBytesCnt < 4194240){
|
|
||||||
if (readBytesCnt > 0)
|
BufferedOutputStream fragmentBos;
|
||||||
bos.write(chunk, 0, readBytesCnt);
|
|
||||||
break;
|
long counter;
|
||||||
}
|
|
||||||
|
long originalFileLen = file.length();
|
||||||
bos.write(chunk);
|
|
||||||
}
|
double chunkPercent = (4194240.0 / (originalFileLen / 100.0) / 100.0);
|
||||||
bis.close();
|
long totalSizeCnt = 0;
|
||||||
}
|
|
||||||
bos.close();
|
byte[] chunk;
|
||||||
//=============== let's check what we have ==============
|
int readBytesCnt;
|
||||||
long resultFileSize = resultFile.length();
|
|
||||||
logPrinter.print("Total chunks size: " + cnkTotalSize, EMsgType.INFO);
|
main_loop:
|
||||||
logPrinter.print("Merged file size: " + resultFileSize, EMsgType.INFO);
|
for (int i = 0; ; i++){
|
||||||
|
fragmentBos = new BufferedOutputStream(
|
||||||
if (cnkTotalSize != resultFileSize)
|
new FileOutputStream(new File(folder.getAbsolutePath()+File.separator+String.format("%02d", i)))
|
||||||
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
|
);
|
||||||
else
|
|
||||||
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
|
counter = 0;
|
||||||
}
|
|
||||||
catch (Exception e){
|
while (counter < 1024){ // 0xffff0000 total
|
||||||
e.printStackTrace();
|
|
||||||
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
|
if (this.isCancelled()){
|
||||||
}
|
fragmentBos.close();
|
||||||
|
bis.close();
|
||||||
logPrinter.print("Merge task complete!", EMsgType.INFO);
|
boolean isDeleted = folder.delete();
|
||||||
logPrinter.close();
|
File[] chArrToDel = folder.listFiles();
|
||||||
return null;
|
if (! isDeleted && chArrToDel != null){
|
||||||
}
|
isDeleted = true;
|
||||||
};
|
for (File chunkFile : chArrToDel)
|
||||||
|
isDeleted &= chunkFile.delete();
|
||||||
|
isDeleted &= folder.delete();
|
||||||
|
}
|
||||||
|
logPrinter.print("Split task interrupted and folder "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
|
||||||
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = new byte[4194240];
|
||||||
|
|
||||||
|
if ((readBytesCnt = bis.read(chunk)) < 4194240){
|
||||||
|
if (readBytesCnt > 0)
|
||||||
|
fragmentBos.write(chunk, 0, readBytesCnt);
|
||||||
|
fragmentBos.close();
|
||||||
|
logPrinter.updateProgress(1.0);
|
||||||
|
break main_loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentBos.write(chunk);
|
||||||
|
|
||||||
|
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
||||||
|
counter++; // NOTE: here we have some redundancy of variables. It has to be fixed one day.
|
||||||
|
totalSizeCnt++;
|
||||||
|
}
|
||||||
|
fragmentBos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bis.close();
|
||||||
|
|
||||||
|
//=============== let's check what we have ==============
|
||||||
|
logPrinter.print("Original file size: "+originalFileLen, EMsgType.INFO);
|
||||||
|
long totalChunksSize = 0;
|
||||||
|
File[] chunkFileArr = folder.listFiles();
|
||||||
|
|
||||||
|
if (chunkFileArr == null) {
|
||||||
|
logPrinter.print("Unable to check results. It means that something went wrong.", EMsgType.FAIL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Arrays.sort(chunkFileArr);
|
||||||
|
for (File chunkFile : chunkFileArr) {
|
||||||
|
logPrinter.print("Chunk " + chunkFile.getName() + " size: " + chunkFile.length(), EMsgType.INFO);
|
||||||
|
totalChunksSize += chunkFile.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
logPrinter.print("Total chunks size: " + totalChunksSize, EMsgType.INFO);
|
||||||
|
|
||||||
|
if (originalFileLen != totalChunksSize)
|
||||||
|
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
|
||||||
|
else
|
||||||
|
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
logPrinter.print("Split task complete!", EMsgType.INFO);
|
||||||
|
logPrinter.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MergeTask extends Task<Boolean> {
|
||||||
|
|
||||||
|
private LogPrinter logPrinter;
|
||||||
|
private String saveToPath;
|
||||||
|
private String filePath;
|
||||||
|
|
||||||
|
MergeTask(String filePath, String saveToPath) {
|
||||||
|
this.filePath = filePath;
|
||||||
|
this.saveToPath = saveToPath;
|
||||||
|
logPrinter = new LogPrinter(EModule.SPLIT_MERGE_TOOL);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected Boolean call() {
|
||||||
|
logPrinter.print("Merge file: "+filePath, EMsgType.INFO);
|
||||||
|
|
||||||
|
File folder = new File(filePath);
|
||||||
|
|
||||||
|
long cnkTotalSize = 0;
|
||||||
|
|
||||||
|
File[] chunkFiles = folder.listFiles((file, s) -> s.matches("^[0-9][0-9]$"));
|
||||||
|
|
||||||
|
if (chunkFiles == null){
|
||||||
|
logPrinter.print("Selected folder doesn't have any chunks. Nothing to do here.", EMsgType.FAIL);
|
||||||
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arrays.sort(chunkFiles);
|
||||||
|
|
||||||
|
logPrinter.print("Next files will be merged in following order: ", EMsgType.INFO);
|
||||||
|
for (File cnk : chunkFiles){
|
||||||
|
logPrinter.print(" "+cnk.getName(), EMsgType.INFO);
|
||||||
|
cnkTotalSize += cnk.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
double chunkPercent = (4194240.0 / (cnkTotalSize / 100.0) / 100.0);
|
||||||
|
long totalSizeCnt = 0;
|
||||||
|
|
||||||
|
File resultFile = new File(saveToPath+File.separator+"!_"+folder.getName());
|
||||||
|
//*******
|
||||||
|
for (int i = 0; ; i++){
|
||||||
|
if (this.isCancelled()){
|
||||||
|
logPrinter.print("Split task interrupted!", EMsgType.PASS);
|
||||||
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultFile.exists()){
|
||||||
|
if (i >= 50){
|
||||||
|
logPrinter.print("Can't create new file.", EMsgType.FAIL);
|
||||||
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logPrinter.print("Trying to create a good new file...", EMsgType.WARNING);
|
||||||
|
resultFile = new File(saveToPath+File.separator+"!_"+i+"_"+folder.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
logPrinter.print("Save results to: "+resultFile.getAbsolutePath(), EMsgType.INFO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//*******
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(resultFile));
|
||||||
|
|
||||||
|
BufferedInputStream bis;
|
||||||
|
byte[] chunk;
|
||||||
|
int readBytesCnt;
|
||||||
|
|
||||||
|
for (File cnk : chunkFiles){
|
||||||
|
bis = new BufferedInputStream(new FileInputStream(cnk));
|
||||||
|
while (true){
|
||||||
|
|
||||||
|
if (this.isCancelled()){
|
||||||
|
bos.close();
|
||||||
|
bis.close();
|
||||||
|
boolean isDeleted = resultFile.delete();
|
||||||
|
logPrinter.print("Split task interrupted and file "+(isDeleted?"deleted.":"is not deleted."), EMsgType.PASS);
|
||||||
|
logPrinter.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = new byte[4194240];
|
||||||
|
readBytesCnt = bis.read(chunk);
|
||||||
|
|
||||||
|
logPrinter.updateProgress(chunkPercent * totalSizeCnt);
|
||||||
|
totalSizeCnt++;
|
||||||
|
|
||||||
|
if (readBytesCnt < 4194240){
|
||||||
|
if (readBytesCnt > 0)
|
||||||
|
bos.write(chunk, 0, readBytesCnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bos.write(chunk);
|
||||||
|
}
|
||||||
|
bis.close();
|
||||||
|
}
|
||||||
|
bos.close();
|
||||||
|
//=============== let's check what we have ==============
|
||||||
|
long resultFileSize = resultFile.length();
|
||||||
|
logPrinter.print("Total chunks size: " + cnkTotalSize, EMsgType.INFO);
|
||||||
|
logPrinter.print("Merged file size: " + resultFileSize, EMsgType.INFO);
|
||||||
|
|
||||||
|
if (cnkTotalSize != resultFileSize){
|
||||||
|
logPrinter.print("Sizes are different! Do NOT use this file for installations!", EMsgType.FAIL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logPrinter.print("Sizes are the same! Split file should be good!", EMsgType.PASS);
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
logPrinter.print("Error: "+e.getMessage(), EMsgType.FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
logPrinter.print("Merge task complete!", EMsgType.INFO);
|
||||||
|
logPrinter.close();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.shape.SVGPath?>
|
<?import javafx.scene.shape.SVGPath?>
|
||||||
|
|
||||||
<AnchorPane xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.FrontController">
|
<AnchorPane fx:id="usbNetPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.FrontController">
|
||||||
<children>
|
<children>
|
||||||
<VBox layoutX="10.0" layoutY="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<VBox layoutX="10.0" layoutY="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<children>
|
<children>
|
||||||
|
|
|
@ -23,6 +23,16 @@
|
||||||
<SVGPath content="M21,19V17H8V19H21M21,13V11H8V13H21M8,7H21V5H8V7M4,5V7H6V5H4M3,5A1,1 0 0,1 4,4H6A1,1 0 0,1 7,5V7A1,1 0 0,1 6,8H4A1,1 0 0,1 3,7V5M4,11V13H6V11H4M3,11A1,1 0 0,1 4,10H6A1,1 0 0,1 7,11V13A1,1 0 0,1 6,14H4A1,1 0 0,1 3,13V11M4,17V19H6V17H4M3,17A1,1 0 0,1 4,16H6A1,1 0 0,1 7,17V19A1,1 0 0,1 6,20H4A1,1 0 0,1 3,19V17Z" />
|
<SVGPath content="M21,19V17H8V19H21M21,13V11H8V13H21M8,7H21V5H8V7M4,5V7H6V5H4M3,5A1,1 0 0,1 4,4H6A1,1 0 0,1 7,5V7A1,1 0 0,1 6,8H4A1,1 0 0,1 3,7V5M4,11V13H6V11H4M3,11A1,1 0 0,1 4,10H6A1,1 0 0,1 7,11V13A1,1 0 0,1 6,14H4A1,1 0 0,1 3,13V11M4,17V19H6V17H4M3,17A1,1 0 0,1 4,16H6A1,1 0 0,1 7,17V19A1,1 0 0,1 6,20H4A1,1 0 0,1 3,19V17Z" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
<Tab closable="false">
|
||||||
|
<content>
|
||||||
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
|
<fx:include fx:id="SplitMergeTab" source="SplitMergeTab.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" VBox.vgrow="ALWAYS" />
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
<graphic>
|
||||||
|
<SVGPath content="M 2.4003906 2 C 1.0683906 2 2.9605947e-16 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 9 5 L 13 8.5 L 9 12 L 9 10 L 6 10 L 6 7 L 9 7 L 9 5 z M 5 9 L 5 11 L 8 11 L 8 14 L 5 14 L 5 16 L 1 12.5 L 5 9 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" />
|
||||||
|
</graphic>
|
||||||
|
</Tab>
|
||||||
<Tab closable="false">
|
<Tab closable="false">
|
||||||
<content>
|
<content>
|
||||||
<fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" />
|
<fx:include fx:id="SettingsTab" source="SettingsTab.fxml" VBox.vgrow="ALWAYS" />
|
||||||
|
@ -47,16 +57,6 @@
|
||||||
<SVGPath content="M9,22A1,1 0 0,1 8,21V18H4A2,2 0 0,1 2,16V4C2,2.89 2.9,2 4,2H20A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H13.9L10.2,21.71C10,21.9 9.75,22 9.5,22V22H9M10,16V19.08L13.08,16H20V4H4V16H10M17,11H15V9H17V11M13,11H11V9H13V11M9,11H7V9H9V11Z" />
|
<SVGPath content="M9,22A1,1 0 0,1 8,21V18H4A2,2 0 0,1 2,16V4C2,2.89 2.9,2 4,2H20A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H13.9L10.2,21.71C10,21.9 9.75,22 9.5,22V22H9M10,16V19.08L13.08,16H20V4H4V16H10M17,11H15V9H17V11M13,11H11V9H13V11M9,11H7V9H9V11Z" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab closable="false">
|
|
||||||
<content>
|
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
|
||||||
<fx:include fx:id="SplitMergeTab" source="SplitMergeTab.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" VBox.vgrow="ALWAYS" />
|
|
||||||
</AnchorPane>
|
|
||||||
</content>
|
|
||||||
<graphic>
|
|
||||||
<SVGPath content="M 2.4003906 2 C 1.0683906 2 2.9605947e-16 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 9 5 L 13 8.5 L 9 12 L 9 10 L 6 10 L 6 7 L 9 7 L 9 5 z M 5 9 L 5 11 L 8 11 L 8 14 L 5 14 L 5 16 L 1 12.5 L 5 9 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" />
|
|
||||||
</graphic>
|
|
||||||
</Tab>
|
|
||||||
</tabs>
|
</tabs>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<ProgressBar fx:id="progressBar" prefWidth="Infinity" progress="0.0">
|
<ProgressBar fx:id="progressBar" prefWidth="Infinity" progress="0.0">
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox prefHeight="190.0" spacing="25.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.SplitMergeController">
|
<VBox fx:id="smToolPane" spacing="25.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.SplitMergeController">
|
||||||
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 40%, transparent 45%);" />
|
<Pane minHeight="-Infinity" prefHeight="10.0" style="-fx-background-color: linear-gradient(from 41px 34px to 50px 50px, reflect, #00c8fc 40%, transparent 45%);" />
|
||||||
<HBox alignment="CENTER">
|
<HBox alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
|
@ -52,6 +52,12 @@
|
||||||
<Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" />
|
<Button fx:id="changeSaveToBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_ChangeSaveToLocation" />
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
<HBox alignment="CENTER">
|
||||||
|
<children>
|
||||||
|
<Label fx:id="statusLbl" />
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
<Pane VBox.vgrow="ALWAYS" />
|
||||||
<HBox alignment="CENTER">
|
<HBox alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
<Button fx:id="convertBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_Convert" />
|
<Button fx:id="convertBtn" contentDisplay="TOP" mnemonicParsing="false" text="%tabSplMrg_Btn_Convert" />
|
||||||
|
|
|
@ -58,3 +58,5 @@ tabSplMrg_Btn_ChangeSaveToLocation=Change
|
||||||
tabSplMrg_Btn_Convert=Convert
|
tabSplMrg_Btn_Convert=Convert
|
||||||
windowTitleError=Error
|
windowTitleError=Error
|
||||||
windowBodyPleaseFinishTransfersFirst=Unable to split/merge files when application USB/Network process active. Please interrupt active transfers first.
|
windowBodyPleaseFinishTransfersFirst=Unable to split/merge files when application USB/Network process active. Please interrupt active transfers first.
|
||||||
|
done_txt=Done!
|
||||||
|
failure_txt=Failed
|
||||||
|
|
|
@ -58,4 +58,6 @@ tabSplMrg_Btn_SelectFile=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430
|
||||||
tabSplMrg_Btn_SelectFolder=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043F\u0430\u043F\u043A\u0443
|
tabSplMrg_Btn_SelectFolder=\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043F\u0430\u043F\u043A\u0443
|
||||||
windowTitleError=\u041E\u0448\u0438\u0431\u043A\u0430
|
windowTitleError=\u041E\u0448\u0438\u0431\u043A\u0430
|
||||||
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u044C \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0443 \u0438\u043B\u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u0432 \u0442\u043E\u0442 \u043C\u043E\u043C\u0435\u043D\u0442, \u043A\u043E\u0433\u0434\u0430 \u0430\u043A\u0442\u0438\u0432\u0435\u043D \u043F\u0440\u043E\u0446\u0435\u0441\u0441 USB \u0438\u043B\u0438 \u0421\u0435\u0442\u0435\u0432\u043E\u0439 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438. \u0421\u043F\u0435\u0440\u0432\u0430 \u043F\u0440\u0435\u0440\u0432\u0438\u0442\u0435 \u0435\u0433\u043E.
|
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u044C \u0440\u0430\u0437\u0431\u0438\u0432\u043A\u0443 \u0438\u043B\u0438 \u0441\u043B\u0438\u044F\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u0432 \u0442\u043E\u0442 \u043C\u043E\u043C\u0435\u043D\u0442, \u043A\u043E\u0433\u0434\u0430 \u0430\u043A\u0442\u0438\u0432\u0435\u043D \u043F\u0440\u043E\u0446\u0435\u0441\u0441 USB \u0438\u043B\u0438 \u0421\u0435\u0442\u0435\u0432\u043E\u0439 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438. \u0421\u043F\u0435\u0440\u0432\u0430 \u043F\u0440\u0435\u0440\u0432\u0438\u0442\u0435 \u0435\u0433\u043E.
|
||||||
|
done_txt=\u0413\u043E\u0442\u043E\u0432\u043E!
|
||||||
|
failure_txt=\u041D\u0435\u0443\u0434\u0430\u0447\u0430
|
||||||
|
|
||||||
|
|
|
@ -58,3 +58,5 @@ tabSplMrg_Btn_SelectFile=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u0444\u0430
|
||||||
tabSplMrg_Btn_SelectFolder=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043F\u0430\u043F\u043A\u0443
|
tabSplMrg_Btn_SelectFolder=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043F\u0430\u043F\u043A\u0443
|
||||||
windowTitleError=\u041F\u043E\u043C\u0438\u043B\u043A\u0430
|
windowTitleError=\u041F\u043E\u043C\u0438\u043B\u043A\u0430
|
||||||
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0434\u0456\u0439\u0441\u043D\u044E\u0432\u0430\u0442\u0438 \u0440\u043E\u0437\u0431\u0438\u0432\u043A\u0443 \u0430\u0431\u043E \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0443 \u0443 \u0442\u043E\u0439 \u043C\u043E\u043C\u0435\u043D\u0442, \u044F\u043A \u043F\u0440\u043E\u0446\u0435\u0441 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0447\u0435\u0440\u0435\u0437 USB \u0447\u0438 \u0442\u043E \u0447\u0435\u0440\u0435\u0437 \u043C\u0435\u0440\u0435\u0436\u0443 \u0449\u0435 \u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0439. \u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u0440\u0438\u043F\u0438\u043D\u0456\u0442\u044C \u0439\u043E\u0433\u043E.
|
windowBodyPleaseFinishTransfersFirst=\u041D\u0435\u043C\u043E\u0436\u043B\u0438\u0432\u043E \u0437\u0434\u0456\u0439\u0441\u043D\u044E\u0432\u0430\u0442\u0438 \u0440\u043E\u0437\u0431\u0438\u0432\u043A\u0443 \u0430\u0431\u043E \u0437'\u0454\u0434\u043D\u0430\u043D\u043D\u044F \u0444\u0430\u0439\u043B\u0443 \u0443 \u0442\u043E\u0439 \u043C\u043E\u043C\u0435\u043D\u0442, \u044F\u043A \u043F\u0440\u043E\u0446\u0435\u0441 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0456 \u0447\u0435\u0440\u0435\u0437 USB \u0447\u0438 \u0442\u043E \u0447\u0435\u0440\u0435\u0437 \u043C\u0435\u0440\u0435\u0436\u0443 \u0449\u0435 \u0430\u043A\u0442\u0438\u0432\u043D\u0438\u0439. \u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u0440\u0438\u043F\u0438\u043D\u0456\u0442\u044C \u0439\u043E\u0433\u043E.
|
||||||
|
done_txt=\u0413\u043E\u0442\u043E\u0432\u043E!
|
||||||
|
failure_txt=\u041D\u0435\u0432\u0434\u0430\u0447\u0430
|
Loading…
Reference in a new issue