manuskript/manuskript/ui/views/characterTreeView.py

241 lines
7.9 KiB
Python
Raw Normal View History

2015-06-29 09:46:51 +12:00
#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QSize, QModelIndex, Qt
from PyQt5.QtGui import QPixmap, QColor, QIcon, QBrush
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QColorDialog, QDialog
2016-02-07 00:34:22 +13:00
from manuskript.enums import Character
from manuskript.functions import iconColor, mainWindow
2017-11-15 02:48:28 +13:00
from manuskript.ui import style as S
from manuskript.ui import characterInfoDialog
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
class characterTreeView(QTreeWidget):
"""
A QTreeWidget that displays characters from a characterModel in respect of their importance.
"""
2015-06-29 09:46:51 +12:00
def __init__(self, parent=None):
QTreeWidget.__init__(self, parent)
self._model = None
self._catRow = [-1, -1, -1]
self._filter = ""
self._lastID = -1
self._updating = False
self.setRootIsDecorated(False)
self.setIndentation(10)
2015-06-29 20:22:18 +12:00
self.setHeaderHidden(True)
self.setIconSize(QSize(24, 24))
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
self.setColumnCount(1)
self._rootItem = QTreeWidgetItem()
self.insertTopLevelItem(0, self._rootItem)
2016-02-07 00:34:22 +13:00
self.importanceMap = {self.tr("Main"):2, self.tr("Secondary"):1, self.tr("Minor"):0}
def setCharactersModel(self, model):
2015-06-29 09:46:51 +12:00
self._model = model
self._model.dataChanged.connect(self.updateMaybe)
self._model.rowsInserted.connect(self.updateMaybe2)
self._model.rowsRemoved.connect(self.updateMaybe2)
self.updateItems()
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
def setFilter(self, text):
self._filter = text
self.updateItems()
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
def updateMaybe(self, topLeft, bottomRight):
if topLeft.parent() != QModelIndex():
return
2016-02-07 00:34:22 +13:00
2017-11-16 09:05:48 +13:00
if topLeft.column() <= Character.name <= bottomRight.column():
2015-06-29 09:46:51 +12:00
# Update name
self.updateNames()
2016-02-07 00:34:22 +13:00
2017-11-16 09:05:48 +13:00
elif topLeft.column() <= Character.importance <= bottomRight.column():
2015-06-29 09:46:51 +12:00
# Importance changed
self.updateItems()
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
def updateMaybe2(self, parent, first, last):
2016-02-07 00:34:22 +13:00
# Rows inserted or removed, we update only if they are topLevel rows.
2015-06-29 09:46:51 +12:00
if parent == QModelIndex():
self.updateItems()
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
def updateNames(self):
for i in range(self.topLevelItemCount()):
item = self.topLevelItem(i)
2016-02-07 00:34:22 +13:00
for child in range(item.childCount()):
sub = item.child(child)
2015-06-29 09:46:51 +12:00
ID = sub.data(0, Qt.UserRole)
2021-02-22 11:45:34 +13:00
if ID != None:
2015-06-29 20:22:18 +12:00
# Update name
c = self._model.getCharacterByID(ID)
name = c.name()
2015-06-29 09:46:51 +12:00
sub.setText(0, name)
2015-06-29 20:22:18 +12:00
# Update icon
px = QPixmap(32, 32)
color = c.color()
2015-06-29 20:22:18 +12:00
px.fill(color)
sub.setIcon(0, QIcon(px))
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
def updateItems(self):
if not self._model:
return
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
if self.currentItem():
self._lastID = self.currentItem().data(0, Qt.UserRole)
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
self._updating = True
self.clear()
characters = self._model.getCharactersByImportance()
2016-02-07 00:34:22 +13:00
for i, importanceLevel in enumerate(self.importanceMap):
# Create category item
cat = QTreeWidgetItem(self, [importanceLevel])
2017-11-15 02:48:28 +13:00
cat.setBackground(0, QBrush(QColor(S.highlightLight)))
cat.setForeground(0, QBrush(QColor(S.highlightedTextDark)))
2015-06-29 09:46:51 +12:00
cat.setTextAlignment(0, Qt.AlignCenter)
f = cat.font(0)
f.setBold(True)
cat.setFont(0, f)
self.addTopLevelItem(cat)
2016-02-07 00:34:22 +13:00
# cat.setChildIndicatorPolicy(cat.DontShowIndicator)
for c in characters[i]:
name = c.name()
# Check if name passes filter
2016-02-07 00:34:22 +13:00
if not self._filter.lower() in name.lower():
2015-06-29 09:46:51 +12:00
continue
2015-06-29 09:46:51 +12:00
item = QTreeWidgetItem(cat, [name])
item.setData(0, Qt.UserRole, c.ID())
2015-06-29 09:46:51 +12:00
px = QPixmap(32, 32)
color = QColor(c.color())
2015-06-29 09:46:51 +12:00
px.fill(color)
item.setIcon(0, QIcon(px))
2016-02-07 00:34:22 +13:00
if c.ID() == self._lastID:
2015-06-29 09:46:51 +12:00
self.setCurrentItem(item)
2016-02-07 00:34:22 +13:00
2015-06-29 09:46:51 +12:00
self.expandAll()
self._updating = False
2016-02-07 00:34:22 +13:00
def addCharacter(self):
curr_item = self.currentItem()
curr_importance = 0
# check if an item is selected
2021-02-22 11:45:34 +13:00
if curr_item != None:
if curr_item.parent() == None:
# this is a top-level category, so find its importance
# get the current text, then look up the importance level
text = curr_item.text(0)
curr_importance = self.importanceMap[text]
else:
# get the importance from the currently-highlighted character
curr_character = self.currentCharacter()
curr_importance = curr_character.importance()
self._model.addCharacter(importance=curr_importance)
def removeCharacter(self):
"""
Removes selected character.
"""
ID = self.currentCharacterID()
if ID is None:
return None
self._model.removeCharacter(ID)
return ID
def choseCharacterColor(self):
ID = self.currentCharacterID()
c = self._model.getCharacterByID(ID)
if c:
color = iconColor(c.icon)
else:
color = Qt.white
self.colorDialog = QColorDialog(color, mainWindow())
color = self.colorDialog.getColor(color)
if color.isValid():
c.setColor(color)
mainWindow().updateCharacterColor(ID)
def changeCharacterPOVState(self, state):
ID = self.currentCharacterID()
c = self._model.getCharacterByID(ID)
c.setPOVEnabled(state == Qt.Checked)
mainWindow().updateCharacterPOVState(ID)
def addCharacterInfo(self):
#Setting up dialog
charInfoDialog = QDialog()
charInfoUi = characterInfoDialog.Ui_characterInfoDialog()
charInfoUi.setupUi(charInfoDialog)
if charInfoDialog.exec_() == QDialog.Accepted:
# User clicked OK, get the input values
description = charInfoUi.descriptionLineEdit.text()
value = charInfoUi.valueLineEdit.text()
# Add the character info with the input values
IDs = self.currentCharacterIDs()
for ID in IDs:
self._model.addCharacterInfo(ID, description, value)
def removeCharacterInfo(self):
self._model.removeCharacterInfo(self.currentCharacterID())
def currentCharacterID(self):
2015-06-29 09:46:51 +12:00
ID = None
if self.currentItem():
ID = self.currentItem().data(0, Qt.UserRole)
2016-02-07 00:34:22 +13:00
return ID
def currentCharacterIDs(self): #Exactly like currentCharacterID(), except for multiselection
IDs = []
for item in self.selectedItems():
ID = item.data(0, Qt.UserRole)
if ID is not None:
IDs.append(ID)
return IDs
def currentCharacter(self):
"""
Returns the selected character
@return: Character
"""
ID = self.currentCharacterID()
return self._model.getCharacterByID(ID)
def currentCharacters(self):
"""
Returns the selected characters (when multiple are selected)
@return: List of Characters
"""
IDs = self.currentCharacterIDs()
characters = []
for ID in IDs:
characters.append(self._model.getCharacterByID(ID))
return characters
2016-02-07 00:34:22 +13:00
def getItemByID(self, ID):
for t in range(self.topLevelItemCount()):
for i in range(self.topLevelItem(t).childCount()):
item = self.topLevelItem(t).child(i)
if item.data(0, Qt.UserRole) == ID:
return item
2015-06-29 09:46:51 +12:00
def mouseDoubleClickEvent(self, event):
item = self.currentItem()
if item is None:
return
2015-06-29 09:46:51 +12:00
# Catching double clicks to forbid collapsing of toplevel items
if item.parent():
QTreeWidget.mouseDoubleClickEvent(self, event)