File validation + about dialog

This commit is contained in:
Alex Ilienko 2023-08-10 23:48:22 +03:00
parent d9697b7da6
commit 4136488534
6 changed files with 85 additions and 12 deletions

View File

@ -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>

View File

@ -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,18 +272,67 @@ 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.canRead()) { if (selectedFile == null) return;
if (!selectedFile.canRead()) {
log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n"); log("ERROR", "Cannot read file: " + selectedFile.getName() + "\n");
return; return;
} }
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();
}
} }

View File

@ -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;

View File

@ -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" />

View File

@ -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>

View File

@ -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;
}