diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jarabe/journal/browse/localsource.py | 41 | ||||
-rw-r--r-- | src/jarabe/journal/browse/smoothtable.py | 290 | ||||
-rw-r--r-- | src/jarabe/journal/browse/source.py | 85 | ||||
-rw-r--r-- | src/jarabe/journal/browse/tableview.py | 7 | ||||
-rw-r--r-- | src/jarabe/journal/objectview.py (renamed from src/jarabe/journal/objectsview.py) | 0 |
5 files changed, 294 insertions, 129 deletions
diff --git a/src/jarabe/journal/browse/localsource.py b/src/jarabe/journal/browse/localsource.py deleted file mode 100644 index e19941e..0000000 --- a/src/jarabe/journal/browse/localsource.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2009, Aleksey Lim -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk - -from jarabe.journal.browse.source import Source - -class LocalSource(Source): - def __init__(self, resultset): - Source.__init__(self) - self._resultset = resultset - - def get_count(self): - return self._resultset.length - - def get_row(self, offset): - if offset >= self.get_count(): - return False - self._resultset.seek(offset) - return self._resultset.read() - - def get_order(self): - """ Get current order, returns (field_name, gtk.SortType) """ - pass - - def set_order(self, field_name, sort_type): - """ Set current order """ - pass diff --git a/src/jarabe/journal/browse/smoothtable.py b/src/jarabe/journal/browse/smoothtable.py new file mode 100644 index 0000000..8962a11 --- /dev/null +++ b/src/jarabe/journal/browse/smoothtable.py @@ -0,0 +1,290 @@ +# Copyright (C) 2009, Aleksey Lim +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import gtk +import gobject +import math +import bisect +import logging + +class SmoothTable(gtk.Container): + __gsignals__ = { + 'set-scroll-adjustments': (gobject.SIGNAL_RUN_FIRST, None, + [gtk.Adjustment, gtk.Adjustment]), + 'fill-in': (gobject.SIGNAL_RUN_FIRST, None, + [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), + } + + def __init__(self, rows, columns, new_widget): + assert(rows and columns) + + self._rows = [] + self._adj = None + self._adj_value_changed_id = None + self._bin_window = None + self._bin_rows = 0 + self._cell_height = 0 + self._reordered = None + self._last_allocation = None + + gtk.Container.__init__(self) + + cell_no = 0 + for y in range(rows + 2): + row = [] + for x in range(columns): + cell = new_widget() + cell.set_parent(self) + cell.size_allocate(gtk.gdk.Rectangle(-1, -1)) + cell_no += 1 + row.append(cell) + self._rows.append(row) + + def get_columns(self): + return len(self._rows[0]) + + columns = property(get_columns) + + def get_rows(self): + return len(self._rows) - 2 + + rows = property(get_rows) + + def get_head(self): + if self._adj is None: + return 0 + return int(self._adj.value) - int(self._adj.value) % self._cell_height + + head = property(get_head) + + def set_count(self, count): + self._bin_rows = max(0, math.ceil(float(count) / len(self._rows[0]))) + + if self._adj is not None: + self._setup_adjustment(force=True) + if self.flags() & gtk.REALIZED: + self._bin_window.resize(self.allocation.width, + int(self._adj.upper)) + + def do_realize(self): + self.set_flags(gtk.REALIZED) + + self.window = gtk.gdk.Window( + self.get_parent_window(), + window_type=gtk.gdk.WINDOW_CHILD, + x=self.allocation.x, + y=self.allocation.y, + width=self.allocation.width, + height=self.allocation.height, + wclass=gtk.gdk.INPUT_OUTPUT, + colormap=self.get_colormap(), + event_mask=gtk.gdk.VISIBILITY_NOTIFY_MASK) + self.window.set_user_data(self) + + self._bin_window = gtk.gdk.Window( + self.window, + window_type=gtk.gdk.WINDOW_CHILD, + x=0, + y=int(-self._adj.value), + width=self.allocation.width, + height=int(self._adj.upper), + colormap=self.get_colormap(), + wclass=gtk.gdk.INPUT_OUTPUT, + event_mask=(self.get_events() | gtk.gdk.EXPOSURE_MASK | + gtk.gdk.SCROLL_MASK)) + self._bin_window.set_user_data(self) + + self.set_style(self.style.attach(self.window)) + self.style.set_background(self.window, gtk.STATE_NORMAL) + self.style.set_background(self._bin_window, gtk.STATE_NORMAL) + + for row in self._rows: + for cell in row: + cell.set_parent_window(self._bin_window) + + self.queue_resize() + + def do_size_allocate(self, allocation): + if self._reordered is not None: + if allocation == self._reordered: + self._reordered = None + return + self._reordered = None + + self.allocation = allocation + self._cell_height = allocation.height / self.rows + + self._setup_adjustment(force=True) + + if self.flags() & gtk.REALIZED: + self.window.move_resize(*allocation) + self._bin_window.resize(allocation.width, int(self._adj.upper)) + + def do_unrealize(self): + self._bin_window.set_user_data(None) + self._bin_window.destroy() + self._bin_window = None + gtk.Container.do_unrealize(self) + + def do_style_set(self, style): + gtk.Widget.do_style_set(self, style) + if self.flags() & gtk.REALIZED: + self.style.set_background(self._bin_window, gtk.STATE_NORMAL) + + def do_expose_event(self, event): + if event.window != self._bin_window: + return False + gtk.Container.do_expose_event(self, event) + return False + + def do_map(self): + self.set_flags(gtk.MAPPED) + + for row in self._rows: + for cell in row: + cell.map() + + self._bin_window.show() + self.window.show() + + def do_size_request(self, req): + req.width = 0 + req.height = 0 + + for row in self._rows: + for cell in row: + cell.size_request() + + def do_forall(self, include_internals, callback, data): + for row in self._rows: + for cell in row: + callback(cell, data) + + def do_add(self, widget): + pass + + def do_remove(self, widget): + pass + + def do_set_scroll_adjustments(self, hadjustment, vadjustment): + if vadjustment is None or vadjustment == self._adj: + return + + if self._adj is not None: + self._adj.disconnect(self._adj_value_changed_id) + + self._adj = vadjustment + self._setup_adjustment() + + self._adj_value_changed_id = vadjustment.connect('value-changed', + self.__adjustment_value_changed_cb) + + def _setup_adjustment(self, force=False): + self._adj.lower = 0 + self._adj.upper = self._bin_rows * self._cell_height + self._adj.page_size = self.allocation.height + self._adj.changed() + + max_value = max(0, self._adj.upper - self._adj.page_size) + if self._adj.value > max_value: + self._adj.value = max_value + self._adj.value_changed() + elif force: + self._adj.value_changed() + + def _allocate_row(self, row, cell_y): + cell_x = 0 + cell_no = cell_y / self._cell_height * self.columns + + for cell in row: + self.emit('fill-in', cell, cell_no) + + callocation = gtk.gdk.Rectangle(cell_x, cell_y) + callocation.width = self.allocation.width / self.columns + callocation.height = self._cell_height + cell.size_allocate(callocation) + + cell_x += callocation.width + cell_no += 1 + + def __adjustment_value_changed_cb(self, sender=None): + if not self.flags() & gtk.REALIZED: + return + + spare_rows = [] + visible_rows = [] + page_end = self._adj.value + self._adj.page_size + + if self._last_allocation != self.allocation: + self._last_allocation = self.allocation + spare_rows = [] + self._rows + else: + class IndexedRow: + def __init__(self, row): + self.row = row + + def __lt__(self, other): + return self.row[0].allocation.y < other.row[0].allocation.y + + for row in self._rows: + if row[0].allocation.y < 0 or \ + row[0].allocation.y > page_end or \ + (row[0].allocation.y + self._cell_height) < \ + self._adj.value: + spare_rows.append(row) + else: + bisect.insort_right(visible_rows, IndexedRow(row)) + + if not visible_rows or \ + len(visible_rows) < self.rows + (self.head != visible_rows[0]): + self._reordered = self.allocation + + def insert_spare_row(cell_y, end_y): + while cell_y < end_y: + if not spare_rows: + logging.error('spare_rows should not be empty') + return + row = spare_rows.pop() + self._allocate_row(row, cell_y) + cell_y = cell_y + self._cell_height + + cell_y = self.head + for i in visible_rows: + insert_spare_row(cell_y, i.row[0].allocation.y) + cell_y = i.row[0].allocation.y + i.row[0].allocation.height + insert_spare_row(cell_y, page_end) + + self._bin_window.move(0, int(-self._adj.value)) + self.window.process_updates(True) + +SmoothTable.set_set_scroll_adjustments_signal('set-scroll-adjustments') + +if __name__ == '__main__': + window = gtk.Window() + + scrolled = gtk.ScrolledWindow() + scrolled.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS) + window.add(scrolled) + + def cb(sender, button, offset): + button.props.label = str(offset) + table = SmoothTable(3, 3, gtk.Button) + table.connect('fill-in', cb) + table.set_count(100) + scrolled.add(table) + + window.show_all() + gtk.main() diff --git a/src/jarabe/journal/browse/source.py b/src/jarabe/journal/browse/source.py deleted file mode 100644 index 64fa2ab..0000000 --- a/src/jarabe/journal/browse/source.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (C) 2009, Aleksey Lim -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk -from gobject import property, GObject, SIGNAL_RUN_FIRST, TYPE_PYOBJECT - -FIELD_UID = 0 -FIELD_TITLE = 1 -FIELD_MTIME = 2 -FIELD_TIMESTAMP = 3 -FIELD_KEEP = 4 -FIELD_BUDDIES = 5 -FIELD_ICON_COLOR = 6 -FIELD_MIME_TYPE = 7 -FIELD_PROGRESS = 8 -FIELD_ACTIVITY = 9 -FIELD_MOUNT_POINT = 10 -FIELD_ACTIVITY_ID = 11 -FIELD_BUNDLE_ID = 12 - -FIELD_FAVORITE = 30 -FIELD_ICON = 31 -FIELD_MODIFY_TIME = 32 -FIELD_THUMB = 33 - -FIELDS_LIST = {'uid': (FIELD_UID, str), - 'title': (FIELD_TITLE, str), - 'mtime': (FIELD_MTIME, str), - 'timestamp': (FIELD_TIMESTAMP, int), - 'keep': (FIELD_KEEP, int), - 'buddies': (FIELD_BUDDIES, str), - 'icon-color': (FIELD_ICON_COLOR, str), - 'mime_type': (FIELD_MIME_TYPE, str), - 'progress': (FIELD_MIME_TYPE, str), - 'activity': (FIELD_ACTIVITY, str), - 'mountpoint': (FIELD_ACTIVITY, str), - 'activity_id': (FIELD_ACTIVITY_ID, str), - 'bundle_id': (FIELD_BUNDLE_ID, str), - - 'favorite': (FIELD_FAVORITE, bool), - 'icon': (FIELD_ICON, str), - 'modify_time': (FIELD_MODIFY_TIME, str), - 'thumb': (FIELD_THUMB, gtk.gdk.Pixbuf)} - -class Source(GObject): - __gsignals__ = { - 'objects-updated': (SIGNAL_RUN_FIRST, None, []), - 'row-delayed-fetch': (SIGNAL_RUN_FIRST, None, 2*[TYPE_PYOBJECT]) - } - - def get_count(self): - """ Returns number of objects """ - pass - - def get_row(self, offset): - """ Get object - - Returns: - objects in dict {field_name: value, ...} - False can't fint object - None wait for reply signal - - """ - pass - - def get_order(self): - """ Get current order, returns (field_name, gtk.SortType) """ - pass - - def set_order(self, field_name, sort_type): - """ Set current order """ - pass diff --git a/src/jarabe/journal/browse/tableview.py b/src/jarabe/journal/browse/tableview.py index 43a871b..4aa6697 100644 --- a/src/jarabe/journal/browse/tableview.py +++ b/src/jarabe/journal/browse/tableview.py @@ -329,7 +329,7 @@ class TableView(gtk.Bin): def _get_frame(self): adj = self._full_adjustment return (int(adj.value / self._cell_height) * self._cols, - (int(adj.value / self._cell_height) + self._rows) * \ + (int(adj.value / self._cell_height) + self._rows + 1) * \ self._cols - 1) def __adjustment_value_changed(self, adjustment, force=False): @@ -361,8 +361,9 @@ class TableView(gtk.Bin): cell.row = None if cell_num < count: - cell.row = self._model.get_row((cell_num,), - self._get_frame()) + row = self._model.get_row((cell_num,), self._get_frame()) + if row != False: + cell.row = row self._fillin_cell(canvas, cell) cell_num += 1 diff --git a/src/jarabe/journal/objectsview.py b/src/jarabe/journal/objectview.py index fca232b..fca232b 100644 --- a/src/jarabe/journal/objectsview.py +++ b/src/jarabe/journal/objectview.py |