File validation + about dialog
This commit is contained in:
parent
d9697b7da6
commit
4136488534
5
pom.xml
5
pom.xml
@ -64,6 +64,11 @@
|
|||||||
<version>RELEASE</version>
|
<version>RELEASE</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>32.1.2-jre</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -8,10 +8,7 @@ import javafx.fxml.FXMLLoader;
|
|||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.Menu;
|
|
||||||
import javafx.scene.control.MenuItem;
|
|
||||||
import javafx.scene.control.TextArea;
|
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
@ -19,11 +16,13 @@ import javafx.stage.StageStyle;
|
|||||||
import org.controlsfx.glyphfont.FontAwesome;
|
import org.controlsfx.glyphfont.FontAwesome;
|
||||||
import org.controlsfx.glyphfont.GlyphFont;
|
import org.controlsfx.glyphfont.GlyphFont;
|
||||||
import org.controlsfx.glyphfont.GlyphFontRegistry;
|
import org.controlsfx.glyphfont.GlyphFontRegistry;
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -31,6 +30,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class MainController extends SerialController {
|
public class MainController extends SerialController {
|
||||||
@FXML
|
@FXML
|
||||||
public MenuItem cloneRawItem;
|
public MenuItem cloneRawItem;
|
||||||
|
public Label filePath;
|
||||||
@FXML
|
@FXML
|
||||||
private Label welcomeText;
|
private Label welcomeText;
|
||||||
|
|
||||||
@ -56,13 +56,14 @@ public class MainController extends SerialController {
|
|||||||
|
|
||||||
private ScheduledExecutorService executor;
|
private ScheduledExecutorService executor;
|
||||||
|
|
||||||
|
File selectedFile;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
fillComPortMenu();
|
fillComPortMenu();
|
||||||
fillSettingsReadTime();
|
fillSettingsReadTime();
|
||||||
outputArea.setEditable(false);
|
outputArea.setEditable(false);
|
||||||
setOutputA(outputArea);
|
setOutputA(outputArea);
|
||||||
|
|
||||||
fileChooser.getExtensionFilters().addAll(
|
fileChooser.getExtensionFilters().addAll(
|
||||||
new FileChooser.ExtensionFilter("Icom files", "*.ICF")
|
new FileChooser.ExtensionFilter("Icom files", "*.ICF")
|
||||||
);
|
);
|
||||||
@ -210,6 +211,7 @@ public class MainController extends SerialController {
|
|||||||
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
|
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String filterData(String string) {
|
private String filterData(String string) {
|
||||||
string = string.replaceAll("[^\\x00-\\x7F]", "").replaceAll("Icom Inc.", "");
|
string = string.replaceAll("[^\\x00-\\x7F]", "").replaceAll("Icom Inc.", "");
|
||||||
|
|
||||||
@ -270,7 +272,9 @@ public class MainController extends SerialController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onOpenItemClick(ActionEvent actionEvent) {
|
public void onOpenItemClick(ActionEvent actionEvent) {
|
||||||
File selectedFile = fileChooser.showOpenDialog(stage);
|
selectedFile = fileChooser.showOpenDialog(stage);
|
||||||
|
|
||||||
|
if (selectedFile == null) return;
|
||||||
|
|
||||||
if (!selectedFile.canRead()) {
|
if (!selectedFile.canRead()) {
|
||||||
log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n");
|
log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n");
|
||||||
@ -279,9 +283,56 @@ public class MainController extends SerialController {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
String fileContent = Files.readString(selectedFile.toPath());
|
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) {
|
} catch (IOException e) {
|
||||||
log("ERROR", "Error occurred: " + e.getMessage() + "\n");
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ module icf320 {
|
|||||||
requires org.controlsfx.controls;
|
requires org.controlsfx.controls;
|
||||||
requires com.dlsc.formsfx;
|
requires com.dlsc.formsfx;
|
||||||
requires com.fazecast.jSerialComm;
|
requires com.fazecast.jSerialComm;
|
||||||
|
requires com.google.common;
|
||||||
|
|
||||||
opens guru.dead.icf320 to javafx.fxml;
|
opens guru.dead.icf320 to javafx.fxml;
|
||||||
exports guru.dead.icf320;
|
exports guru.dead.icf320;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<?import org.controlsfx.glyphfont.Glyph?>
|
<?import org.controlsfx.glyphfont.Glyph?>
|
||||||
|
|
||||||
<?import org.controlsfx.control.StatusBar?>
|
<?import org.controlsfx.control.StatusBar?>
|
||||||
|
<?import javafx.scene.control.SeparatorMenuItem?>
|
||||||
<BorderPane xmlns="http://javafx.com/javafx/18.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="guru.dead.icf320.MainController">
|
<BorderPane xmlns="http://javafx.com/javafx/18.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="guru.dead.icf320.MainController">
|
||||||
<!-- Menubar on the top -->
|
<!-- Menubar on the top -->
|
||||||
<top>
|
<top>
|
||||||
@ -38,6 +39,12 @@
|
|||||||
<Glyph fontFamily="FontAwesome" icon="DOWNLOAD"/>
|
<Glyph fontFamily="FontAwesome" icon="DOWNLOAD"/>
|
||||||
</graphic>
|
</graphic>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<SeparatorMenuItem/>
|
||||||
|
<MenuItem onAction="#onCloneWriteItemClick" text="Write">
|
||||||
|
<graphic>
|
||||||
|
<Glyph fontFamily="FontAwesome" icon="UPLOAD"/>
|
||||||
|
</graphic>
|
||||||
|
</MenuItem>
|
||||||
<MenuItem fx:id="cloneRawItem" onAction="#onCloneRawItemClick" text="Raw">
|
<MenuItem fx:id="cloneRawItem" onAction="#onCloneRawItemClick" text="Raw">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="FontAwesome" icon="TERMINAL"/>
|
<Glyph fontFamily="FontAwesome" icon="TERMINAL"/>
|
||||||
@ -55,7 +62,7 @@
|
|||||||
</Menu>
|
</Menu>
|
||||||
<Menu text="Help">
|
<Menu text="Help">
|
||||||
<items>
|
<items>
|
||||||
<MenuItem text="About">
|
<MenuItem text="About" onAction="#onAboutMenuItemClick">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="FontAwesome" icon="INFO"/>
|
<Glyph fontFamily="FontAwesome" icon="INFO"/>
|
||||||
</graphic>
|
</graphic>
|
||||||
@ -81,7 +88,7 @@
|
|||||||
<bottom>
|
<bottom>
|
||||||
<StatusBar fx:id="mainStatusBar" text="">
|
<StatusBar fx:id="mainStatusBar" text="">
|
||||||
<leftItems>
|
<leftItems>
|
||||||
|
<Label fx:id="filePath" text="No file." />
|
||||||
</leftItems>
|
</leftItems>
|
||||||
<rightItems>
|
<rightItems>
|
||||||
<Label fx:id="welcomeText" text="Select COM port" />
|
<Label fx:id="welcomeText" text="Select COM port" />
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</padding>
|
</padding>
|
||||||
<HBox alignment="CENTER" spacing="10.0">
|
<HBox alignment="CENTER" spacing="10.0">
|
||||||
<TextArea fx:id="textInput" promptText="Command in HEX" />
|
<TextArea fx:id="textInput" promptText="Command in HEX" />
|
||||||
<Button defaultButton="true" onAction="#onPushButtonClick" text="Push!" />
|
<Button defaultButton="true" onAction="#onPushButtonClick" text="Send" />
|
||||||
</HBox>
|
</HBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
</center>
|
</center>
|
||||||
|
@ -751,3 +751,12 @@
|
|||||||
-fx-border-width: 0 0 1 0;
|
-fx-border-width: 0 0 1 0;
|
||||||
border-width: 0 0 1 0;
|
border-width: 0 0 1 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-pane:header .header-panel {
|
||||||
|
-fx-background-color: #3E3E42;
|
||||||
|
background-color: #3E3E42;
|
||||||
|
-fx-border-color: #222222;
|
||||||
|
border-color: #222222;
|
||||||
|
-fx-border-width: 0 0 1 0;
|
||||||
|
border-width: 0 0 1 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user