#!/usr/bin/env python

import sys, os, pygtk, gtk

TREE_MIN_WIDTH, TREE_MIN_HEIGHT, BUTTONBOX_SPACING = 400, 100, 5
COL_SKU, COL_DESC, COL_PRICE, COL_QUANTITY, COL_LEFT_ALIGN, COL_CENTER_ALIGN = 0, 1, 2, 3, 4, 5
SKU_MIN_WIDTH, DESC_MIN_WIDTH, PRICE_MIN_WIDTH, QUANTITY_MIN_WIDTH = 100, 150, 80, 70
LEFT_ALIGN, CENTER_ALIGN = 0, 0.5

LABEL_1x3 = """

N
q203
Q609
S2
A190,80,1,3,1,1,N,"#DESC"
A40,4,1,3,1,1,N,"#SKU"
A40,450,1,3,1,1,N,"#PRICE"
B140,4,1,1,3,7,85,N,"#SKU"
P1

"""

class LabelPrinter:
	"""A simple interface for printing barcode labels."""
	
	versionString = "Label Printer v0.4"
	
	def quit(self, widget, data=None):
		"""Terminates the applet cleanly."""
		
		gtk.main_quit()
		
		
	def parseDataFile(self, dataFile, view):
		"""Parses dataFile and adds any rows that can be resolved"""
		
		try:
			f = open(dataFile, "r")
			
			for line in f.readlines():
				
				tokens = line.split(",")
				
				if len(tokens) is not 4:
					continue
					
				sku, desc, price, quantity = tokens[0], tokens[1], tokens[2], int(tokens[3]);			
				self.addRow(None, None, view, sku, desc, price, quantity)
					
			f.close()
		
		except StandardError:
			return
		

	def editCellText(self, cell, path, text, model, column):
		"""Edits the cell at the specified path and colum, setting its value to text."""
		
		it = model.get_iter(path)
		
		if column == COL_QUANTITY:
			text = int(text)
		elif column == COL_PRICE and not text.startswith("$"):
			text = "$" + text
		elif column == COL_DESC:
			text = text[:36]
			
		model.set_value(it, column, text)
		
		return True
		
	
	def hasActivateIntent(self, event):
		"""Returns True if event appears to "want" to activate its target.  False otherwise."""
		
		if event.type is gtk.gdk.KEY_PRESS:
			
			if not event.string in " \r":
				return False
		
		return True
		
		
	def addRow(self, button, event, view, sku="", desc="", price="", quantity=1):
		"""Appends and selects a new empty row to view's model."""
		
		if event and not self.hasActivateIntent(event):
			return False
		
		model = view.get_model()
		model.append([sku, desc[:36], price, quantity, LEFT_ALIGN, CENTER_ALIGN])
		
		it = model.get_iter_first()
		while model.iter_next(it):
			it = model.iter_next(it)
		
		view.get_selection().unselect_all()
		view.get_selection().select_iter(it)
		
		return True
		
		
	def selectAll(self, widget, event, view):
		"""Selects all rows in view."""
		
		if event and not self.hasActivateIntent(event):
			return False
				
		view.get_selection().select_all()
		return True
	
		
	def printRows(self, button, event, view):
		""" Prints the currently selected rows of view."""
		
		if event and not self.hasActivateIntent(event):
			return False
		
		model, rows = view.get_selection().get_selected_rows()
				
		try:
			
			for row in rows:  #for each row selected
				
				sku, desc = model[row][COL_SKU], model[row][COL_DESC]
				price, quantity = model[row][COL_PRICE], model[row][COL_QUANTITY]
				
				label = LABEL_1x3.replace("#SKU", sku).replace("#PRICE", price).replace("#DESC", desc)
							
				for i in range(quantity):  #write quantity labels to printer
					lp = open("/dev/lp0", "w")
					lp.write(label)
					lp.close()
				
		except StandardError:
			return True
			
		return True
		
		
	def clearRows(self, button, event, view):
		"""Removes currently selected rows of view."""
		
		if event and not self.hasActivateIntent(event):
			return False
		
		model, rows = view.get_selection().get_selected_rows()
		
		for it in [model.get_iter(row) for row in rows]:
			model.remove(it)
			
		return True
		
	
	def __init__(self, dataFiles):
		"""Creates an instance of and initializes the applet."""
			
		window = gtk.Window(gtk.WINDOW_TOPLEVEL);  #create window
		window.connect("destroy", self.quit)
		window.set_title(self.versionString)
		
		icon = window.render_icon(gtk.STOCK_PRINT, gtk.ICON_SIZE_BUTTON)
		window.set_icon(icon)
		
		model = gtk.ListStore(str, str, str, int, float, float)  #sku, desc, price, quantity, left, center
		
		skuCell, descCell = gtk.CellRendererText(), gtk.CellRendererText()
		priceCell, quantityCell = gtk.CellRendererText(), gtk.CellRendererText()
		
		skuCell.connect("edited", self.editCellText, model, COL_SKU)
		skuCell.set_property("editable", True)
		
		descCell.connect("edited", self.editCellText, model, COL_DESC)
		descCell.set_property("editable", True)
		
		priceCell.connect("edited", self.editCellText, model, COL_PRICE)
		priceCell.set_property("editable", True)
		
		quantityCell.connect("edited", self.editCellText, model, COL_QUANTITY)
		quantityCell.set_property("editable", True)
					
		view = gtk.TreeView(model)
		view.insert_column_with_attributes(-1, "Sku", skuCell, text=COL_SKU, xalign=COL_LEFT_ALIGN)
		view.insert_column_with_attributes(-1, "Desc", descCell, text=COL_DESC, xalign=COL_LEFT_ALIGN)
		view.insert_column_with_attributes(-1, "Price", priceCell, text=COL_PRICE, xalign=COL_LEFT_ALIGN)
		view.insert_column_with_attributes(-1, "Quantity", quantityCell, text=COL_QUANTITY, xalign=COL_CENTER_ALIGN)
		
		view.get_columns()[COL_SKU].set_min_width(SKU_MIN_WIDTH)
		view.get_columns()[COL_SKU].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		
		view.get_columns()[COL_DESC].set_min_width(DESC_MIN_WIDTH)
		view.get_columns()[COL_DESC].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		view.get_columns()[COL_DESC].set_expand(True)
		
		view.get_columns()[COL_PRICE].set_min_width(PRICE_MIN_WIDTH)
		view.get_columns()[COL_PRICE].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		
		view.get_columns()[COL_QUANTITY].set_min_width(QUANTITY_MIN_WIDTH)
		view.get_columns()[COL_QUANTITY].set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
				
		view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
		view.set_size_request(TREE_MIN_WIDTH, TREE_MIN_HEIGHT)
		
		for df in dataFiles:  #parse data files from cmd line
			self.parseDataFile(df, view)
					
		allButton = gtk.Button("_Select All", None)
		allButton.connect("key-press-event", self.selectAll, view)
		allButton.connect("clicked", self.selectAll, None, view)
		
		addButton = gtk.Button(None, gtk.STOCK_ADD)
		addButton.connect("key-press-event", self.addRow, view)
		addButton.connect("clicked", self.addRow, None, view)
		
		printButton = gtk.Button(None, gtk.STOCK_PRINT)
		printButton.connect("key-press-event", self.printRows, view)
		printButton.connect("clicked", self.printRows, None, view)
		
		clearButton = gtk.Button(None, gtk.STOCK_CLEAR)
		clearButton.connect("key-press-event", self.clearRows, view)
		clearButton.connect("clicked", self.clearRows, None, view)
				
		bbox = gtk.HButtonBox()
		bbox.set_layout(gtk.BUTTONBOX_END)
		bbox.set_spacing(BUTTONBOX_SPACING)
		
		bbox.pack_end(allButton, False, False, 0)
		bbox.pack_end(addButton, False, False, 0)
		bbox.pack_end(printButton, False, False, 0)
		bbox.pack_end(clearButton, False, False, 0)
				
		vbox = gtk.VBox(False, 0)
		vbox.pack_start(view, True, True, 0)
		vbox.pack_start(bbox, False, False, BUTTONBOX_SPACING)
				
		view.get_selection().select_all()
		window.add(vbox)  #prepare to start ui
		window.show_all()
		
		gtk.main()

LabelPrinter(sys.argv[1:])  #execution begins

#End of file
