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