Files
foundations-of-pygtk-develo…/Tree_View_Widget/Edit_GroceryList2.py
2019-01-02 14:53:58 -05:00

180 lines
6.8 KiB
Python

#!/usr/bin/python3
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
BUY_IT = 0
QUANTITY = 1
PRODUCT = 2
PRODUCT_CATEGORY = 0
PRODUCT_CHILD = 1
GroceryItem = (( PRODUCT_CATEGORY, True, 0, "Cleaning Supplies"),
( PRODUCT_CHILD, True, 1, "Paper Towels" ),
( PRODUCT_CHILD, True, 3, "Toilet Paper" ),
( PRODUCT_CATEGORY, True, 0, "Food"),
( PRODUCT_CHILD, True, 2, "Bread" ),
( PRODUCT_CHILD, False, 1, "Butter" ),
( PRODUCT_CHILD, True, 1, "Milk" ),
( PRODUCT_CHILD, False, 3, "Chips" ),
( PRODUCT_CHILD, True, 4, "Soda" ))
class AddDialog(Gtk.Dialog):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
parent = kwargs['parent']
# set up buttons
self.add_button("Add", Gtk.ResponseType.OK)
self.add_button("Cancel", Gtk.ResponseType.CANCEL)
# set up dialog widgets
combobox = Gtk.ComboBoxText.new()
entry = Gtk.Entry.new()
spin = Gtk.SpinButton.new_with_range(0, 100, 1)
check = Gtk.CheckButton.new_with_mnemonic("_Buy the Product")
spin.set_digits(0)
# Add all of the categories to the combo box.
for row in GroceryItem:
(ptype, buy, quant, prod) = row
if ptype == PRODUCT_CATEGORY:
combobox.append_text(prod)
# create a grid
grid = Gtk.Grid.new()
grid.set_row_spacing (5)
grid.set_column_spacing(5)
# fill out the grid
grid.attach(Gtk.Label.new("Category:"), 0, 0, 1, 1)
grid.attach(Gtk.Label.new("Product:"), 0, 1, 1, 1)
grid.attach(Gtk.Label.new("Quantity:"), 0, 2, 1, 1)
grid.attach(combobox, 1, 0, 1, 1)
grid.attach(entry, 1, 1, 1, 1)
grid.attach(spin, 1, 2, 1, 1)
grid.attach(check, 1, 3, 1, 1)
self.get_content_area().pack_start(grid, True, True, 5)
self.show_all()
# run the dialog and check the results
if self.run() != Gtk.ResponseType.OK:
self.destroy()
return
quantity = spin.get_value()
product = entry.get_text()
category = combobox.get_active_text()
buy = check.get_active()
if product == "" or category == None:
print("All of the fields were not correctly filled out!")
return
model = parent.get_treeview().get_model();
iter = model.get_iter_from_string("0")
# Retrieve an iterator pointing to the selected category.
while iter:
(name,) = model.get(iter, PRODUCT)
if name.lower() == category.lower():
break
iter = model.iter_next(iter)
# Convert the category iterator to a path so that it will not become invalid
# and add the new product as a child of the category.
path = model.get_path(iter)
child = model.append(iter)
model.set(child, BUY_IT, buy, QUANTITY, quantity, PRODUCT, product)
# Add the quantity to the running total if it is to be purchased.
if buy:
iter = model.get_iter(path)
(i,) = model.get(iter, QUANTITY)
i += quantity
model.set(iter, QUANTITY, i)
self.destroy()
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_border_width(10)
self.set_size_request(275, 270)
self.treeview = Gtk.TreeView.new()
self.setup_tree_view(self.treeview)
store = Gtk.TreeStore.new((GObject.TYPE_BOOLEAN,
GObject.TYPE_INT,
GObject.TYPE_STRING))
iter = None
i = 0
for row in GroceryItem:
(ptype, buy, quant, prod) = row
if ptype == PRODUCT_CATEGORY:
j = i + 1
(ptype1, buy1, quant1, prod1) = GroceryItem[j]
while j < len(GroceryItem) and ptype1 == PRODUCT_CHILD:
if buy1:
quant += quant1
j += 1;
if j < len(GroceryItem):
(ptype1, buy1, quant1, prod1) = GroceryItem[j]
iter = store.append(None)
store.set(iter, BUY_IT, buy, QUANTITY, quant, PRODUCT, prod)
else:
child = store.append(iter)
store.set(child, BUY_IT, buy, QUANTITY, quant, PRODUCT, prod)
i += 1
self.treeview.set_model(store)
self.treeview.expand_all()
scrolled_win = Gtk.ScrolledWindow.new(None, None)
scrolled_win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled_win.add(self.treeview)
button_add = Gtk.Button.new_with_label("Add")
button_add.connect("clicked", self.on_add_button_clicked, self)
button_remove = Gtk.Button.new_with_label("Remove")
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
hbox.pack_end(button_remove, False, True, 5)
hbox.pack_end(button_add, False, True, 5)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
vbox.pack_end(hbox, False, True, 5)
vbox.pack_end(scrolled_win, True, True, 5)
self.add(vbox)
def setup_tree_view(self, treeview):
renderer = Gtk.CellRendererText.new()
column = Gtk.TreeViewColumn("Buy", renderer, text=BUY_IT)
self.treeview.append_column(column)
renderer = Gtk.CellRendererText.new()
column = Gtk.TreeViewColumn("Count", renderer, text=QUANTITY)
treeview.append_column(column)
renderer = Gtk.CellRendererText.new()
renderer.set_property("editable", True)
renderer.connect("edited", self.cell_edited, treeview)
column = Gtk.TreeViewColumn("Product", renderer, text=PRODUCT)
treeview.append_column(column)
def on_add_button_clicked(self, button, parent):
dialog = AddDialog(title="Add a Product", parent=parent,
flags=Gtk.DialogFlags.MODAL)
def get_treeview(self):
return self.treeview
def cell_edited(self, renderer, path, new_text, treeview):
if len(new_text) > 0:
model = treeview.get_model()
iter = model.get_iter_from_string(path)
if iter:
model.set(iter, PRODUCT, new_text)
class Application(Gtk.Application):
def __init__(self, *args, **kwargs):
super().__init__(*args, application_id="org.example.myapp",
**kwargs)
self.window = None
def do_activate(self):
if not self.window:
self.window = AppWindow(application=self, title="Grocery List")
self.window.show_all()
self.window.present()
if __name__ == "__main__":
app = Application()
app.run(sys.argv)