Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Silbe <sascha-pgp@silbe.org>2010-04-11 22:32:36 (GMT)
committer Sascha Silbe <sascha-pgp@silbe.org>2010-04-11 22:32:36 (GMT)
commit1e71c79f110f825596551d8e9bff0978c0128e9d (patch)
treeb1cd99794bdf3bfd997f1a0aa579ea26d6558d46
parentc597bef4015d51bb60275be7ddae9ab88fece699 (diff)
erase (in 'demo' mode), hover effect, style fixesHEADmaster
-rw-r--r--janitor.py104
1 files changed, 91 insertions, 13 deletions
diff --git a/janitor.py b/janitor.py
index d64ed6b..16a6872 100644
--- a/janitor.py
+++ b/janitor.py
@@ -29,6 +29,7 @@ from sugar.activity.widgets import StopButton
from sugar.activity import activity
from sugar.datastore import datastore
import sugar.env
+from sugar.graphics import style
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.toolbarbox import ToolbarBox
from sugar.graphics.toolbarbox import ToolbarButton
@@ -61,6 +62,14 @@ def format_size(size):
return _('%4d GB') % (size / 1024**3)
+class EraseButton(ToolButton):
+
+ def __init__(self, **kwargs):
+ ToolButton.__init__(self, 'edit-delete', **kwargs)
+ self.props.tooltip = _('Erase selected entries')
+ self.props.accelerator = '<Delete>'
+
+
class JanitorActivity(activity.Activity):
_store_columns = [
@@ -69,15 +78,16 @@ class JanitorActivity(activity.Activity):
gobject.TYPE_UINT64,
gobject.TYPE_FLOAT,
gobject.TYPE_STRING,
+ gobject.TYPE_PYOBJECT,
]
NUM_COLUMNS = len(_store_columns)
- COLUMN_SELECT, COLUMN_TITLE, COLUMN_SIZE_INT, COLUMN_SIZE_PERCENT, \
- COLUMN_SIZE_TEXT = range(NUM_COLUMNS)
+ COLUMN_SELECTED, COLUMN_TITLE, COLUMN_SIZE_INT, COLUMN_SIZE_PERCENT, \
+ COLUMN_SIZE_TEXT, COLUMN_OBJECT_ID = range(NUM_COLUMNS)
_view_columns = [
{'name': 'Select',
'renderer': gtk.CellRendererToggle,
- 'view_args': {'active': COLUMN_SELECT},
+ 'view_args': {'active': COLUMN_SELECTED},
'callback': lambda cell, path, self: self._select_toggled(cell, path),
},
{'name': 'Title',
@@ -108,32 +118,63 @@ class JanitorActivity(activity.Activity):
def _setup_canvas(self):
vbox = gtk.VBox()
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
self._create_list_model()
self._list_view = gtk.TreeView(self._list_model)
- self._list_view.set_rules_hint(True)
+ self._list_view.set_hover_selection(True)
+ self._list_view.modify_base(gtk.STATE_NORMAL,
+ style.COLOR_WHITE.get_gdk_color())
+ self._list_view.modify_base(gtk.STATE_ACTIVE,
+ style.COLOR_HIGHLIGHT.get_gdk_color())
+ self._list_view.modify_base(gtk.STATE_SELECTED,
+ style.COLOR_HIGHLIGHT.get_gdk_color())
+ self._list_view.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_PANEL_GREY.get_gdk_color())
+
+ # big hack to make the scrollbar not "overwrite" the header, from
+ # http://mail.gnome.org/archives/gtk-list/2008-November/msg00111.html
+ list_scroll = gtk.VScrollbar(self._list_view.get_vadjustment())
+ list_hbox = gtk.HBox(False, 0)
+ list_vbox = gtk.VBox(False, 0)
+ list_pad_widget = gtk.EventBox()
+ list_pad_widget.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_PANEL_GREY.get_gdk_color())
+ list_hbox.pack_start(self._list_view, True, True, 0)
+ list_hbox.pack_start(list_vbox, False, False, 0)
+ list_vbox.pack_start(list_pad_widget, False, False, 0)
+ list_vbox.pack_start(list_scroll, True, True, 0)
+ list_vbox.show()
+ list_pad_widget.show()
+ list_scroll.show()
+ list_hbox.show()
+ self._list_view.connect('map', self.__list_view_map_cb, list_pad_widget)
- scrolled_window.add(self._list_view)
self._setup_list_view_columns()
sort_column_idx = [idx for idx, column in enumerate(self._view_columns)
if column['name'] == 'Size'][0]
self._list_model.set_sort_column_id(sort_column_idx, gtk.SORT_DESCENDING)
self._list_view.show()
- scrolled_window.show()
- vbox.add(scrolled_window)
+ vbox.add(list_hbox)
self.set_canvas(vbox)
vbox.show()
+ def __list_view_map_cb(self, list_view, pad_widget):
+ x, y = list_view.convert_bin_window_to_widget_coords(0, 0)
+ pad_widget.set_size_request(-1, y)
+
def _setup_toolbar(self):
toolbar_box = ToolbarBox()
activity_button = ActivityToolbarButton(self)
- toolbar_box.toolbar.insert(activity_button, 0)
+ toolbar_box.toolbar.insert(activity_button, -1)
activity_button.show()
+ erase_button = EraseButton()
+ erase_button.connect('clicked', self.__erase_cb)
+ toolbar_box.toolbar.insert(erase_button, -1)
+ erase_button.show()
+
separator = gtk.SeparatorToolItem()
separator.props.draw = False
separator.set_expand(True)
@@ -148,6 +189,12 @@ class JanitorActivity(activity.Activity):
toolbar_box.show()
def _setup_list_view_columns(self):
+ def column_label_map_cb(label):
+ # another bad hack to work around GTK limitations
+ header_button = label.get_parent().get_parent().get_parent()
+ header_button.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_PANEL_GREY.get_gdk_color())
+
for idx, column in enumerate(self._view_columns):
renderer = column['renderer']()
if column.get('ellipsize'):
@@ -165,6 +212,13 @@ class JanitorActivity(activity.Activity):
view_column = gtk.TreeViewColumn(_(column['name']), renderer,
**column['view_args'])
+ column_label = gtk.Label(_(column['name']))
+ column_label.modify_fg(gtk.STATE_NORMAL,
+ style.COLOR_BLACK.get_gdk_color())
+ column_label.connect('map', column_label_map_cb)
+ column_label.show()
+ view_column.set_widget(column_label)
+
if isinstance(renderer, gtk.CellRendererText):
view_column.props.expand = True
@@ -196,6 +250,7 @@ class JanitorActivity(activity.Activity):
entries.append({
'size': size,
'title': metadata.get('title', ''),
+ 'object_id': jobject.object_id,
})
jobject.destroy()
@@ -210,7 +265,8 @@ class JanitorActivity(activity.Activity):
self.COLUMN_TITLE, entry['title'],
self.COLUMN_SIZE_INT, entry['size'],
self.COLUMN_SIZE_PERCENT, percent,
- self.COLUMN_SIZE_TEXT, format_size(entry['size']))
+ self.COLUMN_SIZE_TEXT, format_size(entry['size']),
+ self.COLUMN_OBJECT_ID, entry['object_id'])
def _get_size(self, jobject):
"""Return the file size for a Journal object."""
@@ -224,8 +280,30 @@ class JanitorActivity(activity.Activity):
def _select_toggled(self, cell, path):
"""Called when a 'Select' cell is toggled."""
giter = self._list_model.get_iter((int(path), ))
- selected = self._list_model.get_value(giter, self.COLUMN_SELECT)
- self._list_model.set(giter, self.COLUMN_SELECT, not selected)
+ selected = self._list_model.get_value(giter, self.COLUMN_SELECTED)
+ self._list_model.set(giter, self.COLUMN_SELECTED, not selected)
+
+ def __erase_cb(self, button):
+ self._apply_action(self._get_selection(), self._erase)
+
+ def _get_selection(self):
+ """Return object_ids of all selected entries."""
+ return [row[self.COLUMN_OBJECT_ID] for row in self._list_model
+ if row[self.COLUMN_SELECTED]]
+
+ def _apply_action(self, entries, action):
+ """Apply action to all entries."""
+ [action(entry) for entry in entries]
+
+ def _erase(self, object_id):
+ """Delete given entry from data store."""
+ for row in self._list_model:
+ if row[self.COLUMN_OBJECT_ID] == object_id:
+ self._list_model.remove(row.iter)
+ return
+
+ raise ValueError('object_id %r not found in self._list_model' % (
+ object_id, ))
sugar.logger.start()