summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Reichel <sre@ring0.de>2013-03-26 15:52:57 +0100
committerSebastian Reichel <sre@ring0.de>2013-03-26 15:52:57 +0100
commit7bfb48ef84384ff0460f273ea5841fba628d2a46 (patch)
tree898d019f33a554f03cac91495adcb7165344382e
parent03a4e9f901cd36792de2172b4ebb8f6e852fe1cd (diff)
downloadserial-barcode-scanner-7bfb48ef84384ff0460f273ea5841fba628d2a46.tar.bz2
code restructure
-rw-r--r--LICENSE2
-rw-r--r--Makefile20
-rw-r--r--invoice/footer-line.svg115
-rw-r--r--invoice/logo.svg198
-rw-r--r--src/Makefile9
-rw-r--r--src/audio/Makefile9
-rw-r--r--src/audio/audio-interface.vala23
-rw-r--r--src/audio/audio.vala (renamed from src/audio.vala)12
-rw-r--r--src/audio/main.vala38
-rw-r--r--src/config/Makefile9
-rw-r--r--src/config/config-interface.vala26
-rw-r--r--src/config/config.vala62
-rw-r--r--src/config/main.vala40
-rw-r--r--src/curses-ui/Makefile9
-rw-r--r--src/curses-ui/clock.vala (renamed from src/ui/clock.vala)15
-rw-r--r--src/curses-ui/curses-ui.vala (renamed from src/ui/curses-ui.vala)15
-rw-r--r--src/curses-ui/dialog.vala (renamed from src/ui/dialog.vala)15
-rw-r--r--src/curses-ui/logo.vala45
-rw-r--r--src/curses-ui/main.vala49
-rw-r--r--src/curses-ui/message_box.vala (renamed from src/ui/message_box.vala)15
-rw-r--r--src/curses-ui/numbers.vala (renamed from src/ui/numbers.vala)15
-rw-r--r--src/curses-ui/status.vala39
-rw-r--r--src/database/Makefile9
-rw-r--r--src/database/database.vala (renamed from src/db.vala)359
-rw-r--r--src/database/db-interface.vala148
-rw-r--r--src/database/main.vala44
-rw-r--r--src/main.vala131
-rw-r--r--src/pdf-invoice/Makefile9
-rw-r--r--src/pdf-invoice/main.vala36
-rw-r--r--src/pdf-invoice/pdf-invoice-interface.vala54
-rw-r--r--src/pdf-invoice/pdf-invoice.vala98
-rw-r--r--src/pdf-invoice/test.vala47
-rw-r--r--src/pgp/Makefile9
-rw-r--r--src/pgp/main.vala53
-rw-r--r--src/pgp/pgp-interface.vala21
-rw-r--r--src/pgp/pgp.vala (renamed from src/admin.vala)82
-rw-r--r--src/scanner-session/Makefile9
-rw-r--r--src/scanner-session/main.vala38
-rw-r--r--src/scanner-session/scannersession-interface.vala25
-rw-r--r--src/scanner-session/scannersession.vala (renamed from src/scannersession.vala)93
-rw-r--r--src/serial-device/Makefile9
-rw-r--r--src/serial-device/main.vala47
-rw-r--r--src/serial-device/serial-device-interface.vala20
-rw-r--r--src/serial-device/serial-device.vala (renamed from src/device.vala)7
-rw-r--r--src/ui/logo.vala30
-rw-r--r--src/ui/status.vala24
-rw-r--r--src/web/Makefile9
-rw-r--r--src/web/csv.vala75
-rw-r--r--src/web/main.vala35
-rw-r--r--src/web/template.vala (renamed from src/template.vala)0
-rw-r--r--src/web/web.vala (renamed from src/web.vala)16
-rw-r--r--src/web/websession.vala (renamed from src/websession.vala)0
52 files changed, 1694 insertions, 623 deletions
diff --git a/LICENSE b/LICENSE
index 934fff2..1f0b9a1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
Files: *
-Copyright: 2012, Sebastian Reichel <sre@ring0.de>
+Copyright: 2012-2013, Sebastian Reichel <sre@ring0.de>
License: ISC
Files: templates/js/sorttable.js
diff --git a/Makefile b/Makefile
index 6836132..b80d992 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,11 @@
-SRC=src/main.vala src/device.vala src/scannersession.vala src/db.vala src/audio.vala src/web.vala src/graph-data.vala src/template.vala src/websession.vala src/admin.vala src/price.vapi src/ui/*.vala
-DEPS=--pkg posix --pkg linux --pkg libsoup-2.4 --pkg sqlite3 --pkg gee-1.0 --pkg gio-2.0 --pkg gstreamer-0.10 --pkg libarchive --pkg gpgme --pkg curses -X -lncursesw
-FLAGS=-X -lgpgme -X -w --enable-experimental --thread --vapidir=vapi
+all:
+ cd src && make all
-barcode-scanner: $(SRC)
- valac-0.16 --output $@ $(FLAGS) $(DEPS) $^
+clean:
+ cd src && make clean
+
+install:
+ cd src && make install
shop.db: sql/tables.sql sql/views.sql sql/trigger.sql
@for file in $^ ; do \
@@ -11,10 +13,4 @@ shop.db: sql/tables.sql sql/views.sql sql/trigger.sql
sqlite3 shop.db < $$file; \
done
-run: barcode-scanner
- ./barcode-scanner /dev/ttyS0
-
-clean:
- @rm -f barcode-scanner src/*.c
-
-.PHONY: clean install
+.PHONY: all clean install
diff --git a/invoice/footer-line.svg b/invoice/footer-line.svg
new file mode 100644
index 0000000..eafdffe
--- /dev/null
+++ b/invoice/footer-line.svg
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Ebene_1"
+ x="0px"
+ y="0px"
+ width="576.26099"
+ height="29.396"
+ viewBox="0 0 576.26098 29.395998"
+ enable-background="new 0 0 841.89 595.28"
+ xml:space="preserve"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="footer-line.svg"><metadata
+ id="metadata33"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs31" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview29"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="0.3610923"
+ inkscape:cx="288.86201"
+ inkscape:cy="-11.394063"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Ebene_1" />
+<polygon
+ points="329.35,297.052 323.291,303.528 317.225,310.001 310.751,303.941 304.276,297.877 310.335,291.406 316.398,284.93 322.877,290.99 "
+ id="polygon3"
+ style="fill:#f5c923"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="184.716,304.111 184.813,295.242 193.685,295.345 193.685,295.345 193.781,286.471 202.654,286.573 211.521,286.674 211.421,295.543 202.553,295.44 202.454,304.312 193.586,304.214 "
+ id="polygon5"
+ style="fill:#e0067a"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="287.866,303.342 279.863,307.165 276.041,299.166 276.041,299.166 268.035,302.989 264.209,294.991 260.383,286.99 268.387,283.159 272.213,291.162 280.215,287.334 284.04,295.335 "
+ id="polygon7"
+ style="fill:#0a8938"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="235.295,305.144 228.732,299.176 222.171,293.209 228.14,286.646 234.701,292.613 240.669,286.053 247.232,292.02 241.262,298.58 247.826,304.548 241.857,311.108 "
+ id="polygon9"
+ style="fill:#1f9ad2"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="132.083,297.597 139.883,293.373 147.685,289.154 155.484,284.93 159.707,292.733 163.928,300.532 156.127,304.753 151.907,296.952 144.105,301.171 136.301,305.396 "
+ id="polygon11"
+ style="fill:#df091d"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="367.672,300.209 359.289,303.099 356.397,294.714 364.784,291.825 373.174,288.937 381.559,286.049 389.942,283.159 392.832,291.545 384.443,294.438 376.059,297.324 "
+ id="polygon13"
+ style="fill:#1f9ad2"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="597.592,298.498 591.533,304.975 585.467,311.447 578.994,305.388 572.52,299.323 578.578,292.853 584.641,286.376 591.119,292.437 "
+ id="polygon15"
+ style="fill:#f5c923"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="452.959,305.558 453.057,296.688 461.928,296.791 461.928,296.791 462.023,287.917 470.896,288.02 479.764,288.12 479.664,296.989 470.795,296.887 470.696,305.758 461.828,305.66 "
+ id="polygon17"
+ style="fill:#e0067a"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="556.109,304.788 548.105,308.611 544.283,300.612 544.283,300.612 536.277,304.436 532.452,296.438 528.626,288.437 536.629,284.605 540.455,292.608 548.457,288.78 552.283,296.781 "
+ id="polygon19"
+ style="fill:#0a8938"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="503.537,306.59 496.975,300.622 490.414,294.655 496.383,288.092 502.943,294.06 508.912,287.499 515.475,293.466 509.505,300.026 516.068,305.994 510.1,312.555 "
+ id="polygon21"
+ style="fill:#1f9ad2"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="400.326,299.043 408.125,294.819 415.928,290.601 423.727,286.376 427.949,294.18 432.171,301.979 424.37,306.199 420.15,298.398 412.348,302.617 404.543,306.842 "
+ id="polygon23"
+ style="fill:#df091d"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="635.914,301.655 627.531,304.545 624.641,296.16 633.027,293.271 641.416,290.383 649.801,287.495 658.186,284.605 661.074,292.991 652.686,295.884 644.301,298.771 "
+ id="polygon25"
+ style="fill:#1f9ad2"
+ transform="translate(-132.083,-283.15901)" />
+<polygon
+ points="676.499,300.49 684.299,296.267 692.101,292.048 699.9,287.823 704.123,295.627 708.344,303.426 700.543,307.646 696.323,299.846 688.521,304.064 680.717,308.289 "
+ id="polygon27"
+ style="fill:#df091d"
+ transform="translate(-132.083,-283.15901)" />
+</svg> \ No newline at end of file
diff --git a/invoice/logo.svg b/invoice/logo.svg
new file mode 100644
index 0000000..81e97a9
--- /dev/null
+++ b/invoice/logo.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Ebene_1"
+ x="0px"
+ y="0px"
+ width="169.8799"
+ height="67.135002"
+ viewBox="0 0 169.87989 67.134999"
+ enable-background="new 0 0 841.89 595.28"
+ xml:space="preserve"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="logo.svg"><metadata
+ id="metadata69"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs67" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="666"
+ inkscape:window-height="604"
+ id="namedview65"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="2"
+ inkscape:cx="104.62281"
+ inkscape:cy="78.477865"
+ inkscape:window-x="72"
+ inkscape:window-y="22"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Ebene_1" />
+<g
+ id="g3"
+ transform="matrix(1.0718448,0,0,1.0718448,-366.21507,-285.37868)">
+ <path
+ d="m 410.758,306.076 -4.622,-7.953 v 7.953 h -3.133 V 290.85 h 3.133 v 6.945 l 4.337,-6.945 h 3.769 l -4.864,7.054 5.412,8.172 h -4.032 z"
+ id="path5"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 421.471,297.422 c -0.285,-0.153 -0.525,-0.219 -0.854,-0.219 -0.658,0 -1.249,0.307 -1.797,0.942 v 7.931 h -2.936 v -7.493 c 0,-1.512 -0.176,-2.65 -0.417,-3.286 l 2.629,-0.701 c 0.264,0.46 0.417,0.964 0.46,1.6 0.636,-0.854 1.534,-1.6 2.629,-1.6 0.438,0 0.636,0.044 1.096,0.241 l -0.81,2.585 z"
+ id="path7"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 425.677,301.388 v 0.087 c 0,1.73 0.854,2.717 2.366,2.717 1.008,0 1.949,-0.372 2.848,-1.117 l 1.14,1.753 c -1.293,1.052 -2.651,1.556 -4.229,1.556 -3.22,0 -5.302,-2.279 -5.302,-5.806 0,-2.016 0.416,-3.352 1.402,-4.447 0.92,-1.03 2.037,-1.511 3.527,-1.511 1.292,0 2.52,0.438 3.242,1.183 1.029,1.052 1.489,2.563 1.489,4.908 v 0.679 h -6.483 z m 3.439,-2.279 c 0,-0.833 -0.088,-1.271 -0.351,-1.687 -0.285,-0.438 -0.701,-0.657 -1.292,-0.657 -1.118,0 -1.753,0.876 -1.753,2.432 v 0.043 h 3.396 v -0.131 z"
+ id="path9"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 441.625,306.646 c -0.679,-0.284 -1.292,-0.788 -1.577,-1.358 -0.219,0.219 -0.459,0.438 -0.679,0.592 -0.548,0.395 -1.337,0.613 -2.256,0.613 -2.498,0 -3.855,-1.271 -3.855,-3.506 0,-2.629 1.817,-3.855 5.389,-3.855 0.219,0 0.416,0 0.657,0.022 v -0.46 c 0,-1.249 -0.241,-1.665 -1.314,-1.665 -0.942,0 -2.037,0.46 -3.242,1.271 l -1.249,-2.103 c 0.592,-0.373 1.029,-0.592 1.818,-0.92 1.095,-0.459 2.038,-0.657 3.066,-0.657 1.885,0 3.178,0.701 3.615,1.949 0.153,0.46 0.219,0.811 0.197,2.016 l -0.066,3.768 c -0.021,1.227 0.066,1.752 1.053,2.498 l -1.557,1.795 z m -2.497,-5.478 c -2.037,0 -2.738,0.373 -2.738,1.709 0,0.877 0.548,1.469 1.293,1.469 0.548,0 1.095,-0.285 1.533,-0.768 l 0.044,-2.41 h -0.132 z"
+ id="path11"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 448.46,306.339 c -1.489,0 -2.672,-0.657 -3.022,-1.644 -0.175,-0.482 -0.197,-0.701 -0.197,-1.73 v -6.09 h -1.117 v -2.015 h 1.117 c 0,-1.095 0,-1.818 0.109,-2.651 l 2.979,-0.745 c -0.109,1.029 -0.175,2.256 -0.175,3.396 h 2.629 l -0.745,2.015 h -1.884 v 5.63 c 0,1.425 0.263,1.796 1.271,1.796 0.263,0 0.525,-0.064 1.052,-0.219 l 0.372,1.753 c -0.855,0.351 -1.621,0.504 -2.389,0.504 z"
+ id="path13"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 454.179,293.588 c -0.986,0 -1.796,-0.811 -1.796,-1.818 0,-1.008 0.832,-1.818 1.84,-1.818 0.985,0 1.774,0.811 1.774,1.818 0,1.008 -0.81,1.818 -1.818,1.818 z m -1.468,12.488 v -11.02 l 2.936,-0.46 v 11.48 h -2.936 z"
+ id="path15"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 463.467,306.076 h -2.431 l -4.075,-11.042 3.002,-0.373 1.62,5.061 c 0.241,0.744 0.57,1.972 0.724,2.694 0.087,-0.657 0.328,-1.73 0.679,-2.848 l 1.512,-4.71 h 3.066 l -4.097,11.218 z"
+ id="path17"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 470.128,293.588 c -0.986,0 -1.797,-0.811 -1.797,-1.818 0,-1.008 0.832,-1.818 1.84,-1.818 0.985,0 1.774,0.811 1.774,1.818 0,1.008 -0.81,1.818 -1.817,1.818 z m -1.469,12.488 v -11.02 l 2.937,-0.46 v 11.48 h -2.937 z"
+ id="path19"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 477.882,306.339 c -1.489,0 -2.672,-0.657 -3.022,-1.644 -0.176,-0.482 -0.198,-0.701 -0.198,-1.73 v -6.09 h -1.117 v -2.015 h 1.117 c 0,-1.095 0,-1.818 0.109,-2.651 l 2.979,-0.745 c -0.109,1.029 -0.175,2.256 -0.175,3.396 h 2.629 l -0.745,2.015 h -1.884 v 5.63 c 0,1.425 0.264,1.796 1.271,1.796 0.263,0 0.525,-0.064 1.052,-0.219 l 0.372,1.753 c -0.854,0.351 -1.622,0.504 -2.388,0.504 z"
+ id="path21"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 489.734,306.646 c -0.68,-0.284 -1.293,-0.788 -1.578,-1.358 -0.416,0.395 -0.46,0.438 -0.679,0.592 -0.548,0.395 -1.336,0.613 -2.257,0.613 -2.497,0 -3.855,-1.271 -3.855,-3.506 0,-2.629 1.818,-3.855 5.39,-3.855 0.219,0 0.351,0 0.657,0.022 v -0.46 c 0,-1.249 -0.241,-1.665 -1.314,-1.665 -0.941,0 -2.038,0.46 -3.242,1.271 l -1.249,-2.103 c 0.723,-0.46 1.029,-0.592 1.818,-0.92 1.096,-0.438 2.037,-0.657 3.067,-0.657 1.884,0 3.176,0.701 3.614,1.949 0.153,0.46 0.219,0.811 0.197,2.016 l -0.065,3.768 c -0.022,1.184 0.065,1.752 1.051,2.498 l -1.555,1.795 z m -6.003,-12.729 c -0.941,0 -1.73,-0.789 -1.73,-1.753 0,-0.964 0.811,-1.752 1.774,-1.752 0.941,0 1.709,0.788 1.709,1.752 0,0.965 -0.789,1.753 -1.753,1.753 z m 3.505,7.251 c -2.037,0 -2.738,0.373 -2.738,1.709 0,0.877 0.548,1.469 1.293,1.469 0.547,0 1.096,-0.285 1.533,-0.768 l 0.044,-2.41 h -0.132 z m 1.118,-7.251 c -0.963,0 -1.73,-0.789 -1.73,-1.753 0,-0.964 0.789,-1.752 1.774,-1.752 0.942,0 1.709,0.788 1.709,1.752 -0.001,0.965 -0.79,1.753 -1.753,1.753 z"
+ id="path23"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 496.569,306.339 c -1.489,0 -2.673,-0.657 -3.023,-1.644 -0.175,-0.482 -0.197,-0.701 -0.197,-1.73 v -6.09 h -1.117 v -2.015 h 1.117 c 0,-1.095 0,-1.818 0.11,-2.651 l 2.979,-0.745 c -0.11,1.029 -0.176,2.256 -0.176,3.396 h 2.629 l -0.745,2.015 h -1.884 v 5.63 c 0,1.425 0.263,1.796 1.271,1.796 0.264,0 0.525,-0.064 1.052,-0.219 l 0.372,1.753 c -0.854,0.351 -1.621,0.504 -2.388,0.504 z"
+ id="path25"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 387.098,328.84 c -1.489,0 -2.672,-0.657 -3.022,-1.643 -0.176,-0.482 -0.197,-0.701 -0.197,-1.73 v -6.091 h -1.117 v -2.015 h 1.117 c 0,-1.096 0,-1.818 0.109,-2.651 l 2.979,-0.745 c -0.109,1.029 -0.176,2.257 -0.176,3.396 h 2.629 l -0.745,2.015 h -1.884 v 5.63 c 0,1.424 0.264,1.797 1.271,1.797 0.264,0 0.526,-0.066 1.052,-0.219 l 0.372,1.752 c -0.854,0.351 -1.622,0.504 -2.388,0.504 z"
+ id="path27"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 396.935,319.924 c -0.285,-0.153 -0.525,-0.219 -0.854,-0.219 -0.657,0 -1.248,0.307 -1.796,0.941 v 7.931 h -2.937 v -7.492 c 0,-1.512 -0.175,-2.651 -0.416,-3.286 l 2.629,-0.701 c 0.263,0.461 0.417,0.964 0.46,1.6 0.636,-0.854 1.534,-1.6 2.629,-1.6 0.438,0 0.636,0.044 1.096,0.241 l -0.811,2.585 z"
+ id="path29"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 400.418,316.09 c -0.986,0 -1.797,-0.811 -1.797,-1.818 0,-1.007 0.832,-1.818 1.84,-1.818 0.985,0 1.774,0.811 1.774,1.818 0,1.007 -0.81,1.818 -1.817,1.818 z m -1.469,12.487 v -11.019 l 2.937,-0.461 v 11.479 h -2.937 z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 410.232,314.863 c -0.636,-0.307 -0.855,-0.373 -1.206,-0.373 -0.744,0 -1.227,0.461 -1.227,1.271 v 1.6 h 2.848 l -0.744,2.015 h -2.081 v 9.201 h -2.87 v -9.201 h -1.008 v -2.015 h 1.073 c -0.065,-0.461 -0.109,-1.03 -0.109,-1.534 0,-2.212 1.314,-3.483 3.614,-3.483 0.965,0 1.753,0.197 2.651,0.701 l -0.941,1.818 z"
+ id="path33"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 416.892,314.863 c -0.636,-0.307 -0.854,-0.373 -1.205,-0.373 -0.744,0 -1.227,0.461 -1.227,1.271 v 1.6 h 2.848 l -0.744,2.015 h -2.082 v 9.201 h -2.87 v -9.201 h -1.007 v -2.015 h 1.073 c -0.066,-0.461 -0.109,-1.03 -0.109,-1.534 0,-2.212 1.313,-3.483 3.614,-3.483 0.964,0 1.753,0.197 2.65,0.701 l -0.941,1.818 z"
+ id="path35"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 421.601,328.84 c -1.489,0 -2.672,-0.657 -3.022,-1.643 -0.175,-0.482 -0.197,-0.701 -0.197,-1.73 v -6.091 h -1.117 v -2.015 h 1.117 c 0,-1.096 0,-1.818 0.109,-2.651 l 2.979,-0.745 c -0.109,1.029 -0.175,2.257 -0.175,3.396 h 2.628 l -0.745,2.015 h -1.883 v 5.63 c 0,1.424 0.263,1.797 1.27,1.797 0.264,0 0.526,-0.066 1.053,-0.219 l 0.372,1.752 c -0.855,0.351 -1.622,0.504 -2.389,0.504 z"
+ id="path37"
+ inkscape:connector-curvature="0"
+ style="fill:#858585" />
+ <path
+ d="m 439.281,315.893 h -3.638 v 12.685 h -3.11 v -12.685 h -3.725 v -2.541 h 10.976 l -0.503,2.541 z"
+ id="path39"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 441.646,323.889 v 0.088 c 0,1.73 0.855,2.717 2.366,2.717 1.008,0 1.95,-0.373 2.849,-1.117 l 1.139,1.752 c -1.292,1.052 -2.65,1.556 -4.228,1.556 -3.221,0 -5.302,-2.278 -5.302,-5.806 0,-2.016 0.416,-3.352 1.402,-4.447 0.92,-1.029 2.037,-1.512 3.526,-1.512 1.293,0 2.52,0.439 3.242,1.184 1.03,1.051 1.49,2.563 1.49,4.906 v 0.68 h -6.484 z m 3.441,-2.279 c 0,-0.832 -0.088,-1.271 -0.351,-1.687 -0.285,-0.438 -0.701,-0.657 -1.293,-0.657 -1.117,0 -1.752,0.876 -1.752,2.432 v 0.044 h 3.396 v -0.132 z"
+ id="path41"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 457.18,328.139 c -0.789,0.461 -1.665,0.701 -2.738,0.701 -3.089,0 -4.886,-2.146 -4.886,-5.783 0,-2.586 0.986,-4.294 2.301,-5.191 0.744,-0.504 1.84,-0.833 2.782,-0.833 0.744,0 1.555,0.175 2.168,0.504 0.417,0.219 0.613,0.372 1.096,0.788 l -1.424,1.928 c -0.592,-0.547 -1.227,-0.876 -1.774,-0.876 -1.314,0 -1.906,1.14 -1.906,3.769 0,1.467 0.197,2.344 0.57,2.826 0.306,0.395 0.81,0.635 1.313,0.635 0.68,0 1.293,-0.285 2.016,-0.92 l 0.176,-0.153 1.336,1.774 c -0.439,0.436 -0.636,0.59 -1.03,0.831 z"
+ id="path43"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 466.074,328.577 v -7.536 c 0,-1.117 -0.307,-1.533 -1.139,-1.533 -0.724,0 -1.665,0.438 -2.323,1.029 v 8.04 h -2.979 v -12.969 c 0,-1.052 -0.087,-2.104 -0.219,-2.563 l 3.002,-0.701 c 0.131,0.613 0.196,1.666 0.196,2.738 v 2.234 c 0,0.352 -0.043,0.811 -0.043,0.942 0.767,-0.723 2.037,-1.204 3.176,-1.204 1.425,0 2.563,0.613 2.914,1.599 0.22,0.636 0.284,1.008 0.284,2.081 v 7.843 h -2.869 z"
+ id="path45"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 477.97,328.577 v -7.296 c 0,-1.27 -0.219,-1.643 -0.985,-1.643 -0.592,0 -1.359,0.395 -2.037,1.008 v 7.931 h -2.936 v -8.128 c 0,-0.963 -0.132,-1.884 -0.395,-2.629 l 2.606,-0.744 c 0.263,0.46 0.416,0.941 0.416,1.402 0.438,-0.307 0.812,-0.57 1.293,-0.833 0.591,-0.307 1.358,-0.481 2.016,-0.481 1.249,0 2.344,0.656 2.694,1.621 0.153,0.416 0.219,0.897 0.219,1.599 v 8.193 h -2.891 z"
+ id="path47"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 485.396,316.09 c -0.985,0 -1.797,-0.811 -1.797,-1.818 0,-1.007 0.832,-1.818 1.84,-1.818 0.986,0 1.775,0.811 1.775,1.818 0,1.007 -0.81,1.818 -1.818,1.818 z m -1.467,12.487 v -11.019 l 2.936,-0.461 v 11.479 h -2.936 z"
+ id="path49"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <path
+ d="m 489.931,328.577 v -12.64 c 0,-0.986 -0.021,-1.754 -0.196,-2.914 l 2.957,-0.724 c 0.132,0.833 0.176,2.147 0.176,3.638 v 12.64 h -2.937 z m 6.77,0 -3.769,-6.353 2.87,-4.863 h 3.526 l -3.57,4.688 4.403,6.528 h -3.46 z"
+ id="path51"
+ inkscape:connector-curvature="0"
+ style="fill:#4d4d4d" />
+ <polygon
+ points="369.275,326.967 364.967,322.097 360.654,317.223 365.527,312.914 370.399,308.603 374.71,313.477 379.019,318.35 374.146,322.658 "
+ id="polygon53"
+ style="fill:#f5c923" />
+ <polygon
+ points="377.967,284.888 376.729,278.502 375.488,272.118 381.873,270.877 383.112,277.263 389.498,276.023 390.741,282.407 391.979,288.793 385.594,290.034 384.354,283.648 384.354,283.648 "
+ id="polygon55"
+ style="fill:#0a8938" />
+ <polygon
+ points="363.913,292.584 357.809,294.826 351.703,297.07 349.459,290.964 355.565,288.72 353.323,282.615 359.428,280.373 365.535,278.13 367.777,284.235 361.672,286.479 361.672,286.479 "
+ id="polygon57"
+ style="fill:#e0067a" />
+ <polygon
+ points="399.899,275.099 396.73,269.419 402.411,266.25 405.578,271.93 411.259,268.761 414.428,274.441 408.749,277.612 403.068,280.779 397.39,283.949 394.218,278.269 "
+ id="polygon59"
+ style="fill:#1f9ad2" />
+ <polygon
+ points="372.111,294.115 375.302,288.447 380.97,291.638 377.778,297.305 383.446,300.498 389.115,303.689 385.925,309.355 380.257,306.166 374.587,302.974 368.921,299.783 "
+ id="polygon61"
+ style="fill:#df091d" />
+ <polygon
+ points="347.201,312.941 344.437,307.053 341.668,301.166 347.557,298.4 350.323,304.29 353.088,310.176 355.852,316.063 358.618,321.949 352.731,324.714 349.966,318.827 "
+ id="polygon63"
+ style="fill:#2299d1" />
+</g>
+</svg> \ No newline at end of file
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..da0bf41
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,9 @@
+DAEMONS=audio config curses-ui database pdf-invoice pgp scanner-session serial-device web
+
+all:
+ @$(foreach dir,$(DAEMONS),cd $(dir) && make all && cd ..;)
+
+clean:
+ @$(foreach dir,$(DAEMONS),cd $(dir) && make clean && cd ..;)
+
+.PHONY: all clean
diff --git a/src/audio/Makefile b/src/audio/Makefile
new file mode 100644
index 0000000..a6fd629
--- /dev/null
+++ b/src/audio/Makefile
@@ -0,0 +1,9 @@
+all: audio
+
+audio: main.vala audio.vala audio-interface.vala
+ valac -o $@ --pkg gstreamer-0.10 --pkg gio-2.0 $^
+
+clean:
+ rm -rf audio
+
+.PHONY: all clean
diff --git a/src/audio/audio-interface.vala b/src/audio/audio-interface.vala
new file mode 100644
index 0000000..89d4a6f
--- /dev/null
+++ b/src/audio/audio-interface.vala
@@ -0,0 +1,23 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.AudioPlayer")]
+public interface AudioPlayer : Object {
+ public abstract signal void end_of_stream();
+
+ public abstract void play_system(string file) throws IOError;
+ public abstract string get_random_user_theme() throws IOError;
+ public abstract void play_user(string theme, string type) throws IOError;
+}
diff --git a/src/audio.vala b/src/audio/audio.vala
index 3f22e6d..0225c01 100644
--- a/src/audio.vala
+++ b/src/audio/audio.vala
@@ -1,4 +1,4 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+/* Copyright 2012-2013, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -13,14 +13,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-public class AudioPlayer {
+[DBus (name = "io.mainframe.shopsystem.AudioPlayer")]
+public class AudioPlayerImplementation {
private dynamic Gst.Element p;
string path;
public signal void end_of_stream();
private bool bus_callback(Gst.Bus bus, Gst.Message message) {
- switch (message.type) {
+ switch(message.type) {
case Gst.MessageType.EOS:
end_of_stream();
break;
@@ -29,7 +30,7 @@ public class AudioPlayer {
return true;
}
- public AudioPlayer() {
+ public AudioPlayerImplementation() {
path = Environment.get_current_dir()+"/sounds/";
var alsa = Gst.ElementFactory.make("alsasink", "alsa");
@@ -57,7 +58,8 @@ public class AudioPlayer {
return result;
} catch (Error e) {
- write_to_log("Error: %s\n", e.message);
+ // TODO
+ //write_to_log("Error: %s\n", e.message);
return {};
}
}
diff --git a/src/audio/main.vala b/src/audio/main.vala
new file mode 100644
index 0000000..f3f64f4
--- /dev/null
+++ b/src/audio/main.vala
@@ -0,0 +1,38 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+AudioPlayerImplementation player;
+
+public static int main(string[] args) {
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.AudioPlayer",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/audio", player);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/config/Makefile b/src/config/Makefile
new file mode 100644
index 0000000..0e81ee9
--- /dev/null
+++ b/src/config/Makefile
@@ -0,0 +1,9 @@
+all: config
+
+config: main.vala config.vala config-interface.vala
+ valac -o $@ --pkg gio-2.0 $^
+
+clean:
+ rm -rf config
+
+.PHONY: all clean
diff --git a/src/config/config-interface.vala b/src/config/config-interface.vala
new file mode 100644
index 0000000..c34e3a7
--- /dev/null
+++ b/src/config/config-interface.vala
@@ -0,0 +1,26 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.Config")]
+public interface Config : Object {
+ public abstract bool has_group(string group_name) throws IOError, KeyFileError;
+ public abstract bool has_key(string group_name, string key) throws IOError, KeyFileError;
+ public abstract string get_string(string group_name, string key) throws IOError, KeyFileError;
+ public abstract bool get_boolean(string group_name, string key) throws IOError, KeyFileError;
+ public abstract int get_integer(string group_name, string key) throws IOError, KeyFileError;
+ public abstract int64 get_int64(string group_name, string key) throws IOError, KeyFileError;
+ public abstract uint64 get_uint64(string group_name, string key) throws IOError, KeyFileError;
+ public abstract double get_double(string group_name, string key) throws IOError, KeyFileError;
+}
diff --git a/src/config/config.vala b/src/config/config.vala
new file mode 100644
index 0000000..60fd835
--- /dev/null
+++ b/src/config/config.vala
@@ -0,0 +1,62 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.Config")]
+public class Cfg {
+
+ private KeyFile file;
+
+ public Cfg(string file) {
+ try {
+ this.file = new KeyFile();
+ this.file.load_from_file(file, KeyFileFlags.NONE);
+ } catch(Error e) {
+ error("Could not load configuration file: %s", e.message);
+ }
+ }
+
+ public bool has_group(string group_name) throws KeyFileError {
+ return file.has_group(group_name);
+ }
+
+ public bool has_key(string group_name, string key) throws KeyFileError {
+ return file.has_key(group_name, key);
+ }
+
+ public string get_string(string group_name, string key) throws KeyFileError {
+ return file.get_string(group_name, key);
+ }
+
+ public bool get_boolean(string group_name, string key) throws KeyFileError {
+ return file.get_boolean(group_name, key);
+ }
+
+ public int get_integer(string group_name, string key) throws KeyFileError {
+ return file.get_integer(group_name, key);
+ }
+
+ public int64 get_int64(string group_name, string key) throws KeyFileError {
+ return file.get_int64(group_name, key);
+ }
+
+ public uint64 get_uint64(string group_name, string key) throws KeyFileError {
+ return file.get_uint64(group_name, key);
+ }
+
+ public double get_double(string group_name, string key) throws KeyFileError {
+ return file.get_double(group_name, key);
+ }
+
+}
diff --git a/src/config/main.vala b/src/config/main.vala
new file mode 100644
index 0000000..aa971d6
--- /dev/null
+++ b/src/config/main.vala
@@ -0,0 +1,40 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+Cfg cfg;
+
+public static int main(string[] args) {
+ cfg = new Cfg("../../ktt-shopsystem.cfg");
+
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.Config",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/config", cfg);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/curses-ui/Makefile b/src/curses-ui/Makefile
new file mode 100644
index 0000000..5d168ba
--- /dev/null
+++ b/src/curses-ui/Makefile
@@ -0,0 +1,9 @@
+all: curses-ui
+
+curses-ui: clock.vala curses-ui.vala dialog.vala logo.vala main.vala message_box.vala numbers.vala status.vala ../audio/audio-interface.vala
+ valac -o $@ --pkg curses -X -lncursesw --pkg posix --pkg gio-2.0 $^
+
+clean:
+ rm -rf curses-ui
+
+.PHONY: all clean
diff --git a/src/ui/clock.vala b/src/curses-ui/clock.vala
index e38ad9c..dd3ddcd 100644
--- a/src/ui/clock.vala
+++ b/src/curses-ui/clock.vala
@@ -1,3 +1,18 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
using Curses;
public class ClockWindow {
diff --git a/src/ui/curses-ui.vala b/src/curses-ui/curses-ui.vala
index 6676eea..ec007f2 100644
--- a/src/ui/curses-ui.vala
+++ b/src/curses-ui/curses-ui.vala
@@ -1,3 +1,18 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
public class CursesUI {
MessageBox messages;
Dialog dialog;
diff --git a/src/ui/dialog.vala b/src/curses-ui/dialog.vala
index 29782e5..a8585d4 100644
--- a/src/ui/dialog.vala
+++ b/src/curses-ui/dialog.vala
@@ -1,3 +1,18 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
using Curses;
public class Dialog {
diff --git a/src/curses-ui/logo.vala b/src/curses-ui/logo.vala
new file mode 100644
index 0000000..dbc716d
--- /dev/null
+++ b/src/curses-ui/logo.vala
@@ -0,0 +1,45 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using Curses;
+
+public class Logo {
+ Window win;
+
+ public Logo() {
+ win = new Window(8, COLS - 2, 0, 1);
+ win.bkgdset(COLOR_PAIR(1) | Attribute.BOLD);
+
+ win.addstr("\n");
+ win.addstr(" _ ___ _____ ____ _ \n");
+ win.addstr(" | |/ / ||_ _| / ___|| |__ ___ _ __ \n");
+ win.addstr(" | ' /| __|| | \\___ \\| '_ \\ / _ \\| '_ \\ \n");
+ win.addstr(" | . \\| |_ | | ___) | | | | (_) | |_) )\n");
+ win.addstr(" |_|\\_\\\\__||_| |____/|_| |_|\\___/| .__/ \n");
+ win.addstr(" |_| \n");
+
+ win.clrtobot();
+
+ win.box(0, 0);
+
+ win.refresh();
+ }
+
+ public void redraw() {
+ win.touchwin();
+ win.refresh();
+ }
+
+}
diff --git a/src/curses-ui/main.vala b/src/curses-ui/main.vala
new file mode 100644
index 0000000..1d79c43
--- /dev/null
+++ b/src/curses-ui/main.vala
@@ -0,0 +1,49 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public MainLoop loop;
+
+public static int main(string[] args) {
+ /* handle unix signals */
+ Unix.signal_add(Posix.SIGTERM, handle_signals);
+ Unix.signal_add(Posix.SIGINT, handle_signals);
+
+ AudioPlayer audio = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio");
+
+ var ui = new CursesUI();
+
+ ui.log("KtT Shop System has been started");
+ audio.play_system("startup.ogg");
+
+ /* run mainloop */
+ loop.run();
+
+ ui.log("Stopping Shop System");
+ audio.play_system("shutdown.ogg");
+
+ /* we need to run the mainloop to play audio */
+ audio.end_of_stream.connect(() => { loop.quit(); });
+ loop.run();
+
+ /* leave curses mode */
+ ui.exit();
+
+ return 0;
+}
+
+bool handle_signals() {
+ loop.quit();
+ return false;
+}
diff --git a/src/ui/message_box.vala b/src/curses-ui/message_box.vala
index 4f9c3f6..cc258b4 100644
--- a/src/ui/message_box.vala
+++ b/src/curses-ui/message_box.vala
@@ -1,3 +1,18 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
using Curses;
public class MessageBox {
diff --git a/src/ui/numbers.vala b/src/curses-ui/numbers.vala
index 8ee00d5..200cf63 100644
--- a/src/ui/numbers.vala
+++ b/src/curses-ui/numbers.vala
@@ -1,3 +1,18 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
public class AsciiNumbers {
public string[] zero = {
diff --git a/src/curses-ui/status.vala b/src/curses-ui/status.vala
new file mode 100644
index 0000000..5be6a00
--- /dev/null
+++ b/src/curses-ui/status.vala
@@ -0,0 +1,39 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using Curses;
+
+public class StatusPanel {
+ Window win;
+
+ public StatusPanel() {
+ win = new Window(1, COLS - 2, LINES-1, 1);
+ win.bkgdset(COLOR_PAIR(2) | Attribute.BOLD);
+
+ win.clrtobot();
+ win.refresh();
+ }
+
+ public void set(string msg) {
+ win.mvaddstr(0,1, msg);
+ win.clrtobot();
+ win.refresh();
+ }
+
+ public void redraw() {
+ win.touchwin();
+ win.refresh();
+ }
+}
diff --git a/src/database/Makefile b/src/database/Makefile
new file mode 100644
index 0000000..70253d2
--- /dev/null
+++ b/src/database/Makefile
@@ -0,0 +1,9 @@
+all: db
+
+db: main.vala database.vala db-interface.vala ../price.vapi
+ valac -o $@ --pkg sqlite3 --pkg gee-1.0 --pkg gio-2.0 $^
+
+clean:
+ rm -rf db
+
+.PHONY: all clean
diff --git a/src/db.vala b/src/database/database.vala
index dc1c834..640e175 100644
--- a/src/db.vala
+++ b/src/database/database.vala
@@ -1,4 +1,4 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+/* Copyright 2012-2013, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,109 +15,8 @@
public const int day_in_seconds = 24*60*60;
-public struct StockEntry {
- public string id;
- public string name;
- public int amount;
- public string memberprice;
- public string guestprice;
-}
-
-public struct PriceEntry {
- public int64 valid_from;
- public Price memberprice;
- public Price guestprice;
-}
-
-public struct RestockEntry {
- public int64 timestamp;
- public int amount;
- public string price;
- public int supplier;
- public int64 best_before_date;
-}
-
-public struct Supplier {
- public int64 id;
- public string name;
- public string postal_code;
- public string city;
- public string street;
- public string phone;
- public string website;
-}
-
-public struct UserInfo {
- public int id;
- public string firstname;
- public string lastname;
- public string email;
- public string gender;
- public string street;
- public int postcode;
- public string city;
- public string pgp;
-
- public bool equals(UserInfo x) {
- if(id != x.id) return false;
- if(firstname != x.firstname) return false;
- if(lastname != x.lastname) return false;
- if(email != x.email) return false;
- if(gender != x.gender) return false;
- if(street != x.street) return false;
- if(postcode != x.postcode) return false;
- if(city != x.city) return false;
- if(pgp != x.pgp) return false;
-
- return true;
- }
-
- public bool exists_in_db() {
- if(id in db.get_member_ids())
- return true;
- else
- return false;
- }
-
- public bool equals_db() {
- return this.equals(db.get_user_info(id));
- }
-}
-
-public struct UserAuth {
- public int id;
- public bool disabled;
- public bool superuser;
-}
-
-public struct Product {
- public uint64 ean;
- public string name;
-}
-
-public struct InvoiceEntry {
- public int64 timestamp;
- Product product;
- Price price;
-}
-
-public struct StatsInfo {
- public int count_articles;
- public int count_users;
- public Price stock_value;
- public Price sales_total;
- public Price profit_total;
- public Price sales_today;
- public Price profit_today;
- public Price sales_this_month;
- public Price profit_this_month;
- public Price sales_per_day;
- public Price profit_per_day;
- public Price sales_per_month;
- public Price profit_per_month;
-}
-
-public class Database {
+[DBus (name = "io.mainframe.shopsystem.Database")]
+public class DataBase : Object {
private class Statement {
private Sqlite.Statement stmt;
@@ -158,7 +57,8 @@ public class Database {
}
public string column_text(int index) {
- return stmt.column_text(index);
+ var result = stmt.column_text(index);
+ return (result != null) ? result : "";
}
public int64 column_int64(int index) {
@@ -169,8 +69,10 @@ public class Database {
private Sqlite.Database db;
private static Gee.HashMap<string,string> queries = new Gee.HashMap<string,string>();
private static Gee.HashMap<string,Statement> statements = new Gee.HashMap<string,Statement>();
+ //private static HashTable<string,string> queries = new HashTable<string,string>(null, null);
+ //private static HashTable<string,Statement> statements = new HashTable<string,Statement>(null, null);
- public Database(string file) {
+ public DataBase(string file) {
int rc;
rc = Sqlite.Database.open(file, out db);
@@ -224,10 +126,15 @@ public class Database {
foreach(var entry in queries.entries) {
statements[entry.key] = new Statement(db, entry.value);
}
+#if 0
+ foreach(var key in queries.get_keys()) {
+ statements[key] = new Statement(db, queries[key]);
+ }
+#endif
}
- public Gee.HashMap<string,string> get_products() {
- var result = new Gee.HashMap<string,string>(null, null);
+ public GLib.HashTable<string,string> get_products() {
+ var result = new GLib.HashTable<string,string>(null, null);
statements["products"].reset();
while(statements["products"].step() == Sqlite.ROW)
@@ -236,6 +143,7 @@ public class Database {
return result;
}
+#if 0
public stock get_stats_stock() {
var result = new stock();
var now = time_t();
@@ -265,7 +173,9 @@ public class Database {
return result;
}
+#endif
+#if 0
public profit_per_product get_stats_profit_per_products() {
var result = new profit_per_product();
@@ -281,7 +191,9 @@ public class Database {
return result;
}
+#endif
+#if 0
public profit_per_weekday get_stats_profit_per_weekday() {
var result = new profit_per_weekday();
@@ -313,7 +225,9 @@ public class Database {
return result;
}
+#endif
+#if 0
public profit_per_day get_stats_profit_per_day() {
var result = new profit_per_day();
var to = time_t();
@@ -340,11 +254,12 @@ public class Database {
return result;
}
+#endif
- public Gee.List<StockEntry?> get_stock() {
- var result = new Gee.ArrayList<StockEntry?>();
- statements["stock_status"].reset();
+ public StockEntry[] get_stock() {
+ StockEntry[] result = {};
+ statements["stock_status"].reset();
while(statements["stock_status"].step() == Sqlite.ROW) {
StockEntry entry = {
statements["stock_status"].column_text(0),
@@ -360,17 +275,17 @@ public class Database {
entry.memberprice = @"$mprice";
entry.guestprice = @"$gprice";
- result.add(entry);
+ result += entry;
}
return result;
}
- public Gee.List<PriceEntry?> get_prices(uint64 product) {
- var result = new Gee.ArrayList<PriceEntry?>();
+ public PriceEntry[] get_prices(uint64 product) {
+ PriceEntry[] result = {};
+
statements["prices"].reset();
statements["prices"].bind_text(1, "%llu".printf(product));
-
while(statements["prices"].step() == Sqlite.ROW) {
PriceEntry entry = {
statements["prices"].column_int64(0),
@@ -378,17 +293,17 @@ public class Database {
statements["prices"].column_int(2)
};
- result.add(entry);
+ result += entry;
}
return result;
}
- public Gee.List<RestockEntry?> get_restocks(uint64 product) {
- var result = new Gee.ArrayList<RestockEntry?>();
+ public RestockEntry[] get_restocks(uint64 product) {
+ RestockEntry[] result = {};
+
statements["restocks"].reset();
statements["restocks"].bind_text(1, "%llu".printf(product));
-
while(statements["restocks"].step() == Sqlite.ROW) {
RestockEntry entry = {
statements["restocks"].column_int64(0),
@@ -400,13 +315,13 @@ public class Database {
entry.supplier = statements["restocks"].column_int(3);
entry.best_before_date = statements["restocks"].column_int64(4);
- result.add(entry);
+ result += entry;
}
return result;
}
- public bool buy(int32 user, uint64 article) {
+ public bool buy(int32 user, uint64 article) throws DatabaseError {
int rc = 0;
int64 timestamp = (new DateTime.now_utc()).to_unix();
@@ -417,12 +332,12 @@ public class Database {
rc = statements["purchase"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
return true;
}
- public string get_product_name(uint64 article) {
+ public string get_product_name(uint64 article) throws DatabaseError {
statements["product_name"].reset();
statements["product_name"].bind_text(1, "%llu".printf(article));
@@ -432,13 +347,13 @@ public class Database {
case Sqlite.ROW:
return statements["product_name"].column_text(0);
case Sqlite.DONE:
- return "unbekanntes Produkt: %llu".printf(article);
+ throw new DatabaseError.PRODUCT_NOT_FOUND("unknown product: %llu", article);
default:
- return "[internal error: %d]".printf(rc);
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
}
- public int get_product_amount(uint64 article) {
+ public int get_product_amount(uint64 article) throws DatabaseError {
statements["product_amount"].reset();
statements["product_amount"].bind_text(1, "%llu".printf(article));
@@ -448,15 +363,13 @@ public class Database {
case Sqlite.ROW:
return statements["product_amount"].column_int(0);
case Sqlite.DONE:
- warning("unbekanntes Produkt: %llu".printf(article));
- return -1;
+ throw new DatabaseError.PRODUCT_NOT_FOUND("unknown product: %llu", article);
default:
- warning("[internal error: %d]".printf(rc));
- return -1;
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
}
- public Price get_product_price(int user, uint64 article) {
+ public Price get_product_price(int user, uint64 article) throws DatabaseError {
int64 timestamp = (new DateTime.now_utc()).to_unix();
bool member = user != 0;
@@ -473,15 +386,13 @@ public class Database {
else
return statements["price"].column_int(1);
case Sqlite.DONE:
- write_to_log("unbekanntes Produkt: %llu\n", article);
- return 0;
+ throw new DatabaseError.PRODUCT_NOT_FOUND("unknown product: %llu", article);
default:
- write_to_log("[internal error: %d]\n", rc);
- return 0;
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
}
- public bool undo(int32 user) {
+ public bool undo(int32 user) throws DatabaseError {
uint64 pid = 0;
int rc = 0;
@@ -496,10 +407,9 @@ public class Database {
write_to_log("Remove purchase of %s", pname);
break;
case Sqlite.DONE:
- write_to_log("Error: undo not possible without purchases");
- return false;
+ throw new DatabaseError.PRODUCT_NOT_FOUND("undo not possible without purchases");
default:
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
statements["undo"].reset();
@@ -507,42 +417,37 @@ public class Database {
rc = statements["undo"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
return true;
}
- public bool restock(int user, uint64 product, uint amount, uint price, int supplier, int64 best_before_date) {
- if(user > 0) {
- int rc = 0;
- int64 timestamp = (new DateTime.now_utc()).to_unix();
-
- statements["stock"].reset();
- statements["stock"].bind_int(1, user);
- statements["stock"].bind_text(2, @"$product");
- statements["stock"].bind_text(3, @"$amount");
- statements["stock"].bind_text(4, @"$price");
- statements["stock"].bind_int64(5, timestamp);
- if(supplier > 0)
- statements["stock"].bind_int(6, supplier);
- else
- statements["stock"].bind_null(6);
- if(best_before_date > 0)
- statements["stock"].bind_int64(7, best_before_date);
- else
- statements["stock"].bind_null(7);
-
- rc = statements["stock"].step();
- if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ public void restock(int user, uint64 product, uint amount, uint price, int supplier, int64 best_before_date) throws DatabaseError {
+ int rc = 0;
+ int64 timestamp = (new DateTime.now_utc()).to_unix();
- return true;
- }
+ statements["stock"].reset();
+ statements["stock"].bind_int(1, user);
+ statements["stock"].bind_text(2, @"$product");
+ statements["stock"].bind_text(3, @"$amount");
+ statements["stock"].bind_text(4, @"$price");
+ statements["stock"].bind_int64(5, timestamp);
+ if(supplier > 0)
+ statements["stock"].bind_int(6, supplier);
+ else
+ statements["stock"].bind_null(6);
+ if(best_before_date > 0)
+ statements["stock"].bind_int64(7, best_before_date);
+ else
+ statements["stock"].bind_null(7);
- return false;
+ rc = statements["stock"].step();
+
+ if(rc != Sqlite.DONE)
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- public bool new_product(uint64 id, string name, int memberprice, int guestprice) {
+ public void new_product(uint64 id, string name, int memberprice, int guestprice) throws DatabaseError {
statements["product_create"].reset();
statements["product_create"].bind_text(1, @"$id");
statements["product_create"].bind_text(2, name);
@@ -550,14 +455,13 @@ public class Database {
int rc = statements["product_create"].step();
if(rc != Sqlite.DONE) {
- warning("[internal error: %d]".printf(rc));
- return false;
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- return new_price(id, 0, memberprice, guestprice);
+ new_price(id, 0, memberprice, guestprice);
}
- public bool new_price(uint64 product, int64 timestamp, int memberprice, int guestprice) {
+ public void new_price(uint64 product, int64 timestamp, int memberprice, int guestprice) throws DatabaseError {
statements["price_create"].reset();
statements["price_create"].bind_text(1, @"$product");
statements["price_create"].bind_int64(2, timestamp);
@@ -566,11 +470,8 @@ public class Database {
int rc = statements["price_create"].step();
if(rc != Sqlite.DONE) {
- warning("[internal error: %d]".printf(rc));
- return false;
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
-
- return true;
}
public bool check_user_password(int32 user, string password) {
@@ -587,7 +488,7 @@ public class Database {
}
}
- public void set_user_password(int32 user, string password) {
+ public void set_user_password(int32 user, string password) throws DatabaseError {
var pwhash = Checksum.compute_for_string(ChecksumType.SHA256, password);
int rc;
@@ -596,7 +497,7 @@ public class Database {
statements["user_auth_create"].bind_int(1, user);
rc = statements["user_auth_create"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
/* set password */
statements["password_set"].reset();
@@ -604,36 +505,37 @@ public class Database {
statements["password_set"].bind_int(2, user);
rc = statements["password_set"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- public void set_sessionid(int user, string sessionid) {
+ public void set_sessionid(int user, string sessionid) throws DatabaseError {
statements["session_set"].reset();
statements["session_set"].bind_text(1, sessionid);
statements["session_set"].bind_int(2, user);
int rc = statements["session_set"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- public int get_user_by_sessionid(string sessionid) throws WebSessionError {
+ public int get_user_by_sessionid(string sessionid) throws DatabaseError {
statements["session_get"].reset();
statements["session_get"].bind_text(1, sessionid);
if(statements["session_get"].step() == Sqlite.ROW) {
return statements["session_get"].column_int(0);
} else {
- throw new WebSessionError.SESSION_NOT_FOUND("No such session available in database!");
+ throw new DatabaseError.SESSION_NOT_FOUND("No such session available in database!");
}
}
- public UserInfo get_user_info(int user) {
+ public UserInfo get_user_info(int user) throws DatabaseError {
var result = UserInfo();
statements["userinfo"].reset();
statements["userinfo"].bind_int(1, user);
+ int rc = statements["userinfo"].step();
- if(statements["userinfo"].step() == Sqlite.ROW) {
+ if(rc == Sqlite.ROW) {
result.id = user;
result.firstname = statements["userinfo"].column_text(0);
result.lastname = statements["userinfo"].column_text(1);
@@ -643,12 +545,16 @@ public class Database {
result.postcode = statements["userinfo"].column_int(5);
result.city = statements["userinfo"].column_text(6);
result.pgp = statements["userinfo"].column_text(7);
+ } else if(rc == Sqlite.DONE) {
+ throw new DatabaseError.USER_NOT_FOUND("user not found");
+ } else {
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
return result;
}
- public UserAuth get_user_auth(int user) {
+ public UserAuth get_user_auth(int user) throws DatabaseError {
var result = UserAuth();
result.id = user;
result.disabled = false;
@@ -656,27 +562,33 @@ public class Database {
statements["userauth"].reset();
statements["userauth"].bind_int(1, user);
- if(statements["userauth"].step() == Sqlite.ROW) {
+ int rc = statements["userauth"].step();
+
+ if(rc == Sqlite.ROW) {
result.disabled = statements["userauth"].column_int(0) == 1;
result.superuser = statements["userauth"].column_int(1) == 1;
+ } else if(rc == Sqlite.DONE) {
+ throw new DatabaseError.USER_NOT_FOUND("user not found");
+ } else {
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
return result;
}
- public string get_username(int user) throws WebSessionError {
+ public string get_username(int user) throws DatabaseError {
statements["username"].reset();
statements["username"].bind_int(1, user);
if(statements["username"].step() == Sqlite.ROW) {
return statements["username"].column_text(0)+" "+statements["username"].column_text(1);
} else {
- throw new WebSessionError.USER_NOT_FOUND("No such user available in database!");
+ throw new DatabaseError.USER_NOT_FOUND("No such user available in database!");
}
}
- public Gee.List<InvoiceEntry?> get_invoice(int user, int64 from=0, int64 to=-1) {
- var result = new Gee.ArrayList<InvoiceEntry?>();
+ public InvoiceEntry[] get_invoice(int user, int64 from=0, int64 to=-1) throws DatabaseError {
+ InvoiceEntry[] result = {};
if(to == -1) {
to = time_t();
@@ -686,37 +598,44 @@ public class Database {
statements["invoice"].bind_int(1, user);
statements["invoice"].bind_int64(2, from);
statements["invoice"].bind_int64(3, to);
+ int rc = statements["invoice"].step();
- while(statements["invoice"].step() == Sqlite.ROW) {
+ while(rc == Sqlite.ROW) {
InvoiceEntry entry = {};
entry.timestamp = statements["invoice"].column_int64(0);
entry.product.ean = uint64.parse(statements["invoice"].column_text(1));
entry.product.name = statements["invoice"].column_text(2);
entry.price = statements["invoice"].column_int(3);
- result.add(entry);
+ result += entry;
+
+ rc = statements["invoice"].step();
+ }
+
+ if(rc != Sqlite.DONE) {
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
return result;
}
- public DateTime get_first_purchase(int user) {
+ public int64 get_first_purchase(int user) {
statements["purchase_first"].reset();
statements["purchase_first"].bind_int(1, user);
if(statements["purchase_first"].step() == Sqlite.ROW)
- return new DateTime.from_unix_utc(statements["purchase_first"].column_int64(0));
+ return statements["purchase_first"].column_int64(0);
else
- return new DateTime.from_unix_utc(0);
+ return 0;
}
- public DateTime get_last_purchase(int user) {
+ public int64 get_last_purchase(int user) {
statements["purchase_last"].reset();
statements["purchase_last"].bind_int(1, user);
if(statements["purchase_last"].step() == Sqlite.ROW)
- return new DateTime.from_unix_utc(statements["purchase_last"].column_int64(0));
+ return statements["purchase_last"].column_int64(0);
else
- return new DateTime.from_unix_utc(0);
+ return 0;
}
public StatsInfo get_stats_info() {
@@ -794,17 +713,17 @@ public class Database {
return result;
}
- public Gee.List<int> get_member_ids() {
- var result = new Gee.ArrayList<int>();
+ public int[] get_member_ids() {
+ int[] result = {};
statements["user_get_ids"].reset();
while(statements["user_get_ids"].step() == Sqlite.ROW)
- result.add(statements["user_get_ids"].column_int(0));
+ result += statements["user_get_ids"].column_int(0);
return result;
}
- public void user_disable(int user, bool value) {
+ public void user_disable(int user, bool value) throws DatabaseError {
int rc;
/* create user auth line if not existing */
@@ -812,7 +731,7 @@ public class Database {
statements["user_auth_create"].bind_int(1, user);
rc = statements["user_auth_create"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
/* set disabled flag */
statements["user_disable"].reset();
@@ -820,10 +739,10 @@ public class Database {
statements["user_disable"].bind_int(2, user);
rc = statements["user_disable"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- public void user_replace(UserInfo u) {
+ public void user_replace(UserInfo u) throws DatabaseError {
statements["user_replace"].reset();
statements["user_replace"].bind_int(1, u.id);
statements["user_replace"].bind_text(2, u.email);
@@ -837,13 +756,24 @@ public class Database {
int rc = statements["user_replace"].step();
if(rc != Sqlite.DONE)
- error("[internal error: %d]".printf(rc));
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
- public bool user_is_disabled(int user) {
+ public bool user_is_disabled(int user) throws DatabaseError {
return get_user_auth(user).disabled;
}
+ public bool user_exists(int user) throws DatabaseError {
+ if(user in get_member_ids())
+ return true;
+ return false;
+ }
+
+ public bool user_equals(UserInfo u) throws DatabaseError {
+ var dbu = get_user_info(u.id);
+ return u.equals(dbu);
+ }
+
public int64 get_timestamp_of_last_purchase() {
statements["last_timestamp"].reset();
if(statements["last_timestamp"].step() != Sqlite.ROW)
@@ -851,10 +781,10 @@ public class Database {
return statements["last_timestamp"].column_int64(0);
}
- public Gee.List<Supplier?> get_supplier_list() {
- var result = new Gee.ArrayList<Supplier?>();
- statements["supplier_list"].reset();
+ public Supplier[] get_supplier_list() {
+ Supplier[] result = {};
+ statements["supplier_list"].reset();
while(statements["supplier_list"].step() == Sqlite.ROW) {
Supplier entry = {
statements["supplier_list"].column_int64(0),
@@ -866,7 +796,7 @@ public class Database {
statements["supplier_list"].column_text(6)
};
- result.add(entry);
+ result += entry;
}
return result;
@@ -899,7 +829,7 @@ public class Database {
return result;
}
- public bool add_supplier(string name, string postal_code, string city, string street, string phone, string website) {
+ public void add_supplier(string name, string postal_code, string city, string street, string phone, string website) throws DatabaseError {
statements["supplier_add"].reset();
statements["supplier_add"].bind_text(1, name);
statements["supplier_add"].bind_text(2, postal_code);
@@ -910,10 +840,7 @@ public class Database {
int rc = statements["supplier_add"].step();
if(rc != Sqlite.DONE) {
- warning("[internal error: %d]".printf(rc));
- return false;
+ throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc);
}
-
- return true;
}
}
diff --git a/src/database/db-interface.vala b/src/database/db-interface.vala
new file mode 100644
index 0000000..da95eb7
--- /dev/null
+++ b/src/database/db-interface.vala
@@ -0,0 +1,148 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.Database")]
+public interface Database : Object {
+ public abstract StockEntry[] get_stock() throws IOError;
+ public abstract PriceEntry[] get_prices(uint64 product) throws IOError;
+ public abstract RestockEntry[] get_restocks(uint64 product) throws IOError;
+ public abstract bool buy(int32 user, uint64 article) throws IOError, DatabaseError;
+ public abstract string get_product_name(uint64 article) throws IOError, DatabaseError;
+ public abstract int get_product_amount(uint64 article) throws IOError, DatabaseError;
+ public abstract Price get_product_price(int user, uint64 article) throws IOError, DatabaseError;
+ public abstract bool undo(int32 user) throws IOError, DatabaseError;
+ public abstract bool restock(int user, uint64 product, uint amount, uint price, int supplier, int64 best_before_date) throws IOError, DatabaseError;
+ public abstract bool new_product(uint64 id, string name, int memberprice, int guestprice) throws IOError, DatabaseError;
+ public abstract bool new_price(uint64 product, int64 timestamp, int memberprice, int guestprice) throws IOError, DatabaseError;
+ public abstract bool check_user_password(int32 user, string password) throws IOError;
+ public abstract void set_user_password(int32 user, string password) throws IOError, DatabaseError;
+ public abstract void set_sessionid(int user, string sessionid) throws IOError, DatabaseError;
+ public abstract int get_user_by_sessionid(string sessionid) throws IOError, DatabaseError;
+ public abstract UserInfo get_user_info(int user) throws IOError, DatabaseError;
+ public abstract UserAuth get_user_auth(int user) throws IOError, DatabaseError;
+ public abstract string get_username(int user) throws IOError, DatabaseError;
+ public abstract InvoiceEntry[] get_invoice(int user, int64 from=0, int64 to=-1) throws IOError, DatabaseError;
+ public abstract int64 get_first_purchase(int user) throws IOError;
+ public abstract int64 get_last_purchase(int user) throws IOError;
+ public abstract StatsInfo get_stats_info() throws IOError;
+ public abstract int[] get_member_ids() throws IOError;
+ public abstract void user_disable(int user, bool value) throws IOError, DatabaseError;
+ public abstract void user_replace(UserInfo u) throws IOError, DatabaseError;
+ public abstract bool user_is_disabled(int user) throws IOError, DatabaseError;
+ public abstract bool user_exists(int user) throws IOError, DatabaseError;
+ public abstract bool user_equals(UserInfo u) throws IOError, DatabaseError;
+ public abstract int64 get_timestamp_of_last_purchase() throws IOError;
+ public abstract Supplier[] get_supplier_list() throws IOError;
+ public abstract Supplier get_supplier(int id) throws IOError;
+ public abstract bool add_supplier(string name, string postal_code, string city, string street, string phone, string website) throws IOError, DatabaseError;
+}
+
+public struct StockEntry {
+ public string id;
+ public string name;
+ public int amount;
+ public string memberprice;
+ public string guestprice;
+}
+
+public struct PriceEntry {
+ public int64 valid_from;
+ public Price memberprice;
+ public Price guestprice;
+}
+
+public struct RestockEntry {
+ public int64 timestamp;
+ public int amount;
+ public string price;
+ public int supplier;
+ public int64 best_before_date;
+}
+
+public struct Supplier {
+ public int64 id;
+ public string name;
+ public string postal_code;
+ public string city;
+ public string street;
+ public string phone;
+ public string website;
+}
+
+public struct UserInfo {
+ public int id;
+ public string firstname;
+ public string lastname;
+ public string email;
+ public string gender;
+ public string street;
+ public int postcode;
+ public string city;
+ public string pgp;
+
+ public bool equals(UserInfo x) {
+ if(id != x.id) return false;
+ if(firstname != x.firstname) return false;
+ if(lastname != x.lastname) return false;
+ if(email != x.email) return false;
+ if(gender != x.gender) return false;
+ if(street != x.street) return false;
+ if(postcode != x.postcode) return false;
+ if(city != x.city) return false;
+ if(pgp != x.pgp) return false;
+
+ return true;
+ }
+}
+
+public struct UserAuth {
+ public int id;
+ public bool disabled;
+ public bool superuser;
+}
+
+public struct Product {
+ public uint64 ean;
+ public string name;
+}
+
+public struct InvoiceEntry {
+ public int64 timestamp;
+ Product product;
+ Price price;
+}
+
+public struct StatsInfo {
+ public int count_articles;
+ public int count_users;
+ public Price stock_value;
+ public Price sales_total;
+ public Price profit_total;
+ public Price sales_today;
+ public Price profit_today;
+ public Price sales_this_month;
+ public Price profit_this_month;
+ public Price sales_per_day;
+ public Price profit_per_day;
+ public Price sales_per_month;
+ public Price profit_per_month;
+}
+
+public errordomain DatabaseError {
+ INTERNAL_ERROR,
+ PRODUCT_NOT_FOUND,
+ SESSION_NOT_FOUND,
+ USER_NOT_FOUND
+}
diff --git a/src/database/main.vala b/src/database/main.vala
new file mode 100644
index 0000000..676e960
--- /dev/null
+++ b/src/database/main.vala
@@ -0,0 +1,44 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public static void write_to_log(string message, ...) {
+ /* TODO: send message via DBus? Replace some write_to_log by throwing an error? */
+}
+
+DataBase db;
+
+public static int main(string[] args) {
+ db = new DataBase("../../shop.db");
+
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.Database",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/database", db);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/main.vala b/src/main.vala
deleted file mode 100644
index 67f00ff..0000000
--- a/src/main.vala
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-public Device dev;
-public Database db;
-public AudioPlayer audio;
-public CSVMemberFile csvimport;
-public ScannerSession localsession;
-public MainLoop loop;
-public PGPKeyArchive pgp;
-public KeyFile cfg;
-public CursesUI ui;
-
-const OptionEntry[] option_entries = {
- { "version", 'v', OptionFlags.IN_MAIN, OptionArg.NONE, ref opt_version, "output version information and exit", null },
- {null}
-};
-
-/* parameters */
-static bool opt_version;
-
-public static int main(string[] args) {
- /* parse parameters from shell */
- var context = new OptionContext("- KtT Shop System");
- context.set_help_enabled(true);
- context.add_main_entries(option_entries, "shop");
- context.add_group(Gst.init_get_option_group());
-
- try {
- context.parse(ref args);
- } catch(OptionError e) {
- stderr.puts(e.message + "\n");
- return 1;
- }
-
- if(opt_version) {
- stdout.puts("KtT Shop System 0.1\n");
- return 0;
- }
-
- /* handle unix signals */
- Unix.signal_add(Posix.SIGTERM, handle_signals);
- Unix.signal_add(Posix.SIGINT, handle_signals);
-
- try {
- cfg = new KeyFile();
- cfg.load_from_file("ktt-shopsystem.cfg", KeyFileFlags.NONE);
- } catch(Error e) {
- error("Could not load configuration file: %s", e.message);
- }
-
- string devicefile = "";
- try {
- devicefile = cfg.get_string("SERIAL", "device");
- } catch(KeyFileError e) {
- stderr.puts("Please specify serial device in the configuration file!\n");
- return 1;
- }
-
- dev = new Device(devicefile, 9600, 8, 1);
- db = new Database("shop.db");
- audio = new AudioPlayer();
- loop = new MainLoop();
- localsession = new ScannerSession();
-
- pgp = new PGPKeyArchive(cfg);
-
- dev.received_barcode.connect((data) => {
- if(localsession.interpret(data))
- dev.blink(10);
- });
-
- ui = new CursesUI();
-
- while(!check_valid_time()) {
- write_to_log("Invalid System Time! Retry in 1 minute...");
- Posix.sleep(60);
- }
-
- write_to_log("KtT Shop System has been started");
- audio.play_system("startup.ogg");
-
- /* attach webserver to mainloop */
- new WebServer();
-
- /* run mainloop */
- loop.run();
-
- write_to_log("Stopping Shop System");
- audio.play_system("shutdown.ogg");
-
- /* we need to run the mainloop to play audio */
- audio.end_of_stream.connect(() => { loop.quit(); });
- loop.run();
-
- /* explicitly call destructors */
- dev = null;
- db = null;
- audio = null;
- ui.exit();
-
- return 0;
-}
-
-public bool check_valid_time() {
- return time_t() > db.get_timestamp_of_last_purchase();
-}
-
-public void write_to_log(string format, ...) {
- var arguments = va_list();
- var message = format.vprintf(arguments);
-
- ui.log(message);
-}
-
-bool handle_signals() {
- loop.quit();
- return false;
-}
diff --git a/src/pdf-invoice/Makefile b/src/pdf-invoice/Makefile
index 2a5d2a4..cc6db94 100644
--- a/src/pdf-invoice/Makefile
+++ b/src/pdf-invoice/Makefile
@@ -1,9 +1,12 @@
all: pdf-invoice
-pdf-invoice: pdf-invoice.vala ../price.vapi
- valac --pkg pangocairo --pkg posix --pkg gio-2.0 $^
+pdf-invoice: main.vala pdf-invoice.vala pdf-invoice-interface.vala ../price.vapi
+ valac -g -o $@ --pkg pangocairo --pkg librsvg-2.0 --pkg posix --pkg gdk-2.0 --pkg gio-2.0 $^
+
+test: pdf-invoice-interface.vala test.vala ../price.vapi
+ valac -o $@ --pkg gio-2.0 $^
clean:
- rm -rf pdf-invoice
+ rm -rf pdf-invoice test
.PHONY: all clean
diff --git a/src/pdf-invoice/main.vala b/src/pdf-invoice/main.vala
new file mode 100644
index 0000000..76b03c6
--- /dev/null
+++ b/src/pdf-invoice/main.vala
@@ -0,0 +1,36 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public static int main(string[] args) {
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.InvoicePDF",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection conn) {
+ try {
+ conn.register_object("/io/mainframe/shopsystem/invoicepdf", new InvoicePDF());
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/pdf-invoice/pdf-invoice-interface.vala b/src/pdf-invoice/pdf-invoice-interface.vala
new file mode 100644
index 0000000..d2c04d9
--- /dev/null
+++ b/src/pdf-invoice/pdf-invoice-interface.vala
@@ -0,0 +1,54 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.InvoicePDFError")]
+public errordomain InvoicePDFError {
+ /* missing invoice data */
+ NO_INVOICE_DATA,
+ NO_INVOICE_DATE,
+ NO_INVOICE_ID,
+ NO_INVOICE_RECIPIENT,
+
+ /* data not supported by renderer */
+ ARTICLE_NAME_TOO_LONG,
+ PRICE_TOO_HIGH,
+ TOO_FAR_IN_THE_FUTURE
+}
+
+public struct InvoiceRecipient {
+ public string firstname;
+ public string lastname;
+ public string street;
+ public string postal_code;
+ public string city;
+ public string gender;
+}
+
+public struct InvoiceEntry {
+ int timestamp;
+ string article;
+ Price price;
+}
+
+[DBus (name = "io.mainframe.shopsystem.InvoicePDF")]
+public interface PDFInvoice : Object {
+ public abstract string invoice_id { set; owned get; }
+ public abstract int64 invoice_date { set; owned get; }
+ public abstract InvoiceRecipient invoice_recipient { set; owned get; }
+ public abstract InvoiceEntry[] invoice_entries { set; owned get; }
+
+ public abstract uint8[] generate() throws IOError, InvoicePDFError;
+ public abstract void clear() throws IOError;
+}
diff --git a/src/pdf-invoice/pdf-invoice.vala b/src/pdf-invoice/pdf-invoice.vala
index 92598f6..095dcc6 100644
--- a/src/pdf-invoice/pdf-invoice.vala
+++ b/src/pdf-invoice/pdf-invoice.vala
@@ -13,35 +13,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-[DBus (name = "io.mainframe.shopsystem.InvoicePDFError")]
-public errordomain InvoicePDFError {
- /* missing invoice data */
- NO_INVOICE_DATA,
- NO_INVOICE_DATE,
- NO_INVOICE_ID,
- NO_INVOICE_RECIPIENT,
-
- /* data not supported by renderer */
- ARTICLE_NAME_TOO_LONG,
- PRICE_TOO_HIGH,
- TOO_FAR_IN_THE_FUTURE
-}
-
-public struct InvoiceRecipient {
- public string firstname;
- public string lastname;
- public string street;
- public string postal_code;
- public string city;
- public string gender;
-}
-
-public struct InvoiceEntry {
- int timestamp;
- string article;
- Price price;
-}
-
[DBus (name = "io.mainframe.shopsystem.InvoicePDF")]
public class InvoicePDF {
/* A4 sizes (in points, 72 DPI) */
@@ -49,10 +20,10 @@ public class InvoicePDF {
private const double height = 841.88976; /* 297mm */
/* invoice content, which should appear in the PDF */
- public string invoice_id { set; get; }
+ public string invoice_id { set; owned get; }
public int64 invoice_date { set; get; }
- public InvoiceRecipient invoice_recipient { set; get; }
- public InvoiceEntry[] invoice_entries { set; get; }
+ public InvoiceRecipient invoice_recipient { set; owned get; }
+ public InvoiceEntry[] invoice_entries { set; owned get; }
/* pdf data */
private uint8[] data;
@@ -77,29 +48,27 @@ public class InvoicePDF {
};
public InvoicePDF() {
+ clear();
+ }
+
+ private void render_svg(Cairo.Context ctx, string file) {
+ var svg = new Rsvg.Handle.from_file(file);
+ svg.render_cairo(ctx);
}
private void draw_footer(Cairo.Context ctx) {
- /* TODO: get path from config file, support svg */
- var footer = new Cairo.ImageSurface.from_png("../../invoice/footer-line.png");
- ctx.set_source_surface(footer, 0, 817);
- ctx.paint();
+ ctx.save();
+ ctx.translate(-20, 818);
+ ctx.scale(1.42, 1.42);
+ render_svg(ctx, "../../invoice/footer-line.svg");
+ ctx.restore();
}
private void draw_logo(Cairo.Context ctx) {
- /* TODO: get path from config file, support svg */
- var logo = new Cairo.ImageSurface.from_png("../../invoice/logo.png");
-
- var pattern = new Cairo.Pattern.for_surface(logo);
- Cairo.Matrix scaler;
- pattern.get_matrix(out scaler);
- scaler.scale(1.41,1.41);
- scaler.translate(-364.5,-22.5);
- pattern.set_matrix(scaler);
- pattern.set_filter(Cairo.Filter.BEST);
-
- ctx.set_source(pattern);
- ctx.paint();
+ ctx.save();
+ ctx.translate(366,25);
+ render_svg(ctx, "../../invoice/logo.svg");
+ ctx.restore();
}
private void draw_address(Cairo.Context ctx) {
@@ -661,29 +630,14 @@ public class InvoicePDF {
public void clear() {
invoice_date = 0;
invoice_id = "";
- invoice_recipient = {};
+ invoice_recipient = {
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ };
invoice_entries = null;
}
}
-
-public static int main(string[] args) {
- Bus.own_name(
- BusType.SESSION,
- "io.mainframe.shopsystem.InvoicePDF",
- BusNameOwnerFlags.NONE,
- on_bus_aquired,
- () => {},
- () => stderr.printf ("Could not aquire name\n"));
-
- new MainLoop ().run ();
-
- return 0;
-}
-
-void on_bus_aquired(DBusConnection conn) {
- try {
- conn.register_object ("/io/mainframe/invoicepdf", new InvoicePDF());
- } catch (IOError e) {
- stderr.printf ("Could not register service\n");
- }
-}
diff --git a/src/pdf-invoice/test.vala b/src/pdf-invoice/test.vala
new file mode 100644
index 0000000..f9d21f6
--- /dev/null
+++ b/src/pdf-invoice/test.vala
@@ -0,0 +1,47 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public static int main(string args[]) {
+ PDFInvoice invoice = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.InvoicePDF", "/io/mainframe/shopsystem/invoicepdf");
+
+ InvoiceRecipient r = {
+ "Max",
+ "Mustermann",
+ "Foobar Straße 42",
+ "31337",
+ "Entenhausen",
+ "masculinum"
+ };
+
+ InvoiceEntry e1 = {
+ 1364271520,
+ "Club Mate",
+ 2342
+ };
+
+ /* set invoice data */
+ invoice.invoice_id = "TEST";
+ invoice.invoice_date = 1364271524;
+ invoice.invoice_recipient = r;
+ invoice.invoice_entries = {e1};
+
+ /* generate pdf */
+ var pdfdata = invoice.generate();
+
+ /* write pdf into file */
+ FileUtils.set_contents("test.pdf", (string) pdfdata, pdfdata.length);
+
+ return 0;
+}
diff --git a/src/pgp/Makefile b/src/pgp/Makefile
new file mode 100644
index 0000000..6bcb535
--- /dev/null
+++ b/src/pgp/Makefile
@@ -0,0 +1,9 @@
+all: pgp
+
+pgp: main.vala pgp.vala pgp-interface.vala ../config/config-interface.vala
+ valac -o $@ --vapidir ../../vapi -X -lgpgme --pkg gpgme --pkg gio-2.0 --pkg libarchive $^
+
+clean:
+ rm -rf pgp
+
+.PHONY: all clean
diff --git a/src/pgp/main.vala b/src/pgp/main.vala
new file mode 100644
index 0000000..f95b6f7
--- /dev/null
+++ b/src/pgp/main.vala
@@ -0,0 +1,53 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public static void write_to_log(string message, ...) {
+ /* TODO: send message via DBus? Replace some write_to_log by throwing an error? */
+}
+
+PGPKeyArchive pgp;
+Config cfg;
+
+public static int main(string[] args) {
+ try {
+ cfg = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config");
+ pgp = new PGPKeyArchive(cfg.get_string("PGP", "keyring"));
+ } catch(IOError e) {
+ error("IOError: %s\n", e.message);
+ } catch(KeyFileError e) {
+ error("Config Error: %s\n", e.message);
+ }
+
+
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.PGP",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/pgp", pgp);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/pgp/pgp-interface.vala b/src/pgp/pgp-interface.vala
new file mode 100644
index 0000000..62bfe67
--- /dev/null
+++ b/src/pgp/pgp-interface.vala
@@ -0,0 +1,21 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.PGP")]
+public interface PGP : Object {
+ public abstract string[] import_archive(uint8[] data) throws IOError;
+ public abstract string[] list_keys() throws IOError;
+ public abstract string get_key(string fingerprint) throws IOError;
+}
diff --git a/src/admin.vala b/src/pgp/pgp.vala
index de123e1..bb48c61 100644
--- a/src/admin.vala
+++ b/src/pgp/pgp.vala
@@ -1,4 +1,4 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -13,88 +13,24 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-public class CSVMemberFile {
- private UserInfo[] members;
-
- public Gee.List<int> missing_unblocked_members() {
- var result = new Gee.ArrayList<int>();
- var dbusers = db.get_member_ids();
-
- foreach(var u in dbusers) {
- bool found=false;
- foreach(var m in members) {
- if(u == m.id) {
- found=true;
- break;
- }
- }
-
- if(!found) {
- if(!db.user_is_disabled(u))
- result.add(u);
- }
- }
-
- return result;
- }
-
- private string[] csv_split(string line) {
- return /;(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/.split(line);
- }
-
- private string csv_value(string value) {
- if(value[0] == '"' && value[value.length-1] == '"')
- return value.substring(1,value.length-2);
- else
- return value;
- }
-
- public CSVMemberFile(string data) {
- foreach(var line in data.split("\n")) {
- var linedata = csv_split(line);
- if(linedata.length >= 9) {
- var m = UserInfo();
- m.id = int.parse(csv_value(linedata[0]));
- m.email = csv_value(linedata[1]);
- m.firstname = csv_value(linedata[2]);
- m.lastname = csv_value(linedata[3]);
- m.street = csv_value(linedata[4]);
- m.postcode = int.parse(csv_value(linedata[5]));
- m.city = csv_value(linedata[6]);
- m.gender = csv_value(linedata[7]) == "m" ? "masculinum" : csv_value(linedata[7]) == "w" ? "femininum" : "unknown";
- m.pgp = csv_value(linedata[8]);
- if(csv_value(linedata[0]) != "EXTERNEMITGLIEDSNUMMER")
- members += m;
- }
- }
- }
-
- public UserInfo[] get_members() {
- return members;
- }
-}
-
+[DBus (name = "io.mainframe.shopsystem.PGP")]
public class PGPKeyArchive {
private string keyring;
private GPG.Context gpg;
- public PGPKeyArchive(KeyFile config) {
+ public PGPKeyArchive(string keyring) {
/* check version (important!) */
GPG.check_version();
/* initialize default context */
GPG.Context.Context(out gpg);
- try {
- keyring = config.get_string("PGP", "keyring");
-
- /* remove quotes */
- if(keyring.has_prefix("\"") && keyring.has_suffix("\""))
- keyring = keyring.substring(1,keyring.length-2);
- } catch(KeyFileError e) {
- write_to_log("KeyFileError: %s", e.message);
- return;
- }
+ /* TODO TODO TODO */
+#if 0
+ if(keyring.has_prefix("\"") && keyring.has_suffix("\""))
+ this.keyring = keyring.substring(1,keyring.length-2);
+#endif
+ this.keyring = keyring;
/* TODO: check existence of keyring */
diff --git a/src/scanner-session/Makefile b/src/scanner-session/Makefile
new file mode 100644
index 0000000..ea91d3a
--- /dev/null
+++ b/src/scanner-session/Makefile
@@ -0,0 +1,9 @@
+all: scanner-session
+
+scanner-session: main.vala scannersession.vala scannersession-interface.vala ../database/db-interface.vala ../serial-device/serial-device-interface.vala ../audio/audio-interface.vala ../price.vapi
+ valac -o $@ --pkg gio-2.0 $^
+
+clean:
+ rm -rf scanner-session
+
+.PHONY: all clean
diff --git a/src/scanner-session/main.vala b/src/scanner-session/main.vala
new file mode 100644
index 0000000..11562e1
--- /dev/null
+++ b/src/scanner-session/main.vala
@@ -0,0 +1,38 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+ScannerSessionImplementation session;
+
+public static int main(string[] args) {
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.ScannerSession",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/scanner_session", session);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/scanner-session/scannersession-interface.vala b/src/scanner-session/scannersession-interface.vala
new file mode 100644
index 0000000..0f81dd4
--- /dev/null
+++ b/src/scanner-session/scannersession-interface.vala
@@ -0,0 +1,25 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.ScannerSession")]
+public interface ScannerSession : Object {
+ public abstract signal void msg(MessageType type, string message);
+}
+
+public enum MessageType {
+ INFO,
+ WARNING,
+ ERROR
+}
diff --git a/src/scannersession.vala b/src/scanner-session/scannersession.vala
index 9dbe3d3..6926ba9 100644
--- a/src/scannersession.vala
+++ b/src/scanner-session/scannersession.vala
@@ -1,4 +1,4 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+/* Copyright 2012-2013, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -13,43 +13,45 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-public class ScannerSession {
- public int user {
- get;
- private set;
- default = 0;
- }
- public string name {
- get;
- private set;
- default = "Guest";
- }
- public bool logged_in {
- get;
- private set;
- default = false;
- }
- public bool disabled {
- get;
- private set;
- default = false;
+[DBus (name = "io.mainframe.shopsystem.ScannerSession")]
+public class ScannerSessionImplementation {
+ private int user = 0;
+ private string name = "Guest";
+ private bool logged_in = false;
+ private bool disabled = false;
+ private string theme = "beep";
+
+ private Database db;
+ private AudioPlayer audio;
+
+ public signal void msg(MessageType type, string message);
+
+ public ScannerSessionImplementation() {
+ try {
+ db = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database");
+ audio = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio");
+ } catch(IOError e) {
+ error("IOError: %s\n", e.message);
+ }
}
- public string theme {
- get;
- private set;
- default = "beep";
+
+ private void send_message(MessageType type, string format, ...) {
+ var arguments = va_list();
+ var message = format.vprintf(arguments);
+
+ msg(type, message);
}
- public void logout() {
+ private void logout() {
logged_in = false;
}
- public bool login(int user) {
+ private bool login(int user) {
this.user = user;
try {
this.name = db.get_username(user);
this.disabled = db.get_user_auth(user).disabled;
- } catch(WebSessionError e) {
+ } catch(DatabaseError e) {
return false;
}
this.logged_in = true;
@@ -58,10 +60,7 @@ public class ScannerSession {
return true;
}
- public ScannerSession() {
- }
-
- public bool interpret(string scannerdata) {
+ private bool interpret(string scannerdata) {
if(scannerdata.has_prefix("USER ")) {
string str_id = scannerdata.substring(5);
int32 id = int.parse(str_id);
@@ -69,43 +68,43 @@ public class ScannerSession {
/* check if scannerdata has valid format */
if(scannerdata != "USER %d".printf(id)) {
audio.play_system("error.ogg");
- write_to_log("Error: Invalid User ID: %s", scannerdata);
+ send_message(MessageType.ERROR, "Invalid User ID: %s", scannerdata);
return false;
}
if(logged_in) {
- write_to_log("Warning: Last user forgot to logout");
+ send_message(MessageType.WARNING, "Last user forgot to logout");
logout();
}
if(login(id)) {
audio.play_user(theme, "login");
- write_to_log("Login: %s (%d)", name, user);
+ send_message(MessageType.INFO, "Login: %s (%d)", name, user);
return true;
} else {
audio.play_system("error.ogg");
- write_to_log("Error: Login failed (User ID = %d)", id);
+ send_message(MessageType.ERROR, "Login failed (User ID = %d)", id);
return false;
}
} else if(scannerdata == "GUEST") {
if(logged_in) {
- write_to_log("Warning: Last user forgot to logout");
+ send_message(MessageType.WARNING, "Last user forgot to logout");
logout();
}
if(login(0)) {
audio.play_user(theme, "login");
- write_to_log("Login: %s (%d)", name, user);
+ send_message(MessageType.INFO, "Login: %s (%d)", name, user);
return true;
} else {
audio.play_system("error.ogg");
- write_to_log("Error: Login failed (User ID = 0)");
+ send_message(MessageType.ERROR, "Login failed (User ID = 0)");
return false;
}
} else if(scannerdata == "UNDO") {
if(!logged_in) {
audio.play_system("error.ogg");
- write_to_log("Error: Can't undo if not logged in!");
+ send_message(MessageType.ERROR, "Can't undo if not logged in!");
return false;
} else {
if(db.undo(user)) {
@@ -113,14 +112,14 @@ public class ScannerSession {
return true;
} else {
audio.play_user(theme, "error");
- write_to_log("Error: Couldn't undo last purchase!");
+ send_message(MessageType.ERROR, "Couldn't undo last purchase!");
return false;
}
}
} else if(scannerdata == "LOGOUT") {
if(logged_in) {
audio.play_user(theme, "logout");
- write_to_log("Logout!");
+ send_message(MessageType.INFO, "Logout!");
logout();
return true;
}
@@ -133,7 +132,7 @@ public class ScannerSession {
/* check if scannerdata has valid format */
if(scannerdata != "%llu".printf(id) && scannerdata != "%08llu".printf(id) && scannerdata != "%013llu".printf(id)) {
audio.play_user(theme, "error");
- write_to_log("Error: invalid product: %s", scannerdata);
+ send_message(MessageType.ERROR, "invalid product: %s", scannerdata);
return false;
}
@@ -144,19 +143,19 @@ public class ScannerSession {
var gprice = db.get_product_price(0, id);
audio.play_system("error.ogg");
- write_to_log(@"article info: $name (Member: $mprice €, Guest: $gprice €)");
- write_to_log("Error: Login required for purchase!");
+ send_message(MessageType.INFO, @"article info: $name (Member: $mprice €, Guest: $gprice €)");
+ send_message(MessageType.ERROR, "Login required for purchase!");
return false;
}
if(db.buy(user, id)) {
var price = db.get_product_price(user, id);
audio.play_user(theme, "purchase");
- write_to_log(@"article bought: $name ($price €)");
+ send_message(MessageType.INFO, @"article bought: $name ($price €)");
return true;
} else {
audio.play_user(theme, "error");
- write_to_log("Error: purchase failed!");
+ send_message(MessageType.ERROR, "purchase failed!");
return false;
}
}
diff --git a/src/serial-device/Makefile b/src/serial-device/Makefile
new file mode 100644
index 0000000..952b3a1
--- /dev/null
+++ b/src/serial-device/Makefile
@@ -0,0 +1,9 @@
+all: serial-device
+
+serial-device: main.vala serial-device.vala serial-device-interface.vala ../config/config-interface.vala
+ valac -o $@ --pkg linux --pkg posix --pkg gio-2.0 $^
+
+clean:
+ rm -rf serial-device
+
+.PHONY: all clean
diff --git a/src/serial-device/main.vala b/src/serial-device/main.vala
new file mode 100644
index 0000000..e338842
--- /dev/null
+++ b/src/serial-device/main.vala
@@ -0,0 +1,47 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+Device dev;
+
+public static int main(string[] args) {
+ try {
+ Config cfg = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config");
+ dev = new Device(cfg.get_string("SERIAL", "device"), 9600, 8, 1);
+ } catch(IOError e) {
+ error("IOError: %s\n", e.message);
+ } catch(KeyFileError e) {
+ error("Config Error: %s\n", e.message);
+ }
+
+ Bus.own_name(
+ BusType.SESSION,
+ "io.mainframe.shopsystem.SerialDevice",
+ BusNameOwnerFlags.NONE,
+ on_bus_aquired,
+ () => {},
+ () => stderr.printf("Could not aquire name\n"));
+
+ new MainLoop().run();
+
+ return 0;
+}
+
+void on_bus_aquired(DBusConnection con) {
+ try {
+ con.register_object("/io/mainframe/shopsystem/device", dev);
+ } catch(IOError e) {
+ stderr.printf("Could not register service\n");
+ }
+}
diff --git a/src/serial-device/serial-device-interface.vala b/src/serial-device/serial-device-interface.vala
new file mode 100644
index 0000000..572e810
--- /dev/null
+++ b/src/serial-device/serial-device-interface.vala
@@ -0,0 +1,20 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+[DBus (name = "io.mainframe.shopsystem.SerialDevice")]
+public interface SerialDevice : Object {
+ public abstract signal void received_barcode(string barcode);
+ public abstract void blink(uint duration) throws IOError;
+}
diff --git a/src/device.vala b/src/serial-device/serial-device.vala
index 5d7fc09..76bb5b5 100644
--- a/src/device.vala
+++ b/src/serial-device/serial-device.vala
@@ -1,4 +1,4 @@
-/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+/* Copyright 2012-2013, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -13,12 +13,13 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+[DBus (name = "io.mainframe.shopsystem.SerialDevice")]
public class Device {
private Posix.termios newtio;
private Posix.termios restoretio;
- public int fd=-1;
+ private int fd=-1;
private IOChannel io_read;
- public int byterate;
+ private int byterate;
private File lockfile;
public signal void received_barcode(string barcode);
diff --git a/src/ui/logo.vala b/src/ui/logo.vala
deleted file mode 100644
index 5a94422..0000000
--- a/src/ui/logo.vala
+++ /dev/null
@@ -1,30 +0,0 @@
-using Curses;
-
-public class Logo {
- Window win;
-
- public Logo() {
- win = new Window(8, COLS - 2, 0, 1);
- win.bkgdset(COLOR_PAIR(1) | Attribute.BOLD);
-
- win.addstr("\n");
- win.addstr(" _ ___ _____ ____ _ \n");
- win.addstr(" | |/ / ||_ _| / ___|| |__ ___ _ __ \n");
- win.addstr(" | ' /| __|| | \\___ \\| '_ \\ / _ \\| '_ \\ \n");
- win.addstr(" | . \\| |_ | | ___) | | | | (_) | |_) )\n");
- win.addstr(" |_|\\_\\\\__||_| |____/|_| |_|\\___/| .__/ \n");
- win.addstr(" |_| \n");
-
- win.clrtobot();
-
- win.box(0, 0);
-
- win.refresh();
- }
-
- public void redraw() {
- win.touchwin();
- win.refresh();
- }
-
-}
diff --git a/src/ui/status.vala b/src/ui/status.vala
deleted file mode 100644
index db33820..0000000
--- a/src/ui/status.vala
+++ /dev/null
@@ -1,24 +0,0 @@
-using Curses;
-
-public class StatusPanel {
- Window win;
-
- public StatusPanel() {
- win = new Window(1, COLS - 2, LINES-1, 1);
- win.bkgdset(COLOR_PAIR(2) | Attribute.BOLD);
-
- win.clrtobot();
- win.refresh();
- }
-
- public void set(string msg) {
- win.mvaddstr(0,1, msg);
- win.clrtobot();
- win.refresh();
- }
-
- public void redraw() {
- win.touchwin();
- win.refresh();
- }
-}
diff --git a/src/web/Makefile b/src/web/Makefile
new file mode 100644
index 0000000..cc9d77e
--- /dev/null
+++ b/src/web/Makefile
@@ -0,0 +1,9 @@
+all: web
+
+web: main.vala web.vala websession.vala csv.vala template.vala ../database/db-interface.vala ../pgp/pgp-interface.vala ../price.vapi
+ valac -o $@ --vapidir=../../vapi --pkg gee-1.0 --pkg gio-2.0 --pkg libsoup-2.4 --pkg posix --pkg libarchive --pkg gpgme $^
+
+clean:
+ rm -rf web
+
+.PHONY: all clean
diff --git a/src/web/csv.vala b/src/web/csv.vala
new file mode 100644
index 0000000..4e32a0a
--- /dev/null
+++ b/src/web/csv.vala
@@ -0,0 +1,75 @@
+/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+public class CSVMemberFile {
+ private UserInfo[] members;
+
+ public Gee.List<int> missing_unblocked_members() {
+ var result = new Gee.ArrayList<int>();
+ var dbusers = db.get_member_ids();
+
+ foreach(var u in dbusers) {
+ bool found=false;
+ foreach(var m in members) {
+ if(u == m.id) {
+ found=true;
+ break;
+ }
+ }
+
+ if(!found) {
+ if(!db.user_is_disabled(u))
+ result.add(u);
+ }
+ }
+
+ return result;
+ }
+
+ private string[] csv_split(string line) {
+ return /;(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/.split(line);
+ }
+
+ private string csv_value(string value) {
+ if(value[0] == '"' && value[value.length-1] == '"')
+ return value.substring(1,value.length-2);
+ else
+ return value;
+ }
+
+ public CSVMemberFile(string data) {
+ foreach(var line in data.split("\n")) {
+ var linedata = csv_split(line);
+ if(linedata.length >= 9) {
+ var m = UserInfo();
+ m.id = int.parse(csv_value(linedata[0]));
+ m.email = csv_value(linedata[1]);
+ m.firstname = csv_value(linedata[2]);
+ m.lastname = csv_value(linedata[3]);
+ m.street = csv_value(linedata[4]);
+ m.postcode = int.parse(csv_value(linedata[5]));
+ m.city = csv_value(linedata[6]);
+ m.gender = csv_value(linedata[7]) == "m" ? "masculinum" : csv_value(linedata[7]) == "w" ? "femininum" : "unknown";
+ m.pgp = csv_value(linedata[8]);
+ if(csv_value(linedata[0]) != "EXTERNEMITGLIEDSNUMMER")
+ members += m;
+ }
+ }
+ }
+
+ public UserInfo[] get_members() {
+ return members;
+ }
+}
diff --git a/src/web/main.vala b/src/web/main.vala
new file mode 100644
index 0000000..07dbb03
--- /dev/null
+++ b/src/web/main.vala
@@ -0,0 +1,35 @@
+/* Copyright 2013, Sebastian Reichel <sre@ring0.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+Database db;
+public CSVMemberFile csvimport;
+public PGP pgp;
+
+public static int main(string[] args) {
+ try {
+ db = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database");
+ pgp = Bus.get_proxy_sync(BusType.SESSION, "io.mainframe.shopsystem.PGP", "/io/mainframe/shopsystem/pgp");
+ } catch(IOError e) {
+ error("IOError: %s\n", e.message);
+ }
+
+ /* attach WebServer to MainLoop */
+ new WebServer();
+
+ /* start MainLoop */
+ new MainLoop().run();
+
+ return 0;
+}
diff --git a/src/template.vala b/src/web/template.vala
index 8fe56d0..8fe56d0 100644
--- a/src/template.vala
+++ b/src/web/template.vala
diff --git a/src/web.vala b/src/web/web.vala
index 7140c22..9dfb1ae 100644
--- a/src/web.vala
+++ b/src/web/web.vala
@@ -88,7 +88,8 @@ public class WebServer {
try {
var name = db.get_username(m);
data += @"<tr><td>$m</td><td><a href=\"/users/$m\">$name</a></td></tr>";
- } catch(WebSessionError e) {
+ } catch(DatabaseError e) {
+ /* TODO: write error to log */
}
}
t.replace("DATA", data);
@@ -184,11 +185,11 @@ public class WebServer {
/* new & changed users */
string data1 = "";
foreach(var member in csvimport.get_members()) {
- if(member.exists_in_db() && !member.equals_db()) {
+ if(db.user_exists(member.id) && db.user_equals(member)) {
var dbmember = db.get_user_info(member.id);
data1 += @"<tr class=\"error\"><td><i class=\"icon-minus-sign\"></i><td>$(dbmember.id)</td><td>$(dbmember.firstname)</td><td>$(dbmember.lastname)</td><td>$(dbmember.email)</td><td>$(dbmember.gender)</td><td>$(dbmember.street)</td><td>$(dbmember.postcode)</td><td>$(dbmember.city)</td><td>$(dbmember.pgp)</td></tr>";
}
- if(!member.exists_in_db() || !member.equals_db()) {
+ if(!db.user_exists(member.id) || !db.user_equals(member)) {
data1 += @"<tr class=\"success\"><td><i class=\"icon-plus-sign\"></td><td>$(member.id)</td><td>$(member.firstname)</td><td>$(member.lastname)</td><td>$(member.email)</td><td>$(member.gender)</td><td>$(member.street)</td><td>$(member.postcode)</td><td>$(member.city)</td><td>$(member.pgp)</td></tr>";
}
}
@@ -325,8 +326,8 @@ public class WebServer {
t.menu_set_active("users");
/* years, in which something has been purchased by the user */
- var first = db.get_first_purchase(id);
- var last = db.get_last_purchase(id);
+ var first = new DateTime.from_unix_local(db.get_first_purchase(id));
+ var last = new DateTime.from_unix_local(db.get_last_purchase(id));
string years = "";
for(int i=first.get_year(); i <= last.get_year(); i++) {
years += @"<li><a href=\"/users/$id/invoice/$i/$selectedmonth/$selectedday\">$i</a></li>";
@@ -659,7 +660,7 @@ public class WebServer {
}
}
-
+#if 0
void handler_stats(Soup.Server server, Soup.Message msg, string path, GLib.HashTable? query, Soup.ClientContext client) {
try {
var l = new WebSession(server, msg, path, query, client);
@@ -749,6 +750,7 @@ public class WebServer {
handler_404(server, msg, path, query, client);
}
}
+#endif
void handler_js(Soup.Server server, Soup.Message msg, string path, GLib.HashTable? query, Soup.ClientContext client) {
try {
@@ -837,12 +839,14 @@ public class WebServer {
srv.add_handler("/products", handler_products);
srv.add_handler("/products/new", handler_products_new);
+#if 0
/* stats */
srv.add_handler("/stats", handler_stats);
srv.add_handler("/stats/stock", handler_stats_stock);
srv.add_handler("/stats/profit_per_day", handler_stats_profit_per_day);
srv.add_handler("/stats/profit_per_weekday", handler_stats_profit_per_weekday);
srv.add_handler("/stats/profit_per_product", handler_stats_profit_per_product);
+#endif
/* users */
srv.add_handler("/users", handler_users);
diff --git a/src/websession.vala b/src/web/websession.vala
index 5c562c6..5c562c6 100644
--- a/src/websession.vala
+++ b/src/web/websession.vala