mirror of
https://github.com/wassname/sloth.git
synced 2026-06-29 21:43:41 +08:00
Fix model issues
This commit is contained in:
+75
-66
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
The annotationmodel module contains the classes for the AnnotationModel.
|
||||
"""
|
||||
from PyQt4.QtGui import QTreeView, QItemSelection, QItemSelectionModel, QSortFilterProxyModel, QAbstractItemView
|
||||
from PyQt4.QtCore import QModelIndex, QPersistentModelIndex, QAbstractItemModel, QVariant, Qt, pyqtSignal
|
||||
from PyQt4.QtGui import QTreeView, QItemSelection, QItemSelectionModel, QSortFilterProxyModel
|
||||
from PyQt4.QtCore import QModelIndex, QAbstractItemModel, QVariant, Qt, pyqtSignal
|
||||
import os.path
|
||||
import copy
|
||||
from collections import MutableMapping
|
||||
@@ -13,16 +13,14 @@ class ModelItem(MutableMapping):
|
||||
def __init__(self):
|
||||
if not hasattr(self, "_children"):
|
||||
self._children = []
|
||||
if not hasattr(self, "_pindex"):
|
||||
self._pindex = []
|
||||
if not hasattr(self, "_model"):
|
||||
self._model = None
|
||||
if not hasattr(self, "_parent"):
|
||||
self._parent = None
|
||||
if not hasattr(self, "_columns"):
|
||||
self._columns = 1
|
||||
if not hasattr(self, "_dict"):
|
||||
self._dict = {}
|
||||
if not hasattr(self, "_row"):
|
||||
self._row = -1
|
||||
|
||||
# Methods for MutableMapping
|
||||
def __len__(self):
|
||||
@@ -70,10 +68,12 @@ class ModelItem(MutableMapping):
|
||||
return self._parent
|
||||
|
||||
def data(self, role=Qt.DisplayRole, column=0):
|
||||
if role == Qt.DisplayRole:
|
||||
return ""
|
||||
if role == ItemRole:
|
||||
return QVariant(self)
|
||||
else:
|
||||
return QVariant()
|
||||
return None
|
||||
|
||||
def flags(self, column):
|
||||
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
||||
@@ -81,72 +81,54 @@ class ModelItem(MutableMapping):
|
||||
def setData(self, value, role=Qt.DisplayRole, column=0):
|
||||
return False
|
||||
|
||||
def getPosOfChild(self, item):
|
||||
return self._children.index(item)
|
||||
|
||||
def getChildAt(self, pos):
|
||||
return self._children[pos]
|
||||
|
||||
def getPreviousSibling(self):
|
||||
p = self.parent()
|
||||
if p is not None:
|
||||
row = p.getPosOfChild(self)
|
||||
if row > 0:
|
||||
return p.getChildAt(row-1)
|
||||
if self._row > 0:
|
||||
return p.getChildAt(self._row-1)
|
||||
return None
|
||||
|
||||
def getNextSibling(self):
|
||||
p = self.parent()
|
||||
if p is not None:
|
||||
row = p.getPosOfChild(self)
|
||||
if row < len(p.children()) - 1:
|
||||
return p.getChildAt(row+1)
|
||||
if self._row < len(p.children()) - 1:
|
||||
return p.getChildAt(self._row+1)
|
||||
return None
|
||||
|
||||
def _attachToModel(self, model, indices):
|
||||
def _attachToModel(self, model):
|
||||
assert self.model() is None
|
||||
assert not self._pindex
|
||||
assert self.parent() is not None
|
||||
assert self.parent().model() is not None
|
||||
|
||||
self._model = model
|
||||
|
||||
for i in range(self.model().columnCount()):
|
||||
if i < self._columns:
|
||||
ind = indices[i]
|
||||
else:
|
||||
ind = QModelIndex()
|
||||
self._pindex.append(QPersistentModelIndex(ind))
|
||||
|
||||
# Recurse
|
||||
for i in range(len(self.children())):
|
||||
item = self.children()[i]
|
||||
cindices = [self.model().createIndex(i, j, item) for j in range(item._columns)]
|
||||
item._attachToModel(model, cindices)
|
||||
|
||||
def pindex(self, column=0):
|
||||
assert self._pindex
|
||||
return self._pindex[column]
|
||||
for item in self.children():
|
||||
item._attachToModel(model)
|
||||
|
||||
def index(self, column=0):
|
||||
assert self._pindex
|
||||
return QModelIndex(self._pindex[column])
|
||||
if self.parent() is None:
|
||||
return QModelIndex()
|
||||
if column >= self.model().columnCount():
|
||||
return QModelIndex()
|
||||
return self.model().createIndex(self._row, column, self)
|
||||
|
||||
def appendChild(self, item):
|
||||
assert isinstance(item, ModelItem)
|
||||
assert item.model() is None
|
||||
assert item.parent() is None
|
||||
|
||||
next_row = len(self._children)
|
||||
if self.model() is not None:
|
||||
next_row = len(self._children)
|
||||
self.model().beginInsertRows(self.index(), next_row, next_row)
|
||||
|
||||
item._parent = self
|
||||
item._row = next_row
|
||||
self.children().append(item)
|
||||
|
||||
if self.model() is not None:
|
||||
indices = [self.model().createIndex(next_row, i, item) for i in range(item._columns)]
|
||||
item._attachToModel(self.model(), indices)
|
||||
item._attachToModel(self.model())
|
||||
self.model().endInsertRows()
|
||||
|
||||
def appendChildren(self, items):
|
||||
@@ -155,30 +137,20 @@ class ModelItem(MutableMapping):
|
||||
assert item.model() is None
|
||||
assert item.parent() is None
|
||||
|
||||
next_row = len(self._children)
|
||||
if self.model() is not None:
|
||||
next_row = len(self._children)
|
||||
self.model().beginInsertRows(self.index(), next_row, next_row + len(items) - 1)
|
||||
|
||||
for item in items:
|
||||
for i, item in enumerate(items):
|
||||
item._parent = self
|
||||
item._row = next_row + i
|
||||
self.children().append(item)
|
||||
|
||||
if self.model() is not None:
|
||||
for i in range(len(items)):
|
||||
item = items[i]
|
||||
indices = [self.model().createIndex(next_row+i, j, item) for j in range(item._columns)]
|
||||
item._attachToModel(self.model(), indices)
|
||||
|
||||
for item in items:
|
||||
item._attachToModel(self.model())
|
||||
self.model().endInsertRows()
|
||||
|
||||
def deleteAllChildren(self):
|
||||
for child in self._children:
|
||||
child.deleteAllChildren()
|
||||
|
||||
self._model.beginRemoveRows(self.index(), 0, len(self._children) - 1)
|
||||
self._children = []
|
||||
self._model.endRemoveRows()
|
||||
|
||||
def delete(self):
|
||||
if self.parent() is None:
|
||||
raise RuntimeError("Trying to delete orphan")
|
||||
@@ -186,21 +158,38 @@ class ModelItem(MutableMapping):
|
||||
self.parent().deleteChild(self)
|
||||
|
||||
def deleteChild(self, arg):
|
||||
# Grandchildren are considered deleted automatically
|
||||
if isinstance(arg, ModelItem):
|
||||
self.deleteChild(self._children.index(arg))
|
||||
return self.deleteChild(self._children.index(arg))
|
||||
else:
|
||||
if arg < 0 or arg >= len(self._children):
|
||||
raise IndexError("child index out of range")
|
||||
self._children[arg].deleteAllChildren()
|
||||
self._model.beginRemoveRows(self.index(), arg, arg)
|
||||
|
||||
if self.model() is not None:
|
||||
self._model.beginRemoveRows(self.index(), arg, arg)
|
||||
|
||||
del self._children[arg]
|
||||
|
||||
# Update cached row numbers
|
||||
for i, c in enumerate(self._children):
|
||||
c._row = i
|
||||
|
||||
if self.model() is not None:
|
||||
self._model.endRemoveRows()
|
||||
|
||||
def deleteAllChildren(self):
|
||||
if self.model() is not None:
|
||||
self._model.beginRemoveRows(self.index(), 0, len(self._children) - 1)
|
||||
|
||||
self._children = []
|
||||
|
||||
if self.model() is not None:
|
||||
self._model.endRemoveRows()
|
||||
|
||||
class RootModelItem(ModelItem):
|
||||
def __init__(self, model):
|
||||
ModelItem.__init__(self)
|
||||
self._model = model
|
||||
self._pindex = [QPersistentModelIndex() for i in range(model.columnCount())]
|
||||
|
||||
def appendChild(self, item):
|
||||
if isinstance(item, FileModelItem):
|
||||
@@ -357,8 +346,11 @@ class AnnotationModelItem(KeyValueModelItem):
|
||||
|
||||
# Delegated from QAbstractItemModel
|
||||
def data(self, role=Qt.DisplayRole, column=0):
|
||||
if role == Qt.DisplayRole and column == 0:
|
||||
return self['type']
|
||||
if role == Qt.DisplayRole:
|
||||
if column == 0:
|
||||
return self['type']
|
||||
else:
|
||||
return ""
|
||||
elif role == TypeRole:
|
||||
return self['type']
|
||||
elif role == DataRole:
|
||||
@@ -369,7 +361,6 @@ class KeyValueRowModelItem(ModelItem):
|
||||
def __init__(self, key):
|
||||
ModelItem.__init__(self)
|
||||
self._key = key
|
||||
self._columns = 2
|
||||
|
||||
def key(self):
|
||||
return self._key
|
||||
@@ -404,6 +395,9 @@ class AnnotationModel(QAbstractItemModel):
|
||||
return 2
|
||||
|
||||
def rowCount(self, index=QModelIndex()):
|
||||
# Only items with column==1 can have children
|
||||
if index.column() > 0:
|
||||
return 0
|
||||
item = self.itemFromIndex(index)
|
||||
return len(item.children())
|
||||
|
||||
@@ -417,10 +411,25 @@ class AnnotationModel(QAbstractItemModel):
|
||||
return parent.index()
|
||||
|
||||
def index(self, row, column, parent_idx=QModelIndex()):
|
||||
parent = self.itemFromIndex(parent_idx)
|
||||
if row >= len(parent.children()):
|
||||
# Handle invalid rows/columns
|
||||
if row < 0 or column < 0:
|
||||
return QModelIndex()
|
||||
return parent.children()[row].index(column)
|
||||
|
||||
# Only items with column == 0 can have children
|
||||
if parent_idx.isValid() and parent_idx.column() > 0:
|
||||
return QModelIndex()
|
||||
|
||||
# Handle root item
|
||||
if parent_idx == QModelIndex():
|
||||
parent = self._root
|
||||
# Handle normal items
|
||||
else:
|
||||
parent = self.itemFromIndex(parent_idx)
|
||||
if row < 0 or row >= len(parent.children()):
|
||||
return QModelIndex()
|
||||
if column < 0 or column >= self.columnCount():
|
||||
return QModelIndex()
|
||||
return self.createIndex(row, column, parent.children()[row])
|
||||
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
if not index.isValid():
|
||||
@@ -512,7 +521,7 @@ class AnnotationTreeView(QTreeView):
|
||||
|
||||
self.setUniformRowHeights(True)
|
||||
self.setSelectionMode(QTreeView.ExtendedSelection)
|
||||
self.setSelectionBehavior(QTreeView.SelectItems)
|
||||
self.setSelectionBehavior(QTreeView.SelectRows)
|
||||
self.setAllColumnsShowFocus(True)
|
||||
self.setAlternatingRowColors(True)
|
||||
#self.setEditTriggers(QAbstractItemView.SelectedClicked)
|
||||
|
||||
Reference in New Issue
Block a user