|
|
|
@ -1,9 +1,13 @@
@@ -1,9 +1,13 @@
|
|
|
|
|
package de.srsoftware.belegscanner; |
|
|
|
|
|
|
|
|
|
import de.srsoftware.belegscanner.gui.DocTable; |
|
|
|
|
import de.srsoftware.belegscanner.gui.ImproveSelector; |
|
|
|
|
import de.srsoftware.belegscanner.gui.MainFrame; |
|
|
|
|
import de.srsoftware.belegscanner.gui.ResolutionSelector; |
|
|
|
|
import de.srsoftware.belegscanner.gui.RotationSelector; |
|
|
|
|
import de.srsoftware.belegscanner.gui.StatusBar; |
|
|
|
|
import de.srsoftware.belegscanner.gui.Toolbar; |
|
|
|
|
import de.srsoftware.belegscanner.gui.TypeSelector; |
|
|
|
|
import de.srsoftware.belegscanner.model.api.Page; |
|
|
|
|
import de.srsoftware.belegscanner.model.api.Project; |
|
|
|
|
import de.srsoftware.tools.gui.DateChooser; |
|
|
|
@ -12,19 +16,20 @@ import org.json.JSONObject;
@@ -12,19 +16,20 @@ import org.json.JSONObject;
|
|
|
|
|
import org.slf4j.Logger; |
|
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
|
|
import javax.swing.*; |
|
|
|
|
import java.awt.*; |
|
|
|
|
import java.io.File; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.net.URI; |
|
|
|
|
import java.net.URISyntaxException; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Locale; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Optional; |
|
|
|
|
import java.util.Vector; |
|
|
|
|
|
|
|
|
|
import static de.srsoftware.belegscanner.Application.main; |
|
|
|
|
import static de.srsoftware.belegscanner.Application.t; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.CONFIG_TARGET; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.DEFAULT_HEIGHT; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.DEFAULT_WIDTH; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.JPG; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.OCR; |
|
|
|
|
import static de.srsoftware.belegscanner.Constants.PDF; |
|
|
|
@ -37,33 +42,35 @@ public class Worker {
@@ -37,33 +42,35 @@ public class Worker {
|
|
|
|
|
private SelectComboBox pathPicker; |
|
|
|
|
private StatusBar statusBar; |
|
|
|
|
private DateChooser datePicker; |
|
|
|
|
private String category,rawPath, resolvedPath; |
|
|
|
|
private String profile,rawPath, resolvedPath, type=OCR; |
|
|
|
|
private Toolbar toolbar; |
|
|
|
|
private DocTable docTable; |
|
|
|
|
private boolean improveBrightness,scanning; |
|
|
|
|
private int resolution; |
|
|
|
|
private boolean improveBrightness,scanning,removePageOnStitching; |
|
|
|
|
private int resolution,rotationAngle; |
|
|
|
|
private Dimension dimension; |
|
|
|
|
private String mode = "Color"; |
|
|
|
|
private MainFrame mainFrame; |
|
|
|
|
private int rotationAngle; |
|
|
|
|
|
|
|
|
|
private JTextField heightField, widthField; |
|
|
|
|
private ResolutionSelector resolutionSelector; |
|
|
|
|
private ImproveSelector improveSelector; |
|
|
|
|
private RotationSelector rotationSelector; |
|
|
|
|
private TypeSelector typeSelector; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Worker(Configuration config) { |
|
|
|
|
this.config = config; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void dropCategory(String droppedCat) { |
|
|
|
|
LOG.debug("Worker.dropCategory({})",droppedCat); |
|
|
|
|
public void dropProfile(String droppedProfile) { |
|
|
|
|
LOG.debug("Worker.dropProfile({})",droppedProfile); |
|
|
|
|
} |
|
|
|
|
public JSONObject getCategories() { |
|
|
|
|
return config.getOrCreate("app.categories",new JSONObject()); |
|
|
|
|
public JSONObject getProfiles() { |
|
|
|
|
return config.getOrCreate("profiles",new JSONObject()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Optional<JSONObject> 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); |
|
|
|
|
return type; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void resolvePath(){ |
|
|
|
@ -74,9 +81,13 @@ public class Worker {
@@ -74,9 +81,13 @@ public class Worker {
|
|
|
|
|
int month = date.getMonth()+1; |
|
|
|
|
int day = date.getDate(); |
|
|
|
|
resolvedPath = rawPath.replace("$"+t("HOME"),HOME) |
|
|
|
|
.replace("$"+t("CATEGORY"), category) |
|
|
|
|
.replace("$"+t("PROFILE"), profile) |
|
|
|
|
.replace("$"+t("YEAR"), year+"") |
|
|
|
|
.replace("$"+t("MONTH"), month<10 ? "0"+month : ""+month) |
|
|
|
|
.replace("$"+t("Month"),monthName(month)) |
|
|
|
|
.replace("$"+t("month"),monthName(month).toLowerCase()) |
|
|
|
|
.replace("$"+t("Mon"),monthNameShort(month)) |
|
|
|
|
.replace("$"+t("mon"),monthNameShort(month).toLowerCase()) |
|
|
|
|
.replace("$"+t("DAY"), day < 10 ? "0"+day : ""+day); |
|
|
|
|
|
|
|
|
|
var start = resolvedPath.indexOf("$"); |
|
|
|
@ -97,6 +108,43 @@ public class Worker {
@@ -97,6 +108,43 @@ public class Worker {
|
|
|
|
|
} |
|
|
|
|
toolbar.dropUnusedAdditionalFields(); |
|
|
|
|
statusBar.setPath(resolvedPath+"."+extension()); |
|
|
|
|
mainFrame.pack(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String monthName(int month) { |
|
|
|
|
return switch (month){ |
|
|
|
|
case 1: yield t("January"); |
|
|
|
|
case 2: yield t("February"); |
|
|
|
|
case 3: yield t("March"); |
|
|
|
|
case 4: yield t("April"); |
|
|
|
|
case 5: yield t("May"); |
|
|
|
|
case 6: yield t("June"); |
|
|
|
|
case 7: yield t("July"); |
|
|
|
|
case 8: yield t("August"); |
|
|
|
|
case 9: yield t("September"); |
|
|
|
|
case 10: yield t("October"); |
|
|
|
|
case 11: yield t("November"); |
|
|
|
|
case 12: yield t("December"); |
|
|
|
|
default: yield t("Error"); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String monthNameShort(int month) { |
|
|
|
|
return switch (month){ |
|
|
|
|
case 1: yield t("Jan"); |
|
|
|
|
case 2: yield t("Feb"); |
|
|
|
|
case 3: yield t("Mar"); |
|
|
|
|
case 4: yield t("Apr"); |
|
|
|
|
case 5: yield t("May"); |
|
|
|
|
case 6: yield t("Jun"); |
|
|
|
|
case 7: yield t("Jul"); |
|
|
|
|
case 8: yield t("Aug"); |
|
|
|
|
case 9: yield t("Sep"); |
|
|
|
|
case 10: yield t("Oct"); |
|
|
|
|
case 11: yield t("Nov"); |
|
|
|
|
case 12: yield t("Dec"); |
|
|
|
|
default: yield t("Error"); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String extension() { |
|
|
|
@ -119,9 +167,29 @@ public class Worker {
@@ -119,9 +167,29 @@ public class Worker {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void scan() { |
|
|
|
|
saveProfile(); |
|
|
|
|
new Thread(this::performScan).start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void saveProfile() { |
|
|
|
|
var prefix = String.join(".","profiles",profile,""); |
|
|
|
|
|
|
|
|
|
Map.of( |
|
|
|
|
"path",rawPath, |
|
|
|
|
"size",Map.of("height",dimension.height,"width",dimension.width), |
|
|
|
|
"resolution",resolution, |
|
|
|
|
"improvements", Map.of("brightness",improveBrightness,"drop_page",removePageOnStitching), |
|
|
|
|
"rotation",rotationAngle, |
|
|
|
|
"target_type",type) |
|
|
|
|
.entrySet() |
|
|
|
|
.forEach(e -> config.set(prefix+e.getKey(),e.getValue())); |
|
|
|
|
try { |
|
|
|
|
config.save(); |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
LOG.error("Failed to save profile",e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void performScan(){ |
|
|
|
|
LOG.debug("scan()"); |
|
|
|
|
var project = docTable.getProject(resolvedPath).orElseGet(() -> docTable.createProject(resolvedPath)); |
|
|
|
@ -366,21 +434,48 @@ public class Worker {
@@ -366,21 +434,48 @@ public class Worker {
|
|
|
|
|
this.statusBar = statusBar; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setType(String type) { |
|
|
|
|
LOG.debug("setType({})",type); |
|
|
|
|
config.set(CONFIG_TARGET, type); |
|
|
|
|
public void setType(String newType) { |
|
|
|
|
LOG.debug("setType({})",newType); |
|
|
|
|
type = newType; |
|
|
|
|
resolvePath(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setCat(String newCat) { |
|
|
|
|
LOG.debug("setCat({}})",newCat); |
|
|
|
|
this.category = newCat; |
|
|
|
|
getCategory(newCat).map(cat -> cat.get(Constants.PATH)) |
|
|
|
|
.map(o -> o instanceof String path ? path : null) |
|
|
|
|
.ifPresent(path -> { |
|
|
|
|
pathPicker.setText(path); |
|
|
|
|
setPath(path); |
|
|
|
|
}); |
|
|
|
|
public void loadProfile(String newProfile) { |
|
|
|
|
LOG.debug("setCat({}})",newProfile); |
|
|
|
|
profile = newProfile; |
|
|
|
|
var prefix = String.join(".","profiles",profile,""); |
|
|
|
|
Optional.ofNullable((String)config.get(prefix+"path")).ifPresent(path -> { |
|
|
|
|
pathPicker.setText(path); |
|
|
|
|
setPath(path); |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Integer)config.get(prefix+"size.height")).ifPresent(h -> { |
|
|
|
|
heightField.setText(""+h); |
|
|
|
|
dimension = new Dimension(dimension.width,h); |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Integer)config.get(prefix+"size.width")).ifPresent(w -> { |
|
|
|
|
widthField.setText(""+w); |
|
|
|
|
dimension = new Dimension(w,dimension.height); |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Integer)config.get(prefix+"resolution")).ifPresent(res -> { |
|
|
|
|
resolutionSelector.set(res); |
|
|
|
|
resolution = res; |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Boolean)config.get(prefix+"improvements.brightness")).ifPresent(b -> { |
|
|
|
|
improveSelector.setImproveBrightness(b); |
|
|
|
|
improveBrightness = b; |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Boolean)config.get(prefix+"improvements.drop_page")).ifPresent(d -> { |
|
|
|
|
improveSelector.setDropPage(d); |
|
|
|
|
removePageOnStitching = d; |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable((Integer)config.get(prefix+"rotation")).ifPresent(angle -> { |
|
|
|
|
rotationSelector.set(angle); |
|
|
|
|
rotationAngle = angle; |
|
|
|
|
}); |
|
|
|
|
Optional.ofNullable(config.get(prefix+"target_type")).map(Object::toString).ifPresent(t -> { |
|
|
|
|
typeSelector.set(t); |
|
|
|
|
type = t; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -410,9 +505,10 @@ public class Worker {
@@ -410,9 +505,10 @@ public class Worker {
|
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setRotation(int angle) { |
|
|
|
|
public Worker setRotation(int angle) { |
|
|
|
|
LOG.debug("setRotation({})",angle); |
|
|
|
|
rotationAngle = angle; |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void join(Project project) { |
|
|
|
@ -438,7 +534,8 @@ public class Worker {
@@ -438,7 +534,8 @@ public class Worker {
|
|
|
|
|
} |
|
|
|
|
cmd.add("cat"); |
|
|
|
|
cmd.add("output"); |
|
|
|
|
File joinedPDF = new File(project.pattern().replace("["+PAGE+"]",firstPage+"…"+lastPage+".pdf")); |
|
|
|
|
var pageReplace = removePageOnStitching ? "" : firstPage+"…"+lastPage; |
|
|
|
|
File joinedPDF = new File(project.pattern().replace("["+PAGE+"]",pageReplace).trim()+".pdf"); |
|
|
|
|
String target = joinedPDF.getName(); |
|
|
|
|
cmd.add(target); |
|
|
|
|
|
|
|
|
@ -471,4 +568,29 @@ public class Worker {
@@ -471,4 +568,29 @@ public class Worker {
|
|
|
|
|
LOG.error("Failed to show help",e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setRemovePageOnStitching(boolean newValue) { |
|
|
|
|
removePageOnStitching = newValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setDimensionPicker(JTextField height, JTextField width) { |
|
|
|
|
heightField = height; |
|
|
|
|
widthField = width; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setResolutionSelector(ResolutionSelector newVal) { |
|
|
|
|
resolutionSelector = newVal; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setImproveSelector(ImproveSelector newVal) { |
|
|
|
|
improveSelector = newVal; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setRotationSelector(RotationSelector newVal) { |
|
|
|
|
rotationSelector = newVal; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setTypeSelector(TypeSelector newVal) { |
|
|
|
|
typeSelector = newVal; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|