summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--db.vala25
-rw-r--r--main.vala12
-rw-r--r--ui.vala30
-rw-r--r--user-interface.ui140
5 files changed, 208 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index a5fff6e..cdf1b8e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
PREFIX=/usr/local
# web.vala (currently disabled)
-barcode-scanner: main.vala device.vala db.vala
- valac-0.16 --output $@ --pkg posix --pkg linux --pkg libsoup-2.4 --pkg sqlite3 $^
+barcode-scanner: main.vala device.vala db.vala ui.vala
+ valac-0.16 --output $@ --pkg posix --pkg linux --pkg libsoup-2.4 --pkg sqlite3 --pkg gtk+-3.0 --pkg gee-1.0 $^
shop.db: create_db.sql
sqlite3 shop.db < create_db.sql
diff --git a/db.vala b/db.vala
index bf3e3da..fc70500 100644
--- a/db.vala
+++ b/db.vala
@@ -1,6 +1,7 @@
public class Database {
private Sqlite.Database db;
private Sqlite.Statement product_stmt;
+ private Sqlite.Statement products_stmt;
private Sqlite.Statement purchase_stmt1;
private Sqlite.Statement purchase_stmt2;
private Sqlite.Statement undo_stmt1;
@@ -14,6 +15,7 @@ public class Database {
bool logged_in = false;
bool stock_mode = false;
private static string product_query = "SELECT name FROM products WHERE id = ?";
+ private static string products_query = "SELECT id, name FROM products";
private static string purchase_query1 = "INSERT INTO purchases ('user', 'product', 'timestamp') VALUES (?, ?, ?)";
private static string purchase_query2 = "UPDATE products SET amount = amount - 1 WHERE id = ?";
private static string undo_query1 = "SELECT product FROM purchases WHERE user = ? ORDER BY timestamp DESC LIMIT 1";
@@ -46,6 +48,11 @@ public class Database {
error("could not prepare article statement!");
}
+ rc = this.db.prepare_v2(products_query, -1, out products_stmt);
+ if(rc != Sqlite.OK) {
+ error("could not prepare products statement!");
+ }
+
rc = this.db.prepare_v2(undo_query1, -1, out undo_stmt1);
if(rc != Sqlite.OK) {
error("could not prepare first undo statement!");
@@ -91,6 +98,16 @@ public class Database {
return true;
}
+ public Gee.HashMap<string,string> get_products() {
+ var result = new Gee.HashMap<string,string>(null, null);
+ this.products_stmt.reset();
+
+ while(this.products_stmt.step() == Sqlite.ROW)
+ result[this.products_stmt.column_text(0)] = this.products_stmt.column_text(1);
+
+ return result;
+ }
+
public bool buy(uint64 article) {
if(is_logged_in()) {
int rc = 0;
@@ -209,6 +226,14 @@ public class Database {
public bool add_stock_product(uint64 amount) {
if(is_in_stock_mode() && product != 0) {
+ return restock(this.product, amount);
+ }
+
+ return false;
+ }
+
+ public bool restock(uint64 product, uint64 amount) {
+ if(is_logged_in()) {
int rc = 0;
int64 timestamp = (new DateTime.now_utc()).to_unix();
diff --git a/main.vala b/main.vala
index 674fac7..f12be5b 100644
--- a/main.vala
+++ b/main.vala
@@ -1,7 +1,10 @@
public Device dev;
public Database db;
+public Gtk.Builder builder;
public static int main(string[] args) {
+ Gtk.init (ref args);
+
if(args.length < 2) {
stderr.printf("%s <device>\n", args[0]);
return 1;
@@ -9,13 +12,20 @@ public static int main(string[] args) {
dev = new Device(args[1], 9600, 8, 1);
db = new Database("shop.db");
+ builder = new Gtk.Builder();
+ try {
+ builder.add_from_file("user-interface.ui");
+ } catch(Error e) {
+ stderr.printf ("Could not load UI: %s\n", e.message);
+ return 1;
+ }
dev.received_barcode.connect((data) => {
if(interpret(data))
dev.blink(10);
});
- new MainLoop(null, false).run();
+ Gtk.main();
return 0;
}
diff --git a/ui.vala b/ui.vala
new file mode 100644
index 0000000..c2eaa61
--- /dev/null
+++ b/ui.vala
@@ -0,0 +1,30 @@
+public void restock_dialog() {
+ var window = builder.get_object("restock_dialog") as Gtk.Window;
+ window.show_all();
+
+ /* product combobox */
+ var box = builder.get_object("comboboxtext1") as Gtk.ComboBoxText;
+ foreach(var entry in db.get_products().entries) {
+ box.append(entry.key, entry.value);
+ }
+
+ /* spinner button */
+ var spinner = builder.get_object("spinbutton1") as Gtk.SpinButton;
+
+ /* dialog buttons */
+ var cancel = builder.get_object("button-restock-cancel") as Gtk.Button;
+ var ok = builder.get_object("button-restock-add") as Gtk.Button;
+
+ cancel.clicked.connect(() => {
+ window.destroy();
+ });
+
+ ok.clicked.connect(() => {
+ var id = box.get_active_id();
+ var product = (id != null) ? uint64.parse(id) : 0;
+ var amount = (int) spinner.get_value();
+
+ if(db.restock(product, amount))
+ window.destroy();
+ });
+}
diff --git a/user-interface.ui b/user-interface.ui
new file mode 100644
index 0000000..55266f5
--- /dev/null
+++ b/user-interface.ui
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkDialog" id="restock_dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">restock</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">5</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button-restock-cancel">
+ <property name="label">gtk-cancel</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button-restock-add">
+ <property name="label">gtk-add</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Product</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Amount</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">3</property>
+ <property name="invisible_char">•</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="climb_rate">1</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxtext1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button-restock-cancel</action-widget>
+ <action-widget response="0">button-restock-add</action-widget>
+ </action-widgets>
+ </object>
+</interface>