mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-21 05:12:27 +12:00
Story line can display characters
This commit is contained in:
parent
b3ebcaee10
commit
f40a43b6ed
|
@ -373,56 +373,125 @@ def infos(ref):
|
|||
return qApp.translate("references", "Unknown reference: {}.").format(ref)
|
||||
|
||||
|
||||
def tooltip(ref):
|
||||
"""Returns a tooltip in HTML for the reference ``ref``."""
|
||||
def shortInfos(ref):
|
||||
"""Returns infos about reference ``ref``.
|
||||
Returns -1 if ``ref`` is not a valid reference, and None if it is valid but unknown."""
|
||||
match = re.fullmatch(RegEx, ref)
|
||||
|
||||
if not match:
|
||||
return qApp.translate("references", "Not a reference: {}.").format(ref)
|
||||
return -1
|
||||
|
||||
_type = match.group(1)
|
||||
_ref = match.group(2)
|
||||
|
||||
infos = {}
|
||||
infos["ID"] = _ref
|
||||
|
||||
if _type == TextLetter:
|
||||
|
||||
infos["type"] = TextLetter
|
||||
|
||||
m = mainWindow().mdlOutline
|
||||
idx = m.getIndexByID(_ref)
|
||||
|
||||
if not idx.isValid():
|
||||
return qApp.translate("references", "Unknown reference: {}.").format(ref)
|
||||
return None
|
||||
|
||||
item = idx.internalPointer()
|
||||
|
||||
if item.isFolder():
|
||||
tt = qApp.translate("references", "Folder: <b>{}</b>").format(item.title())
|
||||
infos["text_type"] = "folder"
|
||||
else:
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
|
||||
tt += "<br><i>{}</i>".format(item.path())
|
||||
infos["text_type"] = "text"
|
||||
|
||||
return tt
|
||||
infos["title"] = item.title()
|
||||
infos["path"] = item.path()
|
||||
return infos
|
||||
|
||||
elif _type == PersoLetter:
|
||||
|
||||
infos["type"] = PersoLetter
|
||||
|
||||
m = mainWindow().mdlPersos
|
||||
item = m.item(int(_ref), Perso.name.value)
|
||||
if item:
|
||||
return qApp.translate("references", "Character: <b>{}</b>").format(item.text())
|
||||
infos["title"] = item.text()
|
||||
infos["name"] = item.text()
|
||||
return infos
|
||||
|
||||
elif _type == PlotLetter:
|
||||
|
||||
infos["type"] = PlotLetter
|
||||
|
||||
m = mainWindow().mdlPlots
|
||||
name = m.getPlotNameByID(_ref)
|
||||
if name:
|
||||
return qApp.translate("references", "Plot: <b>{}</b>").format(name)
|
||||
infos["title"] = name
|
||||
return infos
|
||||
|
||||
elif _type == WorldLetter:
|
||||
|
||||
infos["type"] = WorldLetter
|
||||
|
||||
m = mainWindow().mdlWorld
|
||||
item = m.itemByID(_ref)
|
||||
if item:
|
||||
name = item.text()
|
||||
path = m.path(item)
|
||||
return qApp.translate("references", "World: <b>{name}</b>{path}").format(
|
||||
name=name,
|
||||
path=" <span style='color:gray;'>({})</span>".format(path) if path else "")
|
||||
infos["title"] = name
|
||||
infos["path"] = path
|
||||
return infos
|
||||
|
||||
return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
|
||||
return None
|
||||
|
||||
|
||||
def title(ref):
|
||||
"""Returns a the title (or name) for the reference ``ref``."""
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1 and "title" in infos:
|
||||
return infos["title"]
|
||||
else:
|
||||
return None
|
||||
|
||||
def type(ref):
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1:
|
||||
return infos["type"]
|
||||
|
||||
def ID(ref):
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1:
|
||||
return infos["ID"]
|
||||
|
||||
def tooltip(ref):
|
||||
"""Returns a tooltip in HTML for the reference ``ref``."""
|
||||
infos = shortInfos(ref)
|
||||
|
||||
if not infos:
|
||||
return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
|
||||
|
||||
if infos == -1:
|
||||
return qApp.translate("references", "Not a reference: {}.").format(ref)
|
||||
|
||||
|
||||
if infos["type"] == TextLetter:
|
||||
if infos["text_type"] == "folder":
|
||||
tt = qApp.translate("references", "Folder: <b>{}</b>").format(infos["title"])
|
||||
else:
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(infos["title"])
|
||||
tt += "<br><i>{}</i>".format(infos["path"])
|
||||
return tt
|
||||
|
||||
elif infos["type"] == PersoLetter:
|
||||
return qApp.translate("references", "Character: <b>{}</b>").format(infos["title"])
|
||||
|
||||
elif infos["type"] == PlotLetter:
|
||||
return qApp.translate("references", "Plot: <b>{}</b>").format(infos["title"])
|
||||
|
||||
elif infos["type"] == WorldLetter:
|
||||
return qApp.translate("references", "World: <b>{name}</b>{path}").format(
|
||||
name=infos["title"],
|
||||
path=" <span style='color:gray;'>({})</span>".format(infos["path"]) if infos["path"] else "")
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import Qt, QTimer, QRectF
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics, QFontMetricsF
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics, QFontMetricsF, QColor
|
||||
from PyQt5.QtWidgets import QWidget, QGraphicsScene, QGraphicsSimpleTextItem, QMenu, QAction, QGraphicsRectItem, \
|
||||
QGraphicsLineItem, QGraphicsEllipseItem
|
||||
|
||||
|
@ -32,15 +32,17 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
def generateMenu(self):
|
||||
m = QMenu()
|
||||
|
||||
for i in [
|
||||
self.tr("Show Plots"),
|
||||
self.tr("Show Characters"),
|
||||
self.tr("Show Objects"),
|
||||
]:
|
||||
a = QAction(i, m)
|
||||
a.setCheckable(True)
|
||||
a.setEnabled(False)
|
||||
m.addAction(a)
|
||||
self.actPlots = QAction(self.tr("Show Plots"), m)
|
||||
self.actPlots.setCheckable(True)
|
||||
self.actPlots.setChecked(True)
|
||||
self.actPlots.toggled.connect(self.reloadTimer.start)
|
||||
m.addAction(self.actPlots)
|
||||
|
||||
self.actCharacters = QAction(self.tr("Show Characters"), m)
|
||||
self.actCharacters.setCheckable(True)
|
||||
self.actCharacters.setChecked(False)
|
||||
self.actCharacters.toggled.connect(self.reloadTimer.start)
|
||||
m.addAction(self.actCharacters)
|
||||
|
||||
self.btnSettings.setMenu(m)
|
||||
|
||||
|
@ -55,6 +57,33 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
self._mdlPersos = mdlPersos
|
||||
self._mdlPersos.dataChanged.connect(self.reloadTimer.start)
|
||||
|
||||
def plotReferences(self):
|
||||
"Returns a list of plot references"
|
||||
if not self._mdlPlots:
|
||||
pass
|
||||
|
||||
plotsID = self._mdlPlots.getPlotsByImportance()
|
||||
r = []
|
||||
for importance in plotsID:
|
||||
for ID in importance:
|
||||
ref = references.plotReference(ID)
|
||||
r.append(ref)
|
||||
|
||||
return r
|
||||
|
||||
def persosReferences(self):
|
||||
"Returns a list of character references"
|
||||
if not self._mdlPersos:
|
||||
pass
|
||||
|
||||
IDs = self._mdlPersos.getPersosByImportance()
|
||||
r = []
|
||||
for importance in IDs:
|
||||
for ID in importance:
|
||||
ref = references.persoReference(ID)
|
||||
r.append(ref)
|
||||
|
||||
return r
|
||||
|
||||
def refresh(self):
|
||||
if not self._mdlPlots or not self._mdlOutline or not self._mdlPersos:
|
||||
|
@ -82,24 +111,24 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
|
||||
MAX_LEVEL = maxLevel(root)
|
||||
|
||||
# Generate left entries
|
||||
# (As of now, plot only)
|
||||
plotsID = self._mdlPlots.getPlotsByImportance()
|
||||
# Get the list of tracked items (array of references)
|
||||
trackedItems = []
|
||||
fm = QFontMetrics(s.font())
|
||||
max_name = 0
|
||||
|
||||
for importance in plotsID:
|
||||
for ID in importance:
|
||||
name = self._mdlPlots.getPlotNameByID(ID)
|
||||
ref = references.plotReference(ID, searchable=True)
|
||||
if self.actPlots.isChecked():
|
||||
trackedItems += self.plotReferences()
|
||||
|
||||
trackedItems.append((ID, ref, name))
|
||||
max_name = max(fm.width(name), max_name)
|
||||
if self.actCharacters.isChecked():
|
||||
trackedItems += self.persosReferences()
|
||||
|
||||
ROWS_HEIGHT = len(trackedItems) * (LINE_HEIGHT + SPACING )
|
||||
TITLE_WIDTH = max_name + 2 * SPACING
|
||||
|
||||
fm = QFontMetrics(s.font())
|
||||
max_name = 0
|
||||
for ref in trackedItems:
|
||||
name = references.title(ref)
|
||||
max_name = max(fm.width(name), max_name)
|
||||
|
||||
TITLE_WIDTH = max_name + 2 * SPACING
|
||||
|
||||
# Add Folders and Texts
|
||||
outline = OutlineRect(0, 0, 0, ROWS_HEIGHT + SPACING + MAX_LEVEL * LEVEL_HEIGHT)
|
||||
|
@ -150,9 +179,22 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
rectChild.setToolTip(references.tooltip(references.textReference(child.ID())))
|
||||
|
||||
# Find tracked references in that scene (or parent folders)
|
||||
for ID, ref, name in trackedItems:
|
||||
for ref in trackedItems:
|
||||
|
||||
result = []
|
||||
|
||||
# Tests if POV
|
||||
scenePOV = False # Will hold true of character is POV of the current text, not containing folder
|
||||
if references.type(ref) == references.PersoLetter:
|
||||
ID = references.ID(ref)
|
||||
c = child
|
||||
while c:
|
||||
if c.POV() == ID:
|
||||
result.append(c.ID())
|
||||
if c == child: scenePOV = True
|
||||
c = c.parent()
|
||||
|
||||
# Search in notes/references
|
||||
c = child
|
||||
while c:
|
||||
result += references.findReferencesTo(ref, c, recursive=False)
|
||||
|
@ -162,7 +204,7 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
ref2 = result[0]
|
||||
|
||||
# Create a RefCircle with the reference
|
||||
c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2)
|
||||
c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2, important=scenePOV)
|
||||
|
||||
# Store it, with the position of that item, to display it on the line later on
|
||||
refCircles.append((ref, c, rect.mapToItem(outline, rectChild.pos())))
|
||||
|
@ -173,22 +215,27 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
|
||||
OUTLINE_WIDTH = itemWidth(root)
|
||||
|
||||
# Add Plots
|
||||
# Add Tracked items
|
||||
i = 0
|
||||
itemsRect = s.addRect(0, 0, 0, 0)
|
||||
itemsRect.setPos(0, MAX_LEVEL * LEVEL_HEIGHT + SPACING)
|
||||
|
||||
for ID, ref, name in trackedItems:
|
||||
color = randomColor()
|
||||
for ref in trackedItems:
|
||||
if references.type(ref) == references.PersoLetter:
|
||||
color = QColor(self._mdlPersos.getPersoColorByID(references.ID(ref)))
|
||||
else:
|
||||
color = randomColor()
|
||||
|
||||
# Rect
|
||||
r = QGraphicsRectItem(0, 0, TITLE_WIDTH, LINE_HEIGHT, itemsRect)
|
||||
r.setPen(QPen(Qt.NoPen))
|
||||
r.setBrush(QBrush(color))
|
||||
r.setPos(0, i * LINE_HEIGHT + i * SPACING)
|
||||
r.setToolTip(references.tooltip(ref))
|
||||
i += 1
|
||||
|
||||
# Text
|
||||
name = references.title(ref)
|
||||
txt = QGraphicsSimpleTextItem(name, r)
|
||||
txt.setPos(r.boundingRect().center() - txt.boundingRect().center())
|
||||
|
||||
|
@ -198,7 +245,7 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
line.setPos(TITLE_WIDTH, r.mapToScene(r.rect().center()).y())
|
||||
s.addItem(line)
|
||||
line.setPen(QPen(color, 5))
|
||||
line.setToolTip(self.tr("Plot: ") + name)
|
||||
line.setToolTip(references.tooltip(ref))
|
||||
|
||||
# We add the circles / references to text, on the line
|
||||
for ref2, circle, pos in refCircles:
|
||||
|
@ -225,13 +272,15 @@ class OutlineRect(QGraphicsRectItem):
|
|||
|
||||
|
||||
class RefCircle(QGraphicsEllipseItem):
|
||||
def __init__(self, x, y, diameter, parent=None, ID=None):
|
||||
def __init__(self, x, y, diameter, parent=None, ID=None, important=False):
|
||||
QGraphicsEllipseItem.__init__(self, x, y, diameter, diameter, parent)
|
||||
self.setBrush(Qt.white)
|
||||
self._ref = references.textReference(ID)
|
||||
self.setToolTip(references.tooltip(self._ref))
|
||||
self.setPen(QPen(Qt.black, 2))
|
||||
self.setAcceptHoverEvents(True)
|
||||
if important:
|
||||
self.setBrush(Qt.black)
|
||||
|
||||
def multiplyDiameter(self, factor):
|
||||
r1 = self.rect()
|
||||
|
|
Loading…
Reference in a new issue