Model-based blocktype list is more fully functional, uses QSortFilterProxyModel for searches
This commit is contained in:
parent
99c6a183f1
commit
267f77c829
@ -50,94 +50,6 @@ class BlockThumbView(QtGui.QWidget):
|
|||||||
self.worldView = IsoWorldView(dim, self.editorSession.textureAtlas, sharedGLWidget=self.editorSession.editorTab.miniMap)
|
self.worldView = IsoWorldView(dim, self.editorSession.textureAtlas, sharedGLWidget=self.editorSession.editorTab.miniMap)
|
||||||
|
|
||||||
self.setLayout(Row(self.worldView))
|
self.setLayout(Row(self.worldView))
|
||||||
#
|
|
||||||
#class BlockTypeItemDelegate(QtGui.QStyledItemDelegate):
|
|
||||||
# def __init__(self, model, listView, *args, **kwargs):
|
|
||||||
# """
|
|
||||||
#
|
|
||||||
# :type listView: QListView
|
|
||||||
# """
|
|
||||||
# super(BlockTypeItemDelegate, self).__init__(*args, **kwargs)
|
|
||||||
# self.listView = listView
|
|
||||||
# self.model = model
|
|
||||||
# self.textureAtlas = model.editor.textureAtlas
|
|
||||||
#
|
|
||||||
# def xpaint(self, painter, option, index):
|
|
||||||
# """
|
|
||||||
#
|
|
||||||
# :type painter: QtGui.QPainter
|
|
||||||
# :type option: QStyleOptionViewItem
|
|
||||||
# :type index: QModelIndex
|
|
||||||
# """
|
|
||||||
# #super(BlockTypeItemDelegate, self).paint(painter, option, index)
|
|
||||||
# QtGui.QStyledItemDelegate.paint(self, painter, option, index)
|
|
||||||
# #self.listWidget.style().drawPrimitive(QtGui.QStyle.PE_PanelItemViewItem, option, painter, None)
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# if False and option.state & QtGui.QStyle.State_Enabled:
|
|
||||||
# widget = BlockTypesItemWidget(self.listView.model().data(index, role=Qt.UserRole), self.textureAtlas)
|
|
||||||
# widget.setGeometry(option.rect)
|
|
||||||
# widget.setMinimumSize(self.model.baseSize)
|
|
||||||
# widget.setBackgroundRole(QtGui.QPalette.NoRole)
|
|
||||||
# widget.setAutoFillBackground(False)
|
|
||||||
# #painter.drawRoundedRect(option.rect, 0, 0)
|
|
||||||
# img = QPixmap(option.rect.size())
|
|
||||||
# img.fill(QtGui.QColor(0, 0, 0, 0))
|
|
||||||
# #log.info("Paint: Active")
|
|
||||||
#
|
|
||||||
# widget.render(img, renderFlags=widget.DrawChildren)
|
|
||||||
#
|
|
||||||
# #if option.state & QtGui.QStyle.State_Selected:
|
|
||||||
# # brush = option.palette.highlight()
|
|
||||||
# # painter.fillRect(option.rect, brush)
|
|
||||||
#
|
|
||||||
# painter.drawPixmap(option.rect.topLeft(), img)
|
|
||||||
# #style = self.listWidget.style()
|
|
||||||
# #style.drawPrimitive(style.PE_PanelItemViewItem, option, painter, widget)
|
|
||||||
# #style.drawControl(style.CE_ItemViewItem, option, painter)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def sizeHint(self, option, index):
|
|
||||||
# return QtCore.QSize(self.listView.width(), self.model.baseSize.height())
|
|
||||||
#
|
|
||||||
#_widgetWidth = 400
|
|
||||||
#
|
|
||||||
#class BlockTypeSetModel(QtCore.QAbstractListModel):
|
|
||||||
#
|
|
||||||
# def __init__(self, editor, *args, **kwargs):
|
|
||||||
# super(BlockTypeSetModel, self).__init__(*args, **kwargs)
|
|
||||||
# self.allBlocks = list(editor.world.blocktypes)
|
|
||||||
# self.editor = editor
|
|
||||||
# widget = BlockTypesItemWidget(editor.world.blocktypes.Stone, editor.textureAtlas)
|
|
||||||
# self.baseSize = QtCore.QSize(widget.sizeHint().width(), widget.sizeHint().height())
|
|
||||||
#
|
|
||||||
# def rowCount(self, parent=QtCore.QModelIndex()):
|
|
||||||
# return len(self.allBlocks)
|
|
||||||
#
|
|
||||||
# def data(self, index, role=Qt.DisplayRole):
|
|
||||||
# if role == Qt.DisplayRole:
|
|
||||||
# return self.allBlocks[index.row()].displayName
|
|
||||||
# #return self.makeIcon(index)
|
|
||||||
# elif role == Qt.UserRole:
|
|
||||||
# return self.allBlocks[index.row()]
|
|
||||||
# else:
|
|
||||||
# return None
|
|
||||||
#
|
|
||||||
# def makeIcon(self, index):
|
|
||||||
# widget = BlockTypesItemWidget(self.data(index, role=Qt.UserRole), self.editor.textureAtlas)
|
|
||||||
# widget.setMinimumSize(self.baseSize)
|
|
||||||
# widget.setBackgroundRole(QtGui.QPalette.NoRole)
|
|
||||||
# widget.setAutoFillBackground(False)
|
|
||||||
# #painter.drawRoundedRect(option.rect, 0, 0)
|
|
||||||
# img = QPixmap(self.baseSize)
|
|
||||||
# img.fill(QtGui.QColor(0, 0, 0, 0))
|
|
||||||
# #log.info("Paint: Active")
|
|
||||||
#
|
|
||||||
# widget.render(img, renderFlags=widget.DrawChildren)
|
|
||||||
# return img
|
|
||||||
# #icon = QtGui.QIcon(img)
|
|
||||||
# #return icon
|
|
||||||
|
|
||||||
class BlockTypeIcon(QtGui.QLabel):
|
class BlockTypeIcon(QtGui.QLabel):
|
||||||
def __init__(self, block, textureAtlas, *args, **kwargs):
|
def __init__(self, block, textureAtlas, *args, **kwargs):
|
||||||
@ -249,22 +161,59 @@ class BlockTypesItemWidget(QtGui.QWidget):
|
|||||||
|
|
||||||
self.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
self.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
||||||
|
|
||||||
|
|
||||||
|
class BlockTypeListFilterModel(QtGui.QSortFilterProxyModel):
|
||||||
|
def __init__(self, sourceModel):
|
||||||
|
super(BlockTypeListFilterModel, self).__init__()
|
||||||
|
self.setSourceModel(sourceModel)
|
||||||
|
self.setFilterKeyColumn(0)
|
||||||
|
self.setFilterCaseSensitivity(Qt.CaseInsensitive)
|
||||||
|
|
||||||
|
def setSearchString(self, val):
|
||||||
|
self.setFilterRegExp(val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def textureAtlas(self):
|
||||||
|
return self.sourceModel().textureAtlas
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blocktypes(self):
|
||||||
|
return self.sourceModel().blocktypes
|
||||||
|
|
||||||
class BlockTypeListModel(QtCore.QAbstractListModel):
|
class BlockTypeListModel(QtCore.QAbstractListModel):
|
||||||
def __init__(self, blocktypes, textureAtlas):
|
def __init__(self, blocktypes, textureAtlas):
|
||||||
super(BlockTypeListModel, self).__init__()
|
super(BlockTypeListModel, self).__init__()
|
||||||
self.blocktypes = blocktypes
|
self.blocktypes = blocktypes
|
||||||
self.blocktypesList = list(blocktypes)
|
self.blocktypesList = list(blocktypes)
|
||||||
self.textureAtlas = textureAtlas
|
self.textureAtlas = textureAtlas
|
||||||
|
self.customBlocks = []
|
||||||
|
|
||||||
def rowCount(self, index):
|
def rowCount(self, index):
|
||||||
return len(self.blocktypes)
|
return len(self.blocktypes) + len(self.customBlocks)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
block = self.blocktypesList[index.row()]
|
row = index.row()
|
||||||
|
if row >= len(self.blocktypes):
|
||||||
|
block = self.customBlocks[row - len(self.blocktypes)]
|
||||||
|
else:
|
||||||
|
block = self.blocktypesList[index.row()]
|
||||||
|
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return block.displayName
|
return block.displayName
|
||||||
if role == Qt.UserRole:
|
if role == Qt.UserRole:
|
||||||
return block
|
return block.internalName, block.blockState
|
||||||
|
|
||||||
|
def addCustomBlock(self, block):
|
||||||
|
index = len(self.blocktypes) + len(self.customBlocks)
|
||||||
|
self.beginInsertRows(QtCore.QModelIndex(), index, index)
|
||||||
|
self.customBlocks.append(block)
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
def removeCustomBlocks(self):
|
||||||
|
self.beginRemoveRows(QtCore.QModelIndex(), len(self.blocktypes), len(self.blocktypes) + len(self.customBlocks) - 1)
|
||||||
|
self.customBlocks = []
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
|
||||||
class BlockTypeListItemDelegate(QtGui.QAbstractItemDelegate):
|
class BlockTypeListItemDelegate(QtGui.QAbstractItemDelegate):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -284,8 +233,10 @@ class BlockTypeListItemDelegate(QtGui.QAbstractItemDelegate):
|
|||||||
:rtype:
|
:rtype:
|
||||||
"""
|
"""
|
||||||
model = index.model()
|
model = index.model()
|
||||||
block = model.data(index, Qt.UserRole) # index.data doesn't work because the BlockType doesn't survive the trip through Qt(?)
|
internalName, blockState = index.data(Qt.UserRole)
|
||||||
log.info("Painting block list widget item in %s with %s", str(option.rect), block.displayName)
|
block = model.blocktypes[internalName, blockState]
|
||||||
|
if option.state & QtGui.QStyle.State_Selected:
|
||||||
|
painter.fillRect(option.rect, option.palette.highlight())
|
||||||
self.itemWidget.setGeometry(option.rect)
|
self.itemWidget.setGeometry(option.rect)
|
||||||
self.itemWidget.setBlocks([block])
|
self.itemWidget.setBlocks([block])
|
||||||
self.itemWidget.setTextureAtlas(model.textureAtlas)
|
self.itemWidget.setTextureAtlas(model.textureAtlas)
|
||||||
@ -307,111 +258,26 @@ class BlockTypeListWidget(QtGui.QListView):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BlockTypeListWidget, self).__init__(*args, **kwargs)
|
super(BlockTypeListWidget, self).__init__(*args, **kwargs)
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
||||||
self.specifiedItems = []
|
|
||||||
self.multipleSelect = False
|
self.multipleSelect = False
|
||||||
self.setItemDelegate(BlockTypeListItemDelegate())
|
self.setItemDelegate(BlockTypeListItemDelegate())
|
||||||
|
|
||||||
_textureAtlas = None
|
|
||||||
|
|
||||||
itemSelectionChanged = QtCore.Signal()
|
itemSelectionChanged = QtCore.Signal()
|
||||||
|
|
||||||
def selectionChanged(self, selected, deselected):
|
def selectionChanged(self, selected, deselected):
|
||||||
self.itemSelectionChanged.emit()
|
self.itemSelectionChanged.emit()
|
||||||
|
|
||||||
@property
|
def selectedBlocks(self):
|
||||||
def textureAtlas(self):
|
model = self.model()
|
||||||
return self._textureAtlas
|
if model is None:
|
||||||
|
return []
|
||||||
|
|
||||||
@textureAtlas.setter
|
selectionModel = self.selectionModel()
|
||||||
def textureAtlas(self, value):
|
indexes = selectionModel.selectedIndexes()
|
||||||
oldVal = self._textureAtlas
|
blocks = [model.blocktypes[tuple(model.data(idx, Qt.UserRole))] for idx in indexes]
|
||||||
self._textureAtlas = value
|
return blocks
|
||||||
if oldVal != value:
|
|
||||||
self.updateList()
|
|
||||||
|
|
||||||
_blocktypes = None
|
def clearSelection(self):
|
||||||
|
self.selectionModel().clear()
|
||||||
@property
|
|
||||||
def blocktypes(self):
|
|
||||||
return self._blocktypes
|
|
||||||
|
|
||||||
@blocktypes.setter
|
|
||||||
def blocktypes(self, value):
|
|
||||||
oldVal = self._blocktypes
|
|
||||||
self._blocktypes = value
|
|
||||||
if oldVal != value:
|
|
||||||
self.updateList()
|
|
||||||
|
|
||||||
_searchValue = None
|
|
||||||
|
|
||||||
def setSearchString(self, val):
|
|
||||||
self._searchValue = val
|
|
||||||
ID = None
|
|
||||||
meta = None
|
|
||||||
try:
|
|
||||||
if ":" in val:
|
|
||||||
ID, meta = val.split(":")
|
|
||||||
else:
|
|
||||||
ID = val
|
|
||||||
meta = 0
|
|
||||||
|
|
||||||
ID = int(ID)
|
|
||||||
meta = int(meta)
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
for item in [i for i in self.specifiedItems if not i.isSelected()]:
|
|
||||||
self.removeItemWidget(item)
|
|
||||||
self.takeItem(self.row(item))
|
|
||||||
self.specifiedItems.remove(item)
|
|
||||||
|
|
||||||
block = self.blocktypes[ID, meta]
|
|
||||||
if block not in self.blocktypes:
|
|
||||||
item, itemWidget = self.createItem(block)
|
|
||||||
|
|
||||||
self.addItem(item)
|
|
||||||
self.setItemWidget(item, itemWidget)
|
|
||||||
self.specifiedItems.append(item)
|
|
||||||
|
|
||||||
for item in self.findItems("", Qt.MatchContains):
|
|
||||||
matched = val.lower() in item.block.displayName.lower()
|
|
||||||
matched |= val in item.block.internalName + item.block.blockState
|
|
||||||
if ID is not None:
|
|
||||||
matched |= (item.block.ID == ID and item.block.meta == meta)
|
|
||||||
|
|
||||||
item.setHidden(not matched)
|
|
||||||
|
|
||||||
def createItem(self, block):
|
|
||||||
item = QtGui.QListWidgetItem()
|
|
||||||
itemWidget = BlockTypesItemWidget([block], self.textureAtlas)
|
|
||||||
item.setSizeHint(itemWidget.sizeHint())
|
|
||||||
item.block = block
|
|
||||||
item.widget = itemWidget
|
|
||||||
if self.multipleSelect:
|
|
||||||
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
|
|
||||||
return item, itemWidget
|
|
||||||
|
|
||||||
def updateList(self):
|
|
||||||
if self.textureAtlas is None:
|
|
||||||
return
|
|
||||||
if self.blocktypes is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
log.info("Updating blocktype list widget (multiple=%s) for %s", self.multipleSelect, self.blocktypes)
|
|
||||||
self.specifiedItems = []
|
|
||||||
self.setModel(BlockTypeListModel(self.blocktypes, self.textureAtlas))
|
|
||||||
|
|
||||||
# for block in self.blocktypes:
|
|
||||||
#
|
|
||||||
# item, itemWidget = self.createItem(block)
|
|
||||||
#
|
|
||||||
# self.addItem(item)
|
|
||||||
# self.setItemWidget(item, itemWidget)
|
|
||||||
#
|
|
||||||
# self.setMinimumWidth(self.sizeHintForColumn(0)+self.autoScrollMargin())
|
|
||||||
# if self._searchValue:
|
|
||||||
# self.setSearchString(self._searchValue)
|
|
||||||
|
|
||||||
|
|
||||||
class BlockTypePicker(QtGui.QDialog):
|
class BlockTypePicker(QtGui.QDialog):
|
||||||
@ -436,6 +302,9 @@ class BlockTypePicker(QtGui.QDialog):
|
|||||||
self.listWidget.multipleSelect = True
|
self.listWidget.multipleSelect = True
|
||||||
|
|
||||||
self.setSizeGripEnabled(True)
|
self.setSizeGripEnabled(True)
|
||||||
|
self.listModel = None
|
||||||
|
self.filterModel = None
|
||||||
|
|
||||||
|
|
||||||
def exec_(self):
|
def exec_(self):
|
||||||
self.searchField.setFocus()
|
self.searchField.setFocus()
|
||||||
@ -451,6 +320,7 @@ class BlockTypePicker(QtGui.QDialog):
|
|||||||
self.rendertypeLabel.setText("")
|
self.rendertypeLabel.setText("")
|
||||||
elif len(self.selectedBlocks) == 1:
|
elif len(self.selectedBlocks) == 1:
|
||||||
block = self.selectedBlocks[0]
|
block = self.selectedBlocks[0]
|
||||||
|
log.info("Block=%s", (block.ID, block.meta))
|
||||||
self.nameLabel.setText("%s" % block.displayName)
|
self.nameLabel.setText("%s" % block.displayName)
|
||||||
self.internalNameLabel.setText("(%d:%d) %s" % (block.ID, block.meta, block.internalName))
|
self.internalNameLabel.setText("(%d:%d) %s" % (block.ID, block.meta, block.internalName))
|
||||||
self.brightnessLabel.setText("Brightness: %d" % block.brightness)
|
self.brightnessLabel.setText("Brightness: %d" % block.brightness)
|
||||||
@ -481,16 +351,25 @@ class BlockTypePicker(QtGui.QDialog):
|
|||||||
"""
|
"""
|
||||||
self._editorSession = editorSession
|
self._editorSession = editorSession
|
||||||
if self.editorSession:
|
if self.editorSession:
|
||||||
self.listWidget.textureAtlas = self.editorSession.textureAtlas
|
|
||||||
self.listWidget.blocktypes = self.editorSession.worldEditor.blocktypes
|
log.info("Updating blocktype list widget (multiple=%s) for %s", self.listWidget.multipleSelect, editorSession.worldEditor.blocktypes)
|
||||||
if self.multipleSelect:
|
self.listWidget.specifiedItems = []
|
||||||
self.selectedBlockList.textureAtlas = self.editorSession.textureAtlas
|
self.listModel = BlockTypeListModel(editorSession.worldEditor.blocktypes, editorSession.textureAtlas)
|
||||||
|
self.filterModel = BlockTypeListFilterModel(self.listModel)
|
||||||
|
self.listWidget.setModel(self.filterModel)
|
||||||
|
|
||||||
|
# if self.multipleSelect:
|
||||||
|
# self.selectedBlockList.textureAtlas = self.editorSession.textureAtlas
|
||||||
|
|
||||||
self.searchField.clearEditText()
|
self.searchField.clearEditText()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def blocktypes(self):
|
||||||
|
return self.editorSession.worldEditor.blocktypes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def selectedBlocks(self):
|
def selectedBlocks(self):
|
||||||
return [i.block for i in self.listWidget.selectedItems()]
|
return self.listWidget.selectedBlocks()
|
||||||
|
|
||||||
@selectedBlocks.setter
|
@selectedBlocks.setter
|
||||||
def selectedBlocks(self, val):
|
def selectedBlocks(self, val):
|
||||||
@ -510,6 +389,31 @@ class BlockTypePicker(QtGui.QDialog):
|
|||||||
def setSearchString(self, val):
|
def setSearchString(self, val):
|
||||||
self.listWidget.setSearchString(val)
|
self.listWidget.setSearchString(val)
|
||||||
|
|
||||||
|
_searchString = None
|
||||||
|
|
||||||
|
def setSearchString(self, val):
|
||||||
|
self._searchString = val
|
||||||
|
try:
|
||||||
|
if ":" in val:
|
||||||
|
ID, meta = val.split(":")
|
||||||
|
else:
|
||||||
|
ID = val
|
||||||
|
meta = 0
|
||||||
|
|
||||||
|
ID = int(ID)
|
||||||
|
meta = int(meta)
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.listModel.removeCustomBlocks()
|
||||||
|
|
||||||
|
block = self.blocktypes[ID, meta]
|
||||||
|
if block not in self.blocktypes:
|
||||||
|
self.listModel.addCustomBlock(block)
|
||||||
|
|
||||||
|
self.filterModel.setSearchString(val)
|
||||||
|
|
||||||
|
|
||||||
_sharedPicker = None
|
_sharedPicker = None
|
||||||
_sharedMultiPicker = None
|
_sharedMultiPicker = None
|
||||||
|
Reference in New Issue
Block a user