--- a/blogic/categories.py Wed Jan 03 10:46:07 2007 -0300
+++ b/blogic/categories.py Wed Jan 03 15:16:30 2007 -0300
@@ -1,4 +1,8 @@
#!/usr/bin/env python
+
+__doc__ = """Basic widgets for handling categories, where
+only one can be primary and many other can be secondary."""
+
#
# blogic - Tool for blog's messages publishing
# Copyright (C) 2006 German Poo-Caaman~o <gpoo@ubiobio.cl>
@@ -21,9 +25,6 @@
pygtk.require('2.0')
import gtk
-import gobject
-import gtkspell
-from gettext import bindtextdomain, textdomain
from gettext import gettext as _
(
@@ -33,22 +34,32 @@
COLUMN_NAME,
) = range(4)
-data = (
- (0, False, False, 'Trivia'),
- (1, False, False, 'Normal'),
- (2, False, False, 'Critical'),
- (3, False, False, 'Urgent')
-)
+class CategoryView(gtk.TreeView):
+ "A custom implementation of gtk.TreeView for handle categories."
+
+ def __init__(self, data):
+ """Initialize a gtk.TreeView creating a gtk.ListStore using
+ the list given.
-class CategoryView(gtk.TreeView):
- def __init__(self, *args):
- gtk.TreeView.__init__(self, *args)
- self.set_model(self._create_model())
+ data is expected to be a list of tuples of (str, bool, bool, str):
+ [ (id, is_primary, is_secondary, category),
+ (id, is_primary, is_secondary, category),
+ ...
+ (id, is_primary, is_secondary, category)
+ ]
+
+ When more than one tuple is declared as active, only the first
+ one will be marked as primary and the others will be marked as
+ secondary.
+ """
+ gtk.TreeView.__init__(self)
+
+ self.primary_path = None
+ self.set_model(self._create_model(data))
self._add_columns()
- self.primary_path = None
- def _create_model(self):
- # Store
+ def _create_model(self, data):
+ more_than_one_primary = False
store = gtk.ListStore(str, bool, bool, str)
for item in data:
iter = store.append()
@@ -57,6 +68,16 @@
COLUMN_PRIMARY, item[COLUMN_PRIMARY],
COLUMN_SECONDARY, item[COLUMN_SECONDARY],
COLUMN_NAME, item[COLUMN_NAME])
+
+ if more_than_one_primary:
+ store.set(iter, COLUMN_PRIMARY, False)
+ store.set(iter, COLUMN_SECONDARY, True)
+
+ if store.get_value(iter, COLUMN_PRIMARY):
+ store.set(iter, COLUMN_SECONDARY, True)
+ more_than_one_primary = True
+ self.primary_path = store.get_path(iter)
+
return store
def _add_columns(self):
@@ -64,17 +85,17 @@
cell = gtk.CellRendererToggle()
cell.connect('toggled', self._primary_toggled, model)
- column = gtk.TreeViewColumn("Main", cell, active=COLUMN_PRIMARY)
+ column = gtk.TreeViewColumn(_('Main'), cell, active=COLUMN_PRIMARY)
self.append_column(column)
cell = gtk.CellRendererToggle()
cell.connect('toggled', self._secondary_toggled, model)
- column = gtk.TreeViewColumn("Use", cell, active=COLUMN_SECONDARY)
+ column = gtk.TreeViewColumn(_('Use'), cell, active=COLUMN_SECONDARY)
column.set_sort_column_id(COLUMN_SECONDARY)
self.append_column(column)
cell = gtk.CellRendererText()
- column = gtk.TreeViewColumn("Category", cell, text=COLUMN_NAME)
+ column = gtk.TreeViewColumn(_('Category'), cell, text=COLUMN_NAME)
column.set_sort_column_id(COLUMN_NAME)
self.append_column(column)
@@ -93,6 +114,9 @@
self.primary_path = path
def _secondary_toggled(self, cell, path, model):
+ """Handle when the secondary category is selected/unselected.
+ When it gets unselected and it was also primary, we
+ unselected as primary as well."""
iter = model.get_iter(path)
secondary = not model.get_value(iter, COLUMN_SECONDARY)
model.set(iter, COLUMN_SECONDARY, secondary)
@@ -101,41 +125,88 @@
model.set(iter, COLUMN_PRIMARY, False)
self.primary_path = None
-class CategoryWindow(gtk.Window):
- def __init__(self, *args):
- gtk.Window.__init__(self, *args)
+ def get_data(self):
+ """Returns two dictionaries. The firts one with the primary
+ category selected and the second one with the secondaries
+ categories selected.
+ """
+
+ model = self.get_model()
+ primary = {}
+ secondary = {}
+ for row in model:
+ if not row[COLUMN_PRIMARY] and row[COLUMN_SECONDARY]:
+ id = row[COLUMN_ID]
+ secondary[id] = row[COLUMN_NAME]
+ elif row[COLUMN_PRIMARY]:
+ id = row[COLUMN_ID]
+ primary[id] = row[COLUMN_NAME]
- self.set_border_width(8)
- self.set_title('Choose categories')
+ # If we only have secondary categories, we need to choose
+ # whichever of them as a primary
+ if not primary and secondary:
+ import random
+ rand = random.Random()
+ id = rand.choice(secondary.keys())
+ primary[id] = secondary[id]
+ secondary.pop(id)
+ return (primary, secondary)
+
+class CategoryDialog(gtk.Dialog):
+ """Implements a dialog to choose categories using the widget
+ CategoryView.
+ """
+ def __init__(self, data, title='Choose categories', parent=None,
+ flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OK, gtk.RESPONSE_OK)):
+ """It has the same behavior as gtk.Dialog, but expects an
+ extra parameter (data) wich is used to fill the model
+ of the widget CategoryView.
+
+ data is expected to be a list of tuples of (str, bool, bool, str):
+ [ (id, is_primary, is_secondary, category),
+ (id, is_primary, is_secondary, category),
+ ...
+ (id, is_primary, is_secondary, category)
+ ]
+
+ When more than one tuple is declared as active, only the first
+ one will be marked as primary and the others will be marked as
+ secondary.
+ """
+ gtk.Dialog.__init__(self, title, parent, flags, buttons)
scroll = gtk.ScrolledWindow()
scroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
- treeview = CategoryView()
- treeview.set_rules_hint(True)
+ self.treeview = CategoryView(data)
+ self.treeview.set_rules_hint(True)
+ scroll.add(self.treeview)
- scroll.add(treeview)
-
- vbox = gtk.VBox(False, 8)
- vbox.pack_start(scroll)
+ self.vbox.pack_start(scroll)
- bbox = gtk.HButtonBox()
- bbox.set_layout(gtk.BUTTONBOX_END)
- bbox.set_spacing(8)
- #bbox.set_border_width(12)
- bbox.add(gtk.Button(stock='gtk-cancel'))
- bbox.add(gtk.Button(stock='gtk-ok'))
-
- vbox.pack_start(bbox, False, False)
-
- self.add(vbox)
+ def get_categories_choosen(self):
+ """Returns two dictionaries. The firts one with the primary
+ category selected and the second one with the secondaries
+ categories selected.
+ """
+ return self.treeview.get_data()
if __name__ == "__main__":
- window = CategoryWindow(gtk.WINDOW_TOPLEVEL)
- #window = create_window()
- window.set_default_size(300,250)
- window.connect('delete-event', gtk.main_quit, None)
- window.show_all()
+ test_data = [
+ (0, False, False, 'Trivia'),
+ (1, True, False, 'Normal'),
+ (2, False, True, 'Critical'),
+ (3, True, False, 'Urgent')
+ ]
- gtk.main()
+ dialog = CategoryWindow(data=test_data)
+ dialog.set_default_size(300,250)
+ dialog.show_all()
+ result = dialog.run()
+
+ while result == gtk.RESPONSE_OK:
+ print dialog.get_categories_choosen()
+ result = dialog.run()