aboutsummaryrefslogtreecommitdiffstats
path: root/mvc/widgets/osx/tablemodel.py
diff options
context:
space:
mode:
authorJesús Eduardo <heckyel@hyperbola.info>2017-09-11 17:47:17 -0500
committerJesús Eduardo <heckyel@hyperbola.info>2017-09-11 17:47:17 -0500
commit14738704ede6dfa6ac79f362a9c1f7f40f470cdc (patch)
tree31c83bdd188ae7b64d7169974d6f066ccfe95367 /mvc/widgets/osx/tablemodel.py
parenteb1896583afbbb622cadcde1a24e17173f61904f (diff)
downloadlibrevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.tar.lz
librevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.tar.xz
librevideoconverter-14738704ede6dfa6ac79f362a9c1f7f40f470cdc.zip
rename mvc at lvc
Diffstat (limited to 'mvc/widgets/osx/tablemodel.py')
-rw-r--r--mvc/widgets/osx/tablemodel.py532
1 files changed, 0 insertions, 532 deletions
diff --git a/mvc/widgets/osx/tablemodel.py b/mvc/widgets/osx/tablemodel.py
deleted file mode 100644
index 980b60b..0000000
--- a/mvc/widgets/osx/tablemodel.py
+++ /dev/null
@@ -1,532 +0,0 @@
-# @Base: Miro - an RSS based video player application
-# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
-# Participatory Culture Foundation
-#
-# 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
-#
-# In addition, as a special exception, the copyright holders give
-# permission to link the code of portions of this program with the OpenSSL
-# library.
-#
-# You must obey the GNU General Public License in all respects for all of
-# the code used other than OpenSSL. If you modify file(s) with this
-# exception, you may extend this exception to your version of the file(s),
-# but you are not obligated to do so. If you do not wish to do so, delete
-# this exception statement from your version. If you delete this exception
-# statement from all source files in the program, then also delete it here.
-
-"""tablemodel.py -- Model classes for TableView. """
-
-import logging
-
-from AppKit import (NSDragOperationNone, NSDragOperationAll, NSTableViewDropOn,
- NSOutlineViewDropOnItemIndex, protocols)
-from Foundation import NSObject, NSNotFound, NSMutableIndexSet
-from objc import YES, NO, nil
-
-from mvc import signals
-from mvc.errors import WidgetActionError
-import fasttypes
-import wrappermap
-
-MIRO_DND_ITEM_LOCAL = 'miro-local-item'
-
-# XXX need unsigned but value comes out as signed.
-NSDragOperationEvery = NSDragOperationAll
-
-def list_from_nsindexset(index_set):
- rows = list()
- index = index_set.firstIndex()
- while (index != NSNotFound):
- rows.append(index)
- index = index_set.indexGreaterThanIndex_(index)
- return rows
-
-class RowList(object):
- """RowList is a Linked list that has some optimizations for looking up
- rows by index number.
- """
- def __init__(self):
- self.list = fasttypes.LinkedList()
- self.iter_cache = []
-
- def firstIter(self):
- return self.list.firstIter()
-
- def lastIter(self):
- return self.list.lastIter()
-
- def insertBefore(self, iter, value):
- self.iter_cache = []
- if iter is None:
- return self.list.append(value)
- else:
- return self.list.insertBefore(iter, value)
-
- def append(self, value):
- return self.list.append(value)
-
- def __len__(self):
- return len(self.list)
-
- def __getitem__(self, iter):
- return self.list[iter]
-
- def __iter__(self):
- iter = self.firstIter()
- while iter != self.lastIter():
- yield iter.value()
- iter.forward()
-
- def remove(self, iter):
- self.iter_cache = []
- return self.list.remove(iter)
-
- def nth_iter(self, index):
- if index < 0:
- raise IndexError(index)
- elif index >= len(self):
- raise LookupError()
- if len(self.iter_cache) == 0:
- self.iter_cache.append(self.firstIter())
- try:
- return self.iter_cache[index].copy()
- except IndexError:
- pass
- iter = self.iter_cache[-1].copy()
- index -= len(self.iter_cache) - 1
- for x in xrange(index):
- iter.forward()
- self.iter_cache.append(iter.copy())
- return iter
-
-class TableModelBase(signals.SignalEmitter):
- """Base class for TableModel and TreeTableModel."""
- def __init__(self, *column_types):
- signals.SignalEmitter.__init__(self)
- self.row_list = RowList()
- self.column_types = column_types
- self.create_signal('row-changed')
- self.create_signal('structure-will-change')
-
- def check_column_values(self, column_values):
- if len(self.column_types) != len(column_values):
- raise ValueError("Wrong number of columns")
- # We might want to do more typechecking here
-
- def get_column_data(self, row, column):
- attr_map = column.attrs()
- return dict((name, row[index]) for name, index in attr_map.items())
-
- def update_value(self, iter, index, value):
- iter.value().values[index] = value
- self.emit('row-changed', iter)
-
- def update(self, iter, *column_values):
- iter.value().update_values(column_values)
- self.emit('row-changed', iter)
-
- def remove(self, iter):
- self.emit('structure-will-change')
- row_list = self.containing_list(iter)
- rv = row_list.remove(iter)
- if rv == row_list.lastIter():
- rv = None
- return rv
-
- def nth_iter(self, index):
- return self.row_list.nth_iter(index)
-
- def next_iter(self, iter):
- row_list = self.containing_list(iter)
- retval = iter.copy()
- retval.forward()
- if retval == row_list.lastIter():
- return None
- else:
- return retval
-
- def first_iter(self):
- if len(self.row_list) > 0:
- return self.row_list.firstIter()
- else:
- return None
-
- def __len__(self):
- return len(self.row_list)
-
- def __getitem__(self, iter):
- return iter.value()
-
- def __iter__(self):
- return iter(self.row_list)
-
-class TableRow(object):
- """See https://develop.participatoryculture.org/index.php/WidgetAPITableView for a description of the API for this class."""
- def __init__(self, column_values):
- self.update_values(column_values)
-
- def update_values(self, column_values):
- self.values = list(column_values)
-
- def __getitem__(self, index):
- return self.values[index]
-
- def __len__(self):
- return len(self.values)
-
- def __iter__(self):
- return iter(self.values)
-
-class TableModel(TableModelBase):
- """See https://develop.participatoryculture.org/index.php/WidgetAPITableView for a description of the API for this class."""
- def __init__(self, *column_types):
- TableModelBase.__init__(self, column_types)
- self.row_indexes = {}
-
- def remember_row_at_index(self, row, index):
- if row not in self.row_indexes:
- self.row_indexes[row] = index
-
- def row_of_iter(self, tableview, iter):
- row = iter.value()
- try:
- return self.row_indexes[row]
- except KeyError:
- iter = self.row_list.firstIter()
- index = 0
- while iter != self.row_list.lastIter():
- current_row = iter.value()
- self.row_indexes[current_row] = index
- if current_row is row:
- return index
- index += 1
- iter.forward()
- raise LookupError("%s is not in this table" % row)
-
- def containing_list(self, iter):
- return self.row_list
-
- def append(self, *column_values):
- self.emit('structure-will-change')
- self.row_indexes = {}
- retval = self.row_list.append(TableRow(column_values))
- return retval
-
- def remove(self, iter):
- self.row_indexes = {}
- return TableModelBase.remove(self, iter)
-
- def insert_before(self, iter, *column_values):
- self.emit('structure-will-change')
- self.row_indexes = {}
- row = TableRow(column_values)
- retval = self.row_list.insertBefore(iter, row)
- return retval
-
- def iter_for_row(self, tableview, row):
- return self.row_list.nth_iter(row)
-
-
-class TreeNode(NSObject, TableRow):
- """A row in a TreeTableModel"""
-
- # Implementation note: these need to be NSObjects because we return them
- # to the NSOutlineView.
-
- def initWithValues_parent_(self, column_values, parent):
- self.children = RowList()
- self.update_values(column_values)
- self.parent = parent
- return self
-
- @staticmethod
- def create_(values, parent):
- return TreeNode.alloc().initWithValues_parent_(values, parent)
-
- def iterchildren(self):
- return iter(self.children)
-
-class TreeTableModel(TableModelBase):
- """https://develop.participatoryculture.org/index.php/WidgetAPITableView"""
- def __init__(self, *column_values):
- TableModelBase.__init__(self, *column_values)
- self.iter_for_item = {}
-
- def containing_list(self, iter):
- return self.row_list_for_iter(iter.value().parent)
-
- def row_list_for_iter(self, iter):
- """Return the rows of all direct children of iter."""
- if iter is None:
- return self.row_list
- else:
- return iter.value().children
-
- def remember_iter(self, iter):
- self.iter_for_item[iter.value()] = iter
- return iter
-
- def append(self, *column_values):
- self.emit('structure-will-change')
- retval = self.row_list.append(TreeNode.create_(column_values, None))
- return self.remember_iter(retval)
-
- def forget_iter_for_item(self, item):
- del self.iter_for_item[item]
- for child in item.children:
- self.forget_iter_for_item(child)
-
- def remove(self, iter):
- item = iter.value()
- rv = TableModelBase.remove(self, iter)
- self.forget_iter_for_item(item)
- return rv
-
- def insert_before(self, iter, *column_values):
- self.emit('structure-will-change')
- row = TreeNode.create_(column_values, self.parent_iter(iter))
- retval = self.containing_list(iter).insertBefore(iter, row)
- return self.remember_iter(retval)
-
- def append_child(self, iter, *column_values):
- self.emit('structure-will-change')
- row_list = self.row_list_for_iter(iter)
- retval = row_list.append(TreeNode.create_(column_values, iter))
- return self.remember_iter(retval)
-
- def child_iter(self, iter):
- row_list = iter.value().children
- if len(row_list) == 0:
- return None
- else:
- return row_list.firstIter()
-
- def nth_child_iter(self, iter, index):
- row_list = self.row_list_for_iter(iter)
- return row_list.nth_iter(index)
-
- def has_child(self, iter):
- return len(iter.value().children) > 0
-
- def children_count(self, iter):
- if iter is not None:
- return len(iter.value().children)
- else:
- return len(self.row_list)
-
- def children_iters(self, iter):
- return self.iters_in_rowlist(self.row_list_for_iter(iter))
-
- def parent_iter(self, iter):
- return iter.value().parent
-
- def iter_for_row(self, tableview, row):
- item = tableview.itemAtRow_(row)
- if item in self.iter_for_item:
- return self.iter_for_item[item]
- elif item == -1:
- raise WidgetActionError("no item at row %s" % row)
- else:
- raise WidgetActionError("no iter for item %s at row %s" %
- (repr(item), row))
-
- def row_of_iter(self, tableview, iter):
- item = iter.value()
- row = tableview.rowForItem_(item)
- if row == -1:
- raise LookupError("%s is not in this table" % repr(item))
- return row
-
- def get_path(self, iter_):
- """Not implemented (yet?) for Cocoa. Currently the only place this is
- needed is tablistmanager, where the situation that uses paths results
- from GTK peculiarities.
- """
- return NotImplemented
-
-class DataSourceBase(NSObject):
- def initWithModel_(self, model):
- self.model = model
- self.drag_source = None
- self.drag_dest = None
- return self
-
- def setDragSource_(self, drag_source):
- self.drag_source = drag_source
-
- def setDragDest_(self, drag_dest):
- self.drag_dest = drag_dest
-
- def view_writeColumnData_ToPasteboard_(self, view, data, pasteboard):
- if not self.drag_source:
- return NO
- wrapper = wrappermap.wrapper(view)
- drag_data = self.drag_source.begin_drag(wrapper, data)
- if not drag_data:
- return NO
- pasteboard.declareTypes_owner_((MIRO_DND_ITEM_LOCAL,), self)
- for typ, value in drag_data.items():
- stringval = repr((repr(value), typ))
- pasteboard.setString_forType_(stringval, MIRO_DND_ITEM_LOCAL)
- return YES
-
- def calcType_(self, drag_info):
- source_actions = drag_info.draggingSourceOperationMask()
- if not (self.drag_dest and
- (self.drag_dest.allowed_actions() | source_actions)):
- return None
- types = self.drag_dest.allowed_types()
- available = drag_info.draggingPasteboard().availableTypeFromArray_(
- (MIRO_DND_ITEM_LOCAL,))
- if available:
- # XXX using eval() sucks.
- data = eval(drag_info.draggingPasteboard().stringForType_(
- MIRO_DND_ITEM_LOCAL))
- if data:
- _, typ = data
- return typ
- return None
-
- def validateDrop_dragInfo_parentIter_position_(self, view, drag_info,
- parent, position):
- typ = self.calcType_(drag_info)
- if typ:
- wrapper = wrappermap.wrapper(view)
- drop_action = self.drag_dest.validate_drop(
- wrapper, self.model, typ,
- drag_info.draggingSourceOperationMask(), parent,
- position)
- if not drop_action:
- return NSDragOperationNone
- if isinstance(drop_action, (tuple, list)):
- drop_action, iter = drop_action
- view.setDropRow_dropOperation_(
- self.model.row_of_iter(view, iter),
- NSTableViewDropOn)
- return drop_action
- else:
- return NSDragOperationNone
-
- def acceptDrop_dragInfo_parentIter_position_(self, view, drag_info,
- parent, position):
- typ = self.calcType_(drag_info)
- if typ:
- # XXX using eval sucks.
- data = eval(drag_info.draggingPasteboard().stringForType_(MIRO_DND_ITEM_LOCAL))
- ids, _ = data
- ids = eval(ids)
- wrapper = wrappermap.wrapper(view)
- self.drag_dest.accept_drop(wrapper, self.model, typ,
- drag_info.draggingSourceOperationMask(), parent,
- position, ids)
- return YES
- else:
- return NO
-
-class MiroTableViewDataSource(DataSourceBase, protocols.NSTableDataSource):
- def numberOfRowsInTableView_(self, table_view):
- return len(self.model)
-
- def tableView_objectValueForTableColumn_row_(self, table_view, column, row):
- node = self.model.nth_iter(row).value()
- self.model.remember_row_at_index(node, row)
- return self.model.get_column_data(node.values, column)
-
- def tableView_writeRowsWithIndexes_toPasteboard_(self, tableview, rowIndexes,
- pasteboard):
- indexes = list_from_nsindexset(rowIndexes)
- data = [self.model[self.model.nth_iter(i)] for i in indexes]
- return self.view_writeColumnData_ToPasteboard_(tableview, data,
- pasteboard)
-
- def translateRow_operation_(self, row, operation):
- if operation == NSTableViewDropOn:
- return self.model.nth_iter(row), -1
- else:
- return None, row
-
- def tableView_validateDrop_proposedRow_proposedDropOperation_(self,
- tableview, drag_info, row, operation):
- parent, position = self.translateRow_operation_(row, operation)
- drop_action = self.validateDrop_dragInfo_parentIter_position_(tableview,
- drag_info, parent, position)
- if isinstance(drop_action, (list, tuple)):
- # XXX nothing uses this yet
- drop_action, iter = drop_action
- tableview.setDropRow_dropOperation_(
- self.model.row_of_iter(tableview, iter),
- NSTableViewDropOn)
- return drop_action
-
- def tableView_acceptDrop_row_dropOperation_(self,
- tableview, drag_info, row, operation):
- parent, position = self.translateRow_operation_(row, operation)
- return self.acceptDrop_dragInfo_parentIter_position_(tableview,
- drag_info, parent, position)
-
-
-class MiroOutlineViewDataSource(DataSourceBase, protocols.NSOutlineViewDataSource):
- def outlineView_child_ofItem_(self, view, child, item):
- if item is nil:
- row_list = self.model.row_list
- else:
- row_list = item.children
- return row_list.nth_iter(child).value()
-
- def outlineView_isItemExpandable_(self, view, item):
- if item is not nil and hasattr(item, 'children'):
- return len(item.children) > 0
- else:
- return len(self.model) > 0
-
- def outlineView_numberOfChildrenOfItem_(self, view, item):
- if item is not nil and hasattr(item, 'children'):
- return len(item.children)
- else:
- return len(self.model)
-
- def outlineView_objectValueForTableColumn_byItem_(self, view, column,
- item):
- return self.model.get_column_data(item.values, column)
-
- def outlineView_writeItems_toPasteboard_(self, outline_view, items,
- pasteboard):
- data = [i.values for i in items]
- return self.view_writeColumnData_ToPasteboard_(outline_view, data,
- pasteboard)
-
- def outlineView_validateDrop_proposedItem_proposedChildIndex_(self,
- outlineview, drag_info, item, child_index):
- if item is None:
- iter = None
- else:
- iter = self.model.iter_for_item[item]
- drop_action = self.validateDrop_dragInfo_parentIter_position_(
- outlineview, drag_info, iter, child_index)
- if isinstance(drop_action, (tuple, list)):
- drop_action, iter = drop_action
- outlineview.setDropItem_dropChildIndex_(
- iter.value(), NSOutlineViewDropOnItemIndex)
- return drop_action
-
- def outlineView_acceptDrop_item_childIndex_(self, outlineview, drag_info,
- item, child_index):
- if item is None:
- iter = None
- else:
- iter = self.model.iter_for_item[item]
- return self.acceptDrop_dragInfo_parentIter_position_(outlineview,
- drag_info, iter, child_index)