diff --git a/pom.xml b/pom.xml index 449fa76..43959a8 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,11 @@ RELEASE compile + + com.google.guava + guava + 32.1.2-jre + diff --git a/src/main/java/guru/dead/icf320/MainController.java b/src/main/java/guru/dead/icf320/MainController.java index 235dd9b..7ce8bd7 100644 --- a/src/main/java/guru/dead/icf320/MainController.java +++ b/src/main/java/guru/dead/icf320/MainController.java @@ -8,10 +8,7 @@ import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.application.Platform; -import javafx.scene.control.Label; -import javafx.scene.control.Menu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.TextArea; +import javafx.scene.control.*; import javafx.stage.FileChooser; import javafx.stage.Modality; import javafx.stage.Stage; @@ -19,11 +16,13 @@ import javafx.stage.StageStyle; import org.controlsfx.glyphfont.FontAwesome; import org.controlsfx.glyphfont.GlyphFont; import org.controlsfx.glyphfont.GlyphFontRegistry; +import com.google.common.base.CharMatcher; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.util.Arrays; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -31,6 +30,7 @@ import java.util.concurrent.TimeUnit; public class MainController extends SerialController { @FXML public MenuItem cloneRawItem; + public Label filePath; @FXML private Label welcomeText; @@ -51,18 +51,19 @@ public class MainController extends SerialController { private Stage stage; FileChooser fileChooser = new FileChooser(); - + int readTime = 20; private ScheduledExecutorService executor; + File selectedFile; + @FXML private void initialize() { fillComPortMenu(); fillSettingsReadTime(); outputArea.setEditable(false); setOutputA(outputArea); - fileChooser.getExtensionFilters().addAll( new FileChooser.ExtensionFilter("Icom files", "*.ICF") ); @@ -210,6 +211,7 @@ public class MainController extends SerialController { log("ERROR", "Error occurred: " + e.getMessage() + "\n"); } } + private String filterData(String string) { string = string.replaceAll("[^\\x00-\\x7F]", "").replaceAll("Icom Inc.", ""); @@ -270,18 +272,67 @@ public class MainController extends SerialController { } public void onOpenItemClick(ActionEvent actionEvent) { - File selectedFile = fileChooser.showOpenDialog(stage); + selectedFile = fileChooser.showOpenDialog(stage); - if(!selectedFile.canRead()) { + if (selectedFile == null) return; + + if (!selectedFile.canRead()) { log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n"); return; } try { String fileContent = Files.readString(selectedFile.toPath()); - outputArea.appendText(fileContent + "\n"); + //TODO: send file content to port + if (!fileFormatValid(fileContent)) { + log("ERROR", "File format is not valid.\n"); + return; + } + log("INFO", "File " + selectedFile.getAbsolutePath() + " opened successfully.\n"); + filePath.setText(selectedFile.getAbsolutePath()); } catch (IOException e) { log("ERROR", "Error occurred: " + e.getMessage() + "\n"); } } + + public void onCloneWriteItemClick(ActionEvent actionEvent) { + if (getSelectedPort() == null || !getSelectedPort().isOpen()) { + log("ERROR", "Please select a valid COM port.\n"); + return; + } + if (selectedFile == null) { + log("ERROR", "Please, select ICF file first.\n"); + return; + } + + + } + + private Boolean fileFormatValid (String fileContent) { + //3: 0000102055020000000000A69C718800C0B63E + //130: 07F010000000000000000049434F4D20496E63 + + String[] lines = Arrays.stream(fileContent.split("\n")).map(str -> str.replaceAll("\r", "").trim()).toArray(String[]::new); + + boolean lineCount = lines.length == 130; + boolean firstLine = lines[2].equals("0000102055020000000000A69C718800C0B63E"); + boolean lastLine = lines[129].equals("07F010000000000000000049434F4D20496E63"); + boolean isAscii = CharMatcher.ascii().matchesAllOf(fileContent); + + return lineCount && firstLine && lastLine && isAscii; + } + + public void onAboutMenuItemClick(ActionEvent actionEvent) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.getDialogPane().getStylesheets().add(getClass().getResource("styles.css").toExternalForm()); + alert.setTitle("About"); + alert.setHeaderText("ICF300 - tool for programming Icom IC-F300 radios."); + String s ="dead.guru\n" + + "Version: 1.0\n" + + "Build: 2023-08-10\n" + + "License: MIT\n" + + "Source code: https://git.dead.guru/assada/icf300"; + alert.setContentText(s); + alert.show(); + } } \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 7da6838..17ffeda 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -5,6 +5,7 @@ module icf320 { requires org.controlsfx.controls; requires com.dlsc.formsfx; requires com.fazecast.jSerialComm; + requires com.google.common; opens guru.dead.icf320 to javafx.fxml; exports guru.dead.icf320; diff --git a/src/main/resources/guru/dead/icf320/home-view.fxml b/src/main/resources/guru/dead/icf320/home-view.fxml index eda0661..b84af23 100644 --- a/src/main/resources/guru/dead/icf320/home-view.fxml +++ b/src/main/resources/guru/dead/icf320/home-view.fxml @@ -12,6 +12,7 @@ + @@ -38,6 +39,12 @@ + + + + + + @@ -55,7 +62,7 @@ - + @@ -81,7 +88,7 @@ - +