diff --git a/.gitignore b/.gitignore
index 9e3e952..c82f584 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/Belegscanner
/bin/
/target/
+.idea
\ No newline at end of file
diff --git a/BelegScanner.iml b/BelegScanner.iml
new file mode 100644
index 0000000..ec4b066
--- /dev/null
+++ b/BelegScanner.iml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/de/srsoftware/belegscanner/Constants.java b/src/main/java/de/srsoftware/belegscanner/Constants.java
index 09ceebb..39ecae6 100644
--- a/src/main/java/de/srsoftware/belegscanner/Constants.java
+++ b/src/main/java/de/srsoftware/belegscanner/Constants.java
@@ -11,4 +11,6 @@ public class Constants {
public static final String OCR = "pdf+ocr";
public static final String PDF = "pdf";
+ public static final String PATH = "path";
+ public static final String PAGE = "PAGE";
}
diff --git a/src/main/java/de/srsoftware/belegscanner/Worker.java b/src/main/java/de/srsoftware/belegscanner/Worker.java
new file mode 100644
index 0000000..1da6e30
--- /dev/null
+++ b/src/main/java/de/srsoftware/belegscanner/Worker.java
@@ -0,0 +1,166 @@
+package de.srsoftware.belegscanner;
+
+import de.srsoftware.belegscanner.gui.DocTable;
+import de.srsoftware.belegscanner.gui.StatusBar;
+import de.srsoftware.belegscanner.gui.Toolbar;
+import de.srsoftware.belegscanner.model.ScanProject;
+import de.srsoftware.belegscanner.model.api.Project;
+import de.srsoftware.tools.gui.DateChooser;
+import de.srsoftware.tools.gui.SelectComboBox;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.awt.*;
+import java.util.Optional;
+
+import static de.srsoftware.belegscanner.Application.t;
+import static de.srsoftware.belegscanner.Constants.CONFIG_TARGET;
+import static de.srsoftware.belegscanner.Constants.JPG;
+import static de.srsoftware.belegscanner.Constants.OCR;
+import static de.srsoftware.belegscanner.Constants.PDF;
+
+public class Worker {
+ private static final Logger LOG = LoggerFactory.getLogger(Worker.class);
+ private static final String HOME = System.getProperty("user.home");
+ private static final String YEAR = t("YEAR");
+ private final Configuration config;
+ private SelectComboBox pathPicker;
+ private StatusBar statusBar;
+ private String category;
+ private DateChooser datePicker;
+ private String rawPath, resolvedPath;
+ private Toolbar toolbar;
+ private DocTable docTable;
+
+ public Worker(Configuration config) {
+ this.config = config;
+ }
+
+ public void dropCategory(String droppedCat) {
+ LOG.debug("Worker.dropCategory({})",droppedCat);
+ }
+ public JSONObject getCategories() {
+ return config.getOrCreate("app.categories",new JSONObject());
+ }
+
+ private Optional getCategory(String name){
+ var cats = getCategories();
+ return cats.has(name) ? (cats.get(name) instanceof JSONObject cat ? Optional.of(cat) : Optional.empty()) : Optional.empty();
+ }
+ public String getType() {
+ return config.getOrCreate(CONFIG_TARGET, PDF);
+ }
+
+ public void resolvePath(){
+ if (rawPath == null) return;
+ LOG.debug("resolve({})",rawPath);
+ var date = datePicker.getSelectedDate();
+ int year = 1900+date.getYear();
+ int month = date.getMonth()+1;
+ int day = date.getDate();
+ resolvedPath = rawPath.replace("$"+t("HOME"),HOME)
+ .replace("$"+t("CATEGORY"), category)
+ .replace("$"+t("YEAR"), year+"")
+ .replace("$"+t("MONTH"), month<10 ? "0"+month : ""+month)
+ .replace("$"+t("DAY"), day < 10 ? "0"+day : ""+day);
+
+ var start = resolvedPath.indexOf("$");
+ toolbar.resetAdditionalFields();
+ while (start>-1) {
+ var end = endOfVar(resolvedPath, start+1);
+ if (end>start+1){
+ var variable = resolvedPath.substring(start+1, end);
+ LOG.debug("…unresolved '{}'",variable);
+ String value = toolbar.requireField(variable);
+ variable = "$"+variable;
+ LOG.debug("replacing '{}' in '{}' by '{}'",variable,resolvedPath,value);
+ resolvedPath = resolvedPath.replace(variable,value);
+ start = resolvedPath.indexOf("$",start+1);
+ } else {
+ start = resolvedPath.indexOf("$",start+2);
+ }
+ }
+ toolbar.dropUnusedAdditionalFields();
+ resolvedPath+="."+extension();
+ statusBar.setPath(resolvedPath);
+ }
+
+ private String extension() {
+ switch (getType()){
+ case PDF:
+ case OCR:
+ return "pdf";
+ case JPG:
+ return "jpg";
+ }
+ return "";
+ }
+
+ private int endOfVar(String path, int index) {
+ while(index cat.get(Constants.PATH))
+ .map(o -> o instanceof String path ? path : null)
+ .ifPresent(path -> {
+ pathPicker.setText(path);
+ setPath(path);
+ });
+ }
+
+
+ public void setDatePicker(DateChooser pd) {
+ datePicker = pd;
+ pd.addActionListener(ev -> this.resolvePath());
+ }
+
+ public void setToolbar(Toolbar toolbar) {
+ this.toolbar = toolbar;
+ }
+
+ public void setDocTable(DocTable docTable) {
+ this.docTable = docTable;
+ }
+}
diff --git a/src/main/java/de/srsoftware/belegscanner/gui/DocTable.java b/src/main/java/de/srsoftware/belegscanner/gui/DocTable.java
index 8d4e119..ced46b4 100644
--- a/src/main/java/de/srsoftware/belegscanner/gui/DocTable.java
+++ b/src/main/java/de/srsoftware/belegscanner/gui/DocTable.java
@@ -3,36 +3,27 @@ package de.srsoftware.belegscanner.gui;
import static de.srsoftware.belegscanner.Application.t;
import java.awt.Color;
-import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
-import java.awt.event.ActionListener;
-import java.io.File;
import java.io.FilenameFilter;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.TreeMap;
-import java.util.Vector;
import javax.swing.BorderFactory;
-import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.MatteBorder;
+import de.srsoftware.belegscanner.Worker;
+import de.srsoftware.belegscanner.listeners.ProjectListener;
+import de.srsoftware.belegscanner.model.api.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import de.srsoftware.belegscanner.Constants;
-
/**
*
* Creates a table of previously scanned documents.
@@ -46,89 +37,20 @@ public class DocTable extends JPanel{
private static int rowCounter = 0;
private static Font btnFont = new Font("Arial", Font.PLAIN, 28);
- public interface PreviewListener{
- public void show(Path filename);
- }
-
- /**
- * represents on previously scanned document
- * @author Stephan Richter
- *
- */
- private class Row{
-
- private JLabel status;
- private JLabel pathLabel;
- private JPanel buttons;
- private String path;
- private JButton joinButton;
-
- public Row(String project) {
- this.path = project;
- rows.put(project, this);
- constraints.gridy = ++rowCounter;
- constraints.gridx = 0;
- add(pathLabel = new JLabel(project), constraints);
- constraints.gridx = 1;
- add(status = new JLabel("neu"),constraints);
-
- buttons = new JPanel();
- buttons.setLayout(new FlowLayout());
-
- buttons.add(button("⚁",t("open folder"),ev -> openFolder(project)));
- buttons.add(joinButton = button("⎗",t("join PDFs"),ev -> joinDocs(project)));
- buttons.add(button("✉",t("display preview"),ev -> preview(project)));
- buttons.add(button("✓",t("done"),ev -> drop(this)));
- buttons.add(button("❌",t("drop file"),ev -> dropFile(project)));
-
- constraints.gridx = 2;
- add(buttons,constraints);
- }
-
- /**
- * drop the selected document from the table
- * @param row
- */
- private void drop(Row row) {
- if (row.joinButton.isEnabled()) joinDocs(row.path);
- remove(pathLabel);
- remove(status);
- remove(buttons);
- invalidate();
- repaint();
- rows.remove(path);
- }
+ private List projects = new ArrayList<>();
- /**
- * update status for selected document
- * @param status
- * @return
- */
- public Row status(String status) {
- this.status.setText(status);
- return this;
- }
-
- /**
- * remove the join button assigned with the selected document
- */
- public void setJoinButton(boolean enabled) {
- joinButton.setEnabled(enabled);
- joinButton.setVisible(enabled);
- }
- }
+ private List listeners = new ArrayList<>();
private static final long serialVersionUID = 1073955198529023744L;
- private final HashMap rows = new HashMap<>();
- private HashSet previewListeners;
private GridBagConstraints constraints;
/**
* create a new DocTable
*/
- public DocTable() {
+ public DocTable(Worker worker) {
setLayout(new GridBagLayout());
+ worker.setDocTable(this);
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(3, 10, 3, 10);
@@ -146,185 +68,9 @@ public class DocTable extends JPanel{
JLabel actions = new JLabel(t("Actions"),SwingConstants.CENTER);
actions.setBorder(border);
add(actions,constraints);
- previewListeners = new HashSet<>();
- }
-
- /**
- * Ad a table entry for the directory represented by path
- * @param project
- */
- public void add(String project) {
- var row = rows.get(project);
- if (row == null) {
- new Row(project).status("neu");
- } else row.setJoinButton(true);
- }
-
- /**
- * register a listener for changes of the preview area
- * @param listener
- * @return
- */
- public DocTable addPreviewListener(PreviewListener listener) {
- previewListeners.add(listener);
- return this;
- }
-
- /**
- * helper method to create a button with given label, tooltip and action listener
- * @param label
- * @param tooltip
- * @param listener
- * @return
- */
- private static JButton button(String label, String tooltip, ActionListener listener) {
- JButton btn = new JButton(label);
- btn.setFont(btnFont);
- btn.setToolTipText(tooltip);
- btn.addActionListener(listener);
- return btn;
- }
-
- private static int compareFiles(String file1, String file2) {
- return timestampFrom(file1) < timestampFrom(file2) ? 1 : -1;
- }
-
- private void dropFile(String path) {
- Path latest = latestFile(new File(path));
- if (latest != null) {
- LOG.debug("Removing {}",latest);
- latest.toFile().delete();
- preview(latest.toFile().getParent()); // show lates of remaining files
- }
- }
-
- /**
- * join documents in given path
- * @param path
- */
- public void joinDocs(String path) {
- LOG.debug("joinFiles({})",path);
- rows.get(path).setJoinButton(false);
- File folder = new File(path).getParentFile();
- if (!folder.exists()) return;
-
- String pattern = new File(path).getName();
- var parts = pattern.split("\\$"+t("PAGE"));
- var prefix = parts[0];
- var suffix = parts.length>1 ? parts[1] : "";
- if (parts.length<2) return;
-
- var pages = new TreeMap();
- for (var file : folder.list()){
- Optional opt = getPage(file, prefix, suffix);
- if (opt.isPresent()){
- pages.put(opt.get(),file);
- }
- }
- if (pages.size()<2) return;
- int first = pages.firstKey();
- int last = pages.lastKey();
-
- var range = first + (last != first ? "…"+last:"");
- var target = pattern.replace("$"+t("PAGE"),range);
-
- var pdfs = pages.values();
- Vector cmd = new Vector<>();
- cmd.add("pdftk");
- cmd.addAll(pdfs);
- cmd.add("cat");
- cmd.add("output");
- cmd.add(target);
- LOG.debug("executing {}",cmd);
- ProcessBuilder builder = new ProcessBuilder(cmd);
- builder.directory(folder);
- try {
- Process process = builder.start();
- setState(path,t("Joining PDFs…"));
- int errorCode = process.waitFor();
- if (errorCode != 0) {
- LOG.error("error code: {} for {}",errorCode,cmd);
- } else LOG.debug("error code: {}",errorCode);
- } catch (InterruptedException | IOException e) {
- LOG.error("{} terminated: ",builder,e);
- }
-
- pdfs.stream()
- .peek(page -> LOG.debug("removing {}",page))
- .map(page -> folder.toPath().resolve(page))
- .map(Path::toFile)
- .forEach(File::delete);
- setState(path,t("PDFs joined."));
- preview(folder);
- }
-
- private Optional getPage(String file, String prefix, String suffix) {
- if (file.startsWith(prefix) && file.endsWith(suffix)) {
- file = file.substring(prefix.length(), file.length() - suffix.length());
- try {
- return Optional.of(Integer.parseInt(file));
- } catch (NumberFormatException nfe) {}
- }
- return Optional.empty();
-
- }
-
- private Path latestFile(File folder) {
- if (!folder.exists()) return null;
- if (!folder.isDirectory()) folder = folder.getParentFile();
- List files = Arrays.asList(folder.list());
- String latest = files.stream().sorted(DocTable::compareFiles).findFirst().orElse(null);
- return latest == null ? null : folder.toPath().resolve(latest);
}
- /**
- * open given path in external file browser
- * @param path
- */
- public void openFolder(String path) {
- Process process = null;
- try {
- process = new ProcessBuilder(List.of("killall",Constants.FILE_BROWSER)).start();
- process.waitFor();
- Thread.sleep(100);
- } catch (IOException | InterruptedException e) {
- LOG.error(t("{} terminated: "),process,e);
- }
-
- try {
- process = new ProcessBuilder(List.of(Constants.FILE_BROWSER,new File(path).getParent())).start();
- } catch (IOException e) {
- LOG.error(t("{} terminated: "),process,e);
- }
- }
-
- public void preview(String path){
- preview(new File(path));
+ public Optional getProject(String resolvedPath) {
+ return projects.stream().filter(p -> resolvedPath.equals(p.pattern())).findAny();
}
-
- /**
- * show lates document of the given directory in preview area
- * @param path
- */
- public void preview(File path) {
- LOG.debug("preview({})",path);
- previewListeners.forEach(l -> l.show(latestFile(path)));
- }
-
- /**
- * update state column text for given path
- * @param path
- * @param state
- */
- public void setState(String path, String state) {
- Row row = rows.get(path);
- if (row != null) row.status(state);
- }
-
- private static long timestampFrom(String filename) {
- try {
- return Long.parseLong(filename.split("\\.",2)[0]);
- } catch (Exception e) {}
- return 0;
- }
}
diff --git a/src/main/java/de/srsoftware/belegscanner/gui/FormatSelector.java b/src/main/java/de/srsoftware/belegscanner/gui/FormatSelector.java
new file mode 100644
index 0000000..89eceff
--- /dev/null
+++ b/src/main/java/de/srsoftware/belegscanner/gui/FormatSelector.java
@@ -0,0 +1,59 @@
+package de.srsoftware.belegscanner.gui;
+
+import de.srsoftware.belegscanner.Worker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import static de.srsoftware.belegscanner.Application.t;
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.BorderLayout.WEST;
+
+public class FormatSelector extends JPanel {
+ private static final Logger LOG = LoggerFactory.getLogger(FormatSelector.class);
+ private final JTextField height, width;
+
+ public FormatSelector(Worker worker){
+ setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
+ JPanel widthSelector = new JPanel();
+ widthSelector.setLayout(new BorderLayout());
+ widthSelector.setMaximumSize(new Dimension(600, 40));
+
+ widthSelector.add(new JLabel(t("Width")+": "), WEST);
+ widthSelector.add(width = new JTextField(209+""), CENTER);
+ widthSelector.add(new JLabel("px"),BorderLayout.EAST);
+ add(widthSelector,NORTH);
+
+ var heightSelector = new JPanel();
+ heightSelector.setLayout(new BorderLayout());
+ heightSelector.setMaximumSize(new Dimension(600, 40));
+
+ heightSelector.add(new JLabel(t("Height")+": "), WEST);
+ heightSelector.add(height = new JTextField(297+""), CENTER);
+ heightSelector.add(new JLabel("px"),BorderLayout.EAST);
+ add(heightSelector,SOUTH);
+
+ KeyAdapter dimensionListener = new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ LOG.debug("updateDimensions()");
+ try {
+ int w = Integer.parseInt(width.getText().trim());
+ int h = Integer.parseInt(height.getText().trim());
+ worker.setDimension(new Dimension(w < 0 ? 0 : w, h < 0 ? 0 : h));
+ } catch (NumberFormatException nfe) {
+ LOG.warn("Invalid dimensions!");
+ }
+ }
+ };
+
+ width.addKeyListener(dimensionListener);
+ height.addKeyListener(dimensionListener);
+ }
+}
diff --git a/src/main/java/de/srsoftware/belegscanner/gui/ImproveSelector.java b/src/main/java/de/srsoftware/belegscanner/gui/ImproveSelector.java
new file mode 100644
index 0000000..cec36bf
--- /dev/null
+++ b/src/main/java/de/srsoftware/belegscanner/gui/ImproveSelector.java
@@ -0,0 +1,29 @@
+package de.srsoftware.belegscanner.gui;
+
+import javax.swing.*;
+import java.awt.*;
+
+import static de.srsoftware.belegscanner.Application.t;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.WEST;
+
+public class ImproveSelector extends JPanel {
+
+ private boolean improveBrightness;
+
+ public ImproveSelector() {
+ super(new BorderLayout());
+ ButtonGroup group = new ButtonGroup();
+ add(new JLabel(t("Adjustments")), NORTH);
+ var checkbox = new JCheckBox(t("Improve brightness"));
+ add(checkbox,WEST);
+ setMaximumSize(new Dimension(600,200));
+ checkbox.addActionListener(e -> {
+ improveBrightness = checkbox.isSelected();
+ });
+ }
+
+ public boolean improveBrightness(){
+ return improveBrightness;
+ }
+}
diff --git a/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java b/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java
index 07c628e..530ec5c 100644
--- a/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java
+++ b/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java
@@ -1,53 +1,27 @@
package de.srsoftware.belegscanner.gui;
-import static de.srsoftware.belegscanner.Application.t;
-import static de.srsoftware.belegscanner.Constants.CONFIG_TARGET;
-import static de.srsoftware.belegscanner.Constants.FILE_BROWSER;
-import static de.srsoftware.belegscanner.Constants.JPG;
-import static de.srsoftware.belegscanner.Constants.PDF;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Image;
-import java.awt.Point;
-import java.awt.event.ActionEvent;
+import de.srsoftware.belegscanner.Configuration;
+import de.srsoftware.belegscanner.Worker;
+import org.icepdf.ri.common.SwingController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.*;
+import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map.Entry;
-import java.util.Vector;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import javax.imageio.ImageIO;
-import javax.swing.BorderFactory;
-import javax.swing.ImageIcon;
-import javax.swing.JComponent;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.SwingConstants;
-
-import org.icepdf.ri.common.ComponentKeyBinding;
-import org.icepdf.ri.common.SwingController;
-import org.icepdf.ri.common.SwingViewBuilder;
-import org.icepdf.ri.common.views.DocumentViewController;
-import org.json.JSONArray;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import de.srsoftware.belegscanner.Configuration;
+import static de.srsoftware.belegscanner.Application.t;
+import static de.srsoftware.belegscanner.Constants.FILE_BROWSER;
/**
* The "guts" of the application:
@@ -60,7 +34,6 @@ public class MainFrame extends JFrame {
private static final long serialVersionUID = 210283601541223645L;
- private static final String HOME = System.getProperty("user.home");
private static final Pattern MARKEN = Pattern.compile("\\$([a-zäöüA-ZÄÖÜ]+)");
private static final String APP_WIDTH = "app.main.dimension.w";
@@ -74,6 +47,7 @@ public class MainFrame extends JFrame {
private static final String BAD_POLICY = "";
private static final String POLICY_FILE = "/etc/ImageMagick-6/policy.xml";
+ private final Worker worker;
private StatusBar statusBar;
private Toolbar toolbar;
@@ -89,21 +63,12 @@ public class MainFrame extends JFrame {
private String patchedPath = "";
private String project = "";
- private Configuration config;
-
private String mode = "Color";
private DocTable docTable;
private Dimension dimension = new Dimension(209, 297);
- private SwingController pdfViewer;
-
- private JLabel fileName;
-
- private boolean isScanning = false;
-
- private JComponent previewComponent = null;
private JPanel pdfPreview;
@@ -113,55 +78,28 @@ public class MainFrame extends JFrame {
*/
public MainFrame(Configuration config) {
super("BelegScanner");
- this.config = config;
- int width = config.getOrCreate(APP_WIDTH,800);
- int height = config.getOrCreate(APP_HEIGHT,600);
-
- BorderLayout layout = new BorderLayout();
- setLayout(layout);
-
- toolbar = new Toolbar(config);
- statusBar = new StatusBar();
- docTable = new DocTable();
-
- add(toolbar,BorderLayout.EAST);
- add(statusBar,BorderLayout.SOUTH);
- add(docTable,BorderLayout.NORTH);
- pdfPreview = preview();
- add(previewComponent = pdfPreview,BorderLayout.CENTER);
-
- toolbar.addCategoryListener(this::setCategory)
- .addDateListener(this::setDate)
- .addDimensionListener(this::setDimension)
- .addFieldListener(this::setField)
- .addPathListener(this::setPath)
- .addScanListener(this::scan);
-
- docTable.addPreviewListener(this::preview);
-
+ setLayout(new BorderLayout());
+ worker = new Worker(config);
+
+ add(toolbar = new Toolbar(worker),BorderLayout.EAST);
+ add(statusBar = new StatusBar(worker),BorderLayout.SOUTH);
+ add(docTable = new DocTable(worker),BorderLayout.NORTH);
+ add(pdfPreview = new Preview(worker),BorderLayout.CENTER);
+
int x = config.getOrCreate(APP_X, 20);
int y = config.getOrCreate(APP_Y, 20);
setLocation(new Point(x, y));
-
- checkScanButton();
-
+
+ int width = config.getOrCreate(APP_WIDTH,800);
+ int height = config.getOrCreate(APP_HEIGHT,600);
setPreferredSize(new Dimension(width,height));
+
pack();
setVisible(true);
}
- /**
- * Scans the given path for occurences of '$VARIABLES' and creates input fields for the found variables.
- * @param path
- */
- private void addFieldsForPath(String path) {
- Vector marks = new Vector<>();
- Matcher matches = MARKEN.matcher(path);
- while (matches.find()) marks.add(matches.group(1));
- toolbar.addFieldsFor(marks);
- };
public String appMissing(String appTest){
List cmd = Arrays.asList(appTest.split(" "));
@@ -242,17 +180,6 @@ public class MainFrame extends JFrame {
- /**
- * checks, whether the scan button may be enabled.
- */
- private void checkScanButton() {
- toolbar.readyToScan(!(isScanning || patchedPath==null || patchedPath.isBlank() || patchedPath.contains("$")));
- }
-
- private String extension(String path) {
- var target = config.get(CONFIG_TARGET);
- return path +"."+ (JPG.equals(target) ? "jpg":"pdf");
- }
private void notifyAppsMissing(List missingApps) {
@@ -269,357 +196,4 @@ public class MainFrame extends JFrame {
JOptionPane.WARNING_MESSAGE);
System.exit(-1);
}
-
-
- /**
- * scan a new document, convert it to pdf and perform text recognition
- * @param path
- * @param dimension
- */
- private void performScan(String project, String path, Dimension dimension) {
- LOG.debug("performScan({})",path);
- /* We need to save all required config values before starting to scan, because they might be changed during scanning */
- String target = config.getOrCreate(CONFIG_TARGET, "pdf");
- setScanning(true);
-
- var targetFile = new File(path);
- File folder = targetFile.getParentFile();
- if (!folder.exists()) {
- LOG.warn(t("Path '{}' does not exist!"),path);
- folder.mkdirs();
- }
-
- docTable.add(project);
-
- int resolution = toolbar.getResolution();
- boolean improbeBrightness = toolbar.getImproveBrightness();
- //long timestamp = new Date().getTime();
- //String raw = timestamp+".jpg";
- var raw = targetFile.getName()+".jpg";
-
- Vector cmd = new Vector<>();
- cmd.add("scanimage");
- cmd.add("-x");
- cmd.add(dimension.width+"");
- cmd.add("-y");
- cmd.add(dimension.height+"");
- cmd.add("--mode");
- cmd.add(mode);
- cmd.add("--resolution");
- cmd.add(resolution+"");
- cmd.add("-o");
- cmd.add(raw);
- LOG.debug("executing {}",cmd);
-
- ProcessBuilder builder = new ProcessBuilder(cmd);
- builder.directory(folder);
- try {
- Process process = builder.start();
- docTable.setState(project,t("Scanning…"));
- int errorCode = process.waitFor();
- if (errorCode != 0) {
- LOG.error(t("Error code: {} for {}"),errorCode,cmd);
- docTable.setState(project, t("Scan failed."));
- setScanning(false);
- return;
- }
- } catch (InterruptedException | IOException e) {
- LOG.error(t("{} terminated: "),builder,e);
- }
- setScanning(false);
- toolbar.nextPage();
-
- if (improbeBrightness) {
- cmd = new Vector<>();
- cmd.add("mogrify");
- cmd.add("-contrast-stretch");
- cmd.add("0x60%");
- cmd.add(raw);
- builder = new ProcessBuilder(cmd);
- builder.directory(folder);
- try {
- Process process = builder.start();
- docTable.setState(project,t("Adjusting brightness…"));
- int errorCode = process.waitFor();
- if (errorCode != 0) {
- LOG.error(t("Error code: {} for {}"),errorCode,cmd);
- docTable.setState(project, t("Adjustment failed."));
- setScanning(false);
- return;
- }
- } catch (InterruptedException | IOException e) {
- LOG.error(t("{} terminated: "),builder,e);
- }
-
- }
-
- if (JPG.equals(target)) {
- docTable.setState(project, t("Image scanned"));
- docTable.preview(folder);
- return;
- };
-
- String pdf = targetFile.getName() + (PDF.equals(target) ? ".pdf" : ".tmp.pdf"); //timestamp+".page.pdf";
- cmd = new Vector<>();
- cmd.add("convert");
- cmd.add(raw);
- cmd.add(pdf);
- builder = new ProcessBuilder(cmd);
- builder.directory(folder);
- try {
- Process process = builder.start();
- docTable.setState(project,t("Converting to PDF…"));
- int errorCode = process.waitFor();
- if (errorCode != 0) {
- LOG.error("Error code: {} for {}",errorCode,cmd);
- docTable.setState(project, t("Conversion failed."));
- return;
- }
-
- } catch (InterruptedException | IOException e) {
- LOG.error("{} terminated: ",builder,e);
- }
- LOG.debug("removing {}",raw);
- folder.toPath().resolve(raw).toFile().delete();
- //Path.of(folder,raw).toFile().delete();
- if (PDF.equals(target)) {
- docTable.setState(project, t("PDF created"));
- docTable.preview(folder);
- return;
- }
-
- String ocr = targetFile.getName() + ".pdf";//timestamp+".page.ocr.pdf";
-
- cmd = new Vector<>();
- cmd.add("pdfsandwich");
- cmd.add("-lang");
- cmd.add("deu");
- cmd.add("-rgb");
- if (resolution>300) {
- cmd.add("-resolution");
- cmd.add(""+resolution);
- }
- cmd.add("-o");
- cmd.add(ocr);
- cmd.add(pdf);
- LOG.debug("executing {}",cmd);
- builder = new ProcessBuilder(cmd);
- builder.directory(folder);
- try {
- Process process = builder.start();
- docTable.setState(project,t("Text recognition…"));
- int errorCode = process.waitFor();
- if (errorCode != 0) {
- LOG.error("error code: {} for {}",errorCode,cmd);
- docTable.setState(project, t("OCR failed."));
- return;
- }
- if (!folder.toPath().resolve(ocr).toFile().exists()){
- docTable.setState(project,t("OCR failed."));
- return;
- }
- } catch (InterruptedException | IOException e) {
- LOG.error("{} terminated: ",builder,e);
- }
-
- LOG.debug("removing {}",pdf);
- folder.toPath().resolve(pdf).toFile().delete();
- docTable.setState(project,t("Finished text recognition."));
- docTable.preview(folder);
-
- }
-
- /**
- * create preview panel
- * @return
- */
- private JPanel preview() {
- // https://stackoverflow.com/a/48248739/1285585
- JPanel pane = new JPanel(new BorderLayout());
-
- pdfViewer = new SwingController();
- SwingViewBuilder factory = new SwingViewBuilder(pdfViewer);
-
- JPanel viewerComponentPanel = factory.buildViewerPanel();
-
- ComponentKeyBinding.install(pdfViewer, viewerComponentPanel);
- // add interactive mouse link annotation support via callback
- pdfViewer.getDocumentViewController().setAnnotationCallback(new org.icepdf.ri.common.MyAnnotationCallback(pdfViewer.getDocumentViewController()));
-
- pane.add(viewerComponentPanel,BorderLayout.CENTER);
- pane.setBorder(BorderFactory.createLineBorder(Color.black));
-
- pane.add(fileName = new JLabel(),BorderLayout.SOUTH);
- fileName.setHorizontalAlignment(SwingConstants.CENTER);
-
- return pane;
- }
-
- /**
- * open file in preview panel
- * @param filePath
- */
- private void preview(Path filePath) {
- if (filePath == null) return;
- String file = filePath.toString();
- if (file.toLowerCase().endsWith("pdf")) {
- if (previewComponent != pdfPreview) {
- remove(previewComponent);
- previewComponent = pdfPreview;
- add(previewComponent,BorderLayout.CENTER);
- pack();
- }
- pdfViewer.openDocument(file);
- pdfViewer.setPageFitMode(DocumentViewController.PAGE_FIT_WINDOW_HEIGHT, false);
- }
- if (file.toLowerCase().endsWith("jpg")) {
- try {
- Image img = ImageIO.read(new File(file));
- Dimension dim = previewComponent.getSize();
- double w = img.getWidth(null);
- double h = img.getHeight(null);
- double factor = Math.min(dim.width/w, dim.height/h);
- if (factor != 1.0) img = img.getScaledInstance((int)(w*factor), (int)(h*factor), Image.SCALE_DEFAULT);
- ImageIcon icon = new ImageIcon(img);
- JLabel label = new JLabel(icon);
- this.remove(previewComponent);
- previewComponent = label;
- this.add(previewComponent, BorderLayout.CENTER);
- pack();
- } catch (IOException e) {
- LOG.error("Was not able to preview {}:",file,e);
- }
- }
- fileName.setText(file);
- }
-
- /**
- * save config, then start scannin in separate thread
- * @param ev
- */
- private void scan(ActionEvent ev) {
- updateConfig();
- new Thread(() -> performScan(project,patchedPath,dimension)).start();
- }
-
- /**
- * update the category currently used
- * @param category
- */
- private void setCategory(String category) {
- this.category = category;
- updatePath();
-
- }
-
- /**
- * update the date currently used
- * @param date
- */
- private void setDate(Date date) {
- this.date = date;
- updatePath();
- }
-
- /**
- * update the scan dimensions currently used
- * @param dim
- */
- private void setDimension(Dimension dim) {
- this.dimension = dim;
- }
-
-
- /**
- * update the value of a variable field
- * @param key
- * @param val
- */
- private void setField(String key, String val) {
- if (val == null || val.isEmpty()) {
- fields.remove(key);
- } else fields.put(key, val);
- updatePath();
- }
-
-
- /**
- * update the path currently used as scan target directory
- * @param path
- */
- private void setPath(String path) {
- this.path = path;
- updatePath();
- }
-
-
- /**
- * toggle scanning state
- * @param scanning
- */
- private void setScanning(boolean scanning) {
- isScanning = scanning;
- checkScanButton();
- }
-
-
- /**
- * push current settings to the configuration, then save it.
- */
- private void updateConfig() {
-
- String prefix = "app.categories."+category+".";
- for (Entry entry : fields.entrySet()) {
- String key = entry.getKey();
- String val = entry.getValue();
- JSONArray arr = config.getOrCreateArray(prefix+"fields."+key);
- HashSet