Werkzeug um Belege zu scannen, Texterkennung durchzuführen und Belege sortiert abzulegen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

459 lines
12 KiB

unit scanner;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtDlgs,
StdCtrls, ExtCtrls, Calendar, Unix;
type
{ ScanThread }
ScanThread = class(TThread)
private
dbtn, obtn, sbtn : TButton;
folder,r :String;
s:TPoint;
p:TImage;
protected
procedure Execute; override;
public
constructor Create(scanButton: TButton; dir: String; size: TPoint; resolution: String; preview: TImage; dropButton: TButton; openButton: TButton);
end;
{ TScanForm }
TScanForm = class(TForm)
dropBtn: TButton;
OpenDir: TButton;
extButton: TButton;
Swap: TButton;
DropButton: TButton;
Calendar: TCalendar;
PicSize: TComboBox;
Preview: TImage;
Stop: TComboBox;
DPI: TLabel;
BaseFolder: TLabel;
Resolution: TComboBox;
BaseFolderDialog: TSelectDirectoryDialog;
ScanButton: TButton;
Product: TComboBox;
Destination: TComboBox;
FolderName: TLabel;
Origin: TComboBox;
TypeSelector: TComboBox;
procedure BaseFolderClick(Sender: TObject);
procedure dropBtnClick(Sender: TObject);
procedure extButtonClick(Sender: TObject);
procedure DropButtonClick(Sender: TObject);
procedure CalendarChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure OpenDirClick(Sender: TObject);
procedure ProductChange(Sender: TObject);
procedure DestinationChange(Sender: TObject);
procedure OriginChange(Sender: TObject);
procedure ScanButtonClick(Sender: TObject);
procedure StopChange(Sender: TObject);
procedure SwapClick(Sender: TObject);
procedure TypeSelectorChange(Sender: TObject);
function ExportConfig(): string;
function ExportOptions(dropDown: TComboBox): string;
procedure ComboKey(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure UpdateFolder();
procedure MixLocations(d1: TComboBox; d2: TComboBox; d3: TComboBox);
procedure DeleteStationFrom(combo: TComboBox; station: string; defaultName : string);
procedure DeleteStation(station : string);
private
date: TDateTime;
function getSize(): TPoint;
public
const
SCANNING : Integer = 1;
IDLE: Integer = 0;
end;
var
ScanForm: TScanForm;
implementation
{$R *.lfm}
{ ScanThread }
constructor ScanThread.Create(scanButton: TButton; dir: String; size: TPoint; resolution: String; preview: TImage; dropButton: TButton; openButton: TButton );
begin
sbtn := scanButton;
obtn := openButton;
dbtn := dropButton;
folder:=dir;
s:=size;
r:=resolution;
p:=preview;
inherited Create(false);
end;
procedure ScanThread.Execute;
var
fname: String;
num: Integer;
pic: TPicture;
begin
ForceDirectories(folder);
num := 0;
repeat
num := num +1;
fname := 'scan_';
if (num<10) then fname:=fname+'0';
if (num<100) then fname:=fname+'0';
if (num<1000) then fname:=fname+'0';
fname := fname+IntToStr(num)+'.jpg';
until not FileExists(folder+fname);
fpSystem('scanimage -x '+IntToStr(s.x)+' -y '+IntToStr(s.y)+' --mode Color --resolution '+r+' --format jpeg > "'+folder+fname+'"');
try
pic:=TPicture.Create;
pic.LoadFromFile(folder+fname);
p.Picture:=pic;
p.Hint:=folder+fname;
finally
end;
dbtn.Hint:=folder+fname;
dbtn.Caption:=fname+' löschen';
dbtn.Enabled:=true;
obtn.Enabled:=true;
sbtn.Enabled:=true;
sbtn.Tag := TScanForm.IDLE;
end;
function allowed(s: String): boolean;
begin
Result := true;
if (s = '') then Result := false;
if (s = 'Start') then Result := false;
if (s = 'Ziel') then Result := false;
if (s = 'Zwischenhalt') then Result := false;
end;
procedure TScanForm.MixLocations(d1: TComboBox; d2: TComboBox; d3: TComboBox);
var
list: TStringList;
begin
list := TStringList.Create;
list.Sorted := True;
if (allowed(d1.Text)) then d1.Items.Add(d1.Text);
if (allowed(d2.Text)) then d2.Items.Add(d2.Text);
if (allowed(d3.Text)) then d3.Items.Add(d3.Text);
list.Assign(d1.Items);
list.AddStrings(d2.Items);
list.AddStrings(d3.Items);
d1.Items.Assign(list);
d2.Items.Assign(list);
d3.Items.Assign(list);
end;
function TScanForm.ExportConfig(): string;
begin
Result := 'folder:'+BaseFolder.Caption+#13;
Result := Result + 'types:' + ExportOptions(TypeSelector) + #13;
Result := Result + 'items:' + ExportOptions(Product) + #13;
MixLocations(Origin, Destination, Stop);
Result := Result + 'locations:' + ExportOptions(Origin) + #13;
Result := Result + 'sizes:' + ExportOptions(PicSize) +#13;
end;
function TScanForm.ExportOptions(dropDown: TComboBox): string;
var
list: TStringList;
item, current: string;
i: integer;
drop: Boolean;
begin
// make sure the current text appears in future lists
item := dropDown.Text;
drop := item.StartsWith(' ');
if drop then
begin
i := 0;
while i < dropDown.Items.Count do
begin
item := Trim(item);
current := Trim(dropDown.Items[i]);
if current = item then dropDown.Items.Delete(i) else i := i+1;
end;
end else dropDown.Items.Add(item);
// create a StringList to sort and concatenate
list := TStringList.Create;
list.StrictDelimiter := True;
list.Sorted := True;
// put all items in the list, will sort and remove duplicates
list.Assign(dropDown.Items);
// update dropdown
dropDown.Items.Assign(list);
// return json array
Result := list.DelimitedText
end;
procedure TScanForm.ComboKey(Sender: TObject; var Key: Word; Shift: TShiftState);
var
combo : TComboBox;
index : integer;
tx : string;
begin
if key = 40 then
begin
if TObject(Sender) is TComboBox then
begin
combo := TComboBox(Sender);
tx := combo.Text;
for index := 0 to combo.Items.Count-1 do
begin
if combo.Items[index].StartsWith(tx,true) then
begin
combo.ItemIndex:=index-1;
Exit;
end;
end;
end;
end;
end;
procedure TScanForm.TypeSelectorChange(Sender: TObject);
var
state: boolean;
begin
TypeSelector.Tag := 1;
state := TypeSelector.Text = 'Ticket';
Origin.Enabled := state;
Origin.Visible := state;
Stop.Enabled := state;
Stop.Visible := state;
Destination.Enabled := state;
Destination.Visible := state;
Swap.Enabled:=state;
Product.Enabled := not state;
Product.Visible := not state;
if (ScanButton.Tag <> TScanForm.SCANNING) then ScanButton.Enabled:=true;
UpdateFolder();
end;
procedure TScanForm.CalendarChange(Sender: TObject);
begin
date := Calendar.DateTime;
TypeSelector.Enabled := True;
UpdateFolder();
end;
procedure TScanForm.OriginChange(Sender: TObject);
begin
Origin.Tag := 1;
UpdateFolder();
end;
function TScanForm.getSize(): TPoint;
var
arr: TStringArray;
s: String;
w, h: Integer;
begin
s:=PicSize.Text;
arr:=s.Split(['x','m']);
w:=StrToInt(arr[0].Trim);
h:=StrToInt(arr[1].Trim);
PicSize.Caption:=IntToStr(w)+' x '+IntToStr(h)+' mm';
Result := TPoint.Create(w,h);
end;
procedure TScanForm.ScanButtonClick(Sender: TObject);
var
config: TFileStream;
filename: string;
json: string;
size: TPoint;
begin
ScanButton.Enabled:=false;
ScanButton.Tag:=TScanForm.SCANNING;
filename := GetEnvironmentVariable('HOME') + '/.config/belegscanner.conf';
size := getSize();
json := ExportConfig();
try
config := TFilestream.Create(filename, fmCreate);
config.Write(json[1], json.Length);
finally
config.Free;
end;
ScanThread.Create(ScanButton,BaseFolder.Caption+'/'+FolderName.Caption+'/',size,Resolution.Caption,Preview,DropButton,extButton);
end;
procedure TScanForm.StopChange(Sender: TObject);
begin
Stop.Tag := 1;
UpdateFolder();
end;
procedure TScanForm.SwapClick(Sender: TObject);
var
dummy: String;
begin
dummy:=Origin.Text;
Origin.Text := Destination.Text;
Destination.Text := dummy;
UpdateFolder();
end;
procedure TScanForm.DestinationChange(Sender: TObject);
begin
Destination.Tag := 1;
UpdateFolder();
end;
procedure TScanForm.ProductChange(Sender: TObject);
begin
Product.Tag := 1;
UpdateFolder();
end;
procedure addItemsTo(combo: TComboBox; line: String);
var
parts: TStringArray;
fixed, part: string;
begin
parts := line.Split(',');
for part in parts do
begin
fixed := part.Replace('"','');
if (fixed <> '') then combo.Items.Add(fixed);
end;
end;
procedure TScanForm.FormCreate(Sender: TObject);
var
filename: String;
lines: TStringList;
line: String;
index: integer;
begin
BaseFolder.Caption:=GetEnvironmentVariable('HOME');
filename := GetEnvironmentVariable('HOME') + '/.config/belegscanner.conf';
lines := TStringList.Create;
Calendar.DateTime:=Now;
try
lines.LoadFromFile(filename);
for index := 0 to lines.Count-1 do
begin
line:=lines.Strings[index];
if line.StartsWith('folder:') then
begin
line:=line.Substring(7);
BaseFolder.Caption:=line;
end;
if line.StartsWith('types:') then addItemsTo(TypeSelector,line.Substring(6));
if line.StartsWith('items:') then addItemsTo(Product,line.Substring(6));
if line.StartsWith('sizes:') then addItemsTo(PicSize,line.Substring(6));
if line.StartsWith('locations:') then
begin
line := line.Substring(10);
addItemsTo(Origin,line);
addItemsTo(Destination,line);
addItemsTo(Stop,line);
end;
end
finally
end;
end;
procedure TScanForm.OpenDirClick(Sender: TObject);
begin
WriteLn(BaseFolder.Caption);
fpSystem('gio open "'+BaseFolder.Caption+'"');
end;
procedure TScanForm.BaseFolderClick(Sender: TObject);
begin
BaseFolderDialog.FileName:=BaseFolder.Caption;
BaseFolderDialog.Execute;
BaseFolder.Caption := BaseFolderDialog.FileName;
end;
procedure TScanForm.DeleteStationFrom(combo: TComboBox; station : string; defaultName : string);
var
index : integer;
begin
index := combo.Items.IndexOf(station);
if index > -1 then
begin
combo.Items.Delete(index);
combo.Text := defaultName;
end;
end;
procedure TScanForm.DeleteStation(station : string);
begin
DeleteStationFrom(Origin,station,'Start');
DeleteStationFrom(Stop,station,'Zwischenhalt');
DeleteStationFrom(Destination,station,'Ziel');
end;
procedure TScanForm.dropBtnClick(Sender: TObject);
var
tx : string;
begin
tx := TypeSelector.Text;
if (tx <> 'Herkunft') and (tx <> 'Ticket') then
begin
TypeSelector.Items.Delete(TypeSelector.ItemIndex);
TypeSelector.Text := 'Herkunft';
end;
tx := Product.Text;
if Product.Enabled and (tx <> 'Produkt') then
begin
Product.Items.Delete(Product.ItemIndex);
Product.Text := 'Produkt';
end;
if Origin.Enabled and (Origin.Text <> 'Start') then deleteStation(Origin.Text);
if Stop.Enabled and (Stop.Text <> 'Zwischenhalt') then deleteStation(Stop.Text);
if Destination.Enabled and (Destination.Text <> 'Ziel') then deleteStation(Destination.Text);
end;
procedure TScanForm.extButtonClick(Sender: TObject);
var
cmd: string;
begin
cmd := 'gvfs-open "'+DropButton.Hint+'"';
fpSystem(cmd);
end;
procedure TScanForm.DropButtonClick(Sender: TObject);
begin
DeleteFile(DropButton.Hint);
Preview.Picture:=nil;
DropButton.Enabled:=false;
extButton.Enabled:=false;
end;
procedure TScanForm.UpdateFolder();
var
tx: string;
begin
tx := FormatDateTime('YYYY-MM-DD', date) + ' - ';
if (Product.Enabled and (Product.Tag > 0) and not( Product.Text = '') and not (Product.Text = 'Produkt')) then tx := tx + Trim(Product.Text) + ' von ';
if (TypeSelector.Tag > 0) then tx := tx + Trim(TypeSelector.Text);
if (Origin.Enabled and (Origin.Tag > 0)) then tx := tx + ': ' + Trim(Origin.Text);
if (Stop.Enabled and (Stop.Tag > 0) and not (Stop.Text = '')and not (Stop.Text = 'Zwischenhalt')) then tx := tx + ' - ' + Trim(Stop.Text);
if (Destination.Enabled and (Destination.Tag > 0)) then tx := tx + ' - ' + Trim(Destination.Text);
FolderName.Caption := tx;
end;
end.