#!/usr/bin/env python # --!-- coding: utf8 --!-- from PyQt5.QtCore import QModelIndex from PyQt5.QtCore import QSize from PyQt5.QtCore import Qt from PyQt5.QtGui import QStandardItem, QBrush, QFontMetrics from PyQt5.QtGui import QStandardItemModel, QColor from PyQt5.QtWidgets import QMenu, QAction, qApp from manuskript.enums import World from manuskript.functions import mainWindow from manuskript.ui import style as S class worldModel(QStandardItemModel): def __init__(self, parent): QStandardItemModel.__init__(self, 0, 3, parent) self.mw = mainWindow() ############################################################################### # SELECTION ############################################################################### def selectedItem(self): """Returns the item selected in mw.treeWorld. invisibleRootItem if None.""" index = self.selectedIndex() item = self.itemFromIndex(index) if item: return item else: return self.invisibleRootItem() def selectedIndex(self): """Returns the selected index in the treeView.""" if self.mw.treeWorld.selectedIndexes(): return self.mw.treeWorld.currentIndex() else: return QModelIndex() def selectedIndexes(self): return self.mw.treeWorld.selectedIndexes() ############################################################################### # GETTERS ############################################################################### def ID(self, index): """Returns the ID of the given index.""" index = index.sibling(index.row(), World.ID.value) return self.data(index) def name(self, index): """Returns the name of the given index.""" index = index.sibling(index.row(), World.name.value) return self.data(index) def description(self, index): index = index.sibling(index.row(), World.description.value) return self.data(index) def conflict(self, index): index = index.sibling(index.row(), World.conflict.value) return self.data(index) def passion(self, index): index = index.sibling(index.row(), World.passion.value) return self.data(index) def itemID(self, item): """Returns the ID of the given item.""" index = self.indexFromItem(item) return self.ID(index) def children(self, item): """Returns a list of all item's children.""" c = [] for i in range(item.rowCount()): c.append(item.child(i)) return c def listAll(self): """Returns a list of tupple ``(name, ID, path)`` for all items.""" lst = [] def readAll(item): name = item.text() ID = self.itemID(item) path = self.path(item) if name and ID: lst.append((name, ID, path)) for c in self.children(item): readAll(c) readAll(self.invisibleRootItem()) return lst def indexByID(self, ID): """Returns the index of item whose ID is ID.""" return self.indexFromItem(self.itemByID(ID)) def itemByID(self, ID): """Returns the item whose ID is ID.""" def browse(item): if self.itemID(item) == ID: return item for c in self.children(item): r = browse(c) if r: return r r = browse(self.invisibleRootItem()) return r if r else None def path(self, item): """Returns the path to the item in the form of 'ancestor > ... > grand-parent > parent'.""" path = [] while item.parent(): item = item.parent() path.append(item.text()) path = " > ".join(path) return path ############################################################################### # ADDING AND REMOVE ############################################################################### def addItem(self, title=None, parent=None): """Adds an item, and returns it.""" if not parent: parent = self.selectedItem() if not title: title = self.tr("New item") name = QStandardItem(title) _id = QStandardItem(self.getUniqueID()) row = [name, _id] + [QStandardItem() for i in range(2, len(World))] parent.appendRow(row) return name def getUniqueID(self): """Returns an unused ID""" parentItem = self.invisibleRootItem() vals = [] def collectIDs(item): vals.append(int(self.itemID(item))) for c in self.children(item): collectIDs(c) for c in self.children(parentItem): collectIDs(c) k = 0 while k in vals: k += 1 return str(k) def removeItem(self): while self.selectedIndexes(): index = self.selectedIndexes()[0] self.removeRows(index.row(), 1, index.parent()) ############################################################################### # TEMPLATES ############################################################################### def dataSets(self): """Returns sets of empty data that can guide the writer for world building.""" dataset = { self.tr("Fantasy world building"): [ (self.tr("Physical"), [ self.tr("Climate"), self.tr("Topography"), self.tr("Astronomy"), self.tr("Natural ressources"), self.tr("Wild life"), self.tr("Flora"), self.tr("History"), self.tr("Races"), self.tr("Diseases"), ]), (self.tr("Cultural"), [ self.tr("Customs"), self.tr("Food"), self.tr("Languages"), self.tr("Education"), self.tr("Dresses"), self.tr("Science"), self.tr("Calendar"), self.tr("Bodily language"), self.tr("Ethics"), self.tr("Religion"), self.tr("Government"), self.tr("Politics"), self.tr("Gender roles"), self.tr("Music and arts"), self.tr("Architecture"), self.tr("Military"), self.tr("Technology"), self.tr("Courtship"), self.tr("Demography"), self.tr("Transportation"), self.tr("Medicine"), ]), (self.tr("Magic system"), [ self.tr("Rules"), self.tr("Organization"), self.tr("Magical objects"), self.tr("Magical places"), self.tr("Magical races"), ]), self.tr("Important places"), self.tr("Important objects"), ] } return dataset def emptyDataMenu(self): """Returns a menu with the empty data sets.""" self.menu = QMenu("menu") for name in self.dataSets(): a = QAction(name, self.menu) a.triggered.connect(self.setEmptyData) self.menu.addAction(a) return self.menu def setEmptyData(self): """Called from the menu generated with ``emptyDataMenu``.""" act = self.sender() data = self.dataSets()[act.text()] def addItems(data, parent): for d in data: if len(d) == 1 or type(d) == str: self.addItem(d, parent) else: i = self.addItem(d[0], parent) addItems(d[1], i) addItems(data, None) self.mw.treeWorld.expandAll() ############################################################################### # APPEARANCE ############################################################################### def data(self, index, role=Qt.EditRole): level = 0 i = index while i.parent() != QModelIndex(): i = i.parent() level += 1 if role == Qt.BackgroundRole: if level == 0: return QBrush(QColor(S.highlightLight)) if role == Qt.TextAlignmentRole: if level == 0: return Qt.AlignCenter if role == Qt.FontRole: if level in [0, 1]: f = qApp.font() f.setBold(True) return f if role == Qt.ForegroundRole: if level == 0: return QBrush(QColor(S.highlightedTextDark)) if role == Qt.SizeHintRole: fm = QFontMetrics(qApp.font()) h = fm.height() if level == 0: return QSize(0, h + 12) elif level == 1: return QSize(0, h + 6) return QStandardItemModel.data(self, index, role)