diff --git a/manuskript/models/references.py b/manuskript/models/references.py
index ac29a06c..d8f87e7a 100644
--- a/manuskript/models/references.py
+++ b/manuskript/models/references.py
@@ -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: {}").format(item.title())
+ infos["text_type"] = "folder"
else:
- tt = qApp.translate("references", "Text: {}").format(item.title())
- tt += "
{}".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: {}").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: {}").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: {name}{path}").format(
- name=name,
- path=" ({})".format(path) if path else "")
+ infos["title"] = name
+ infos["path"] = path
+ return infos
- return qApp.translate("references", "Unknown reference: {}.").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", "Unknown reference: {}.").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: {}").format(infos["title"])
+ else:
+ tt = qApp.translate("references", "Text: {}").format(infos["title"])
+ tt += "
{}".format(infos["path"])
+ return tt
+
+ elif infos["type"] == PersoLetter:
+ return qApp.translate("references", "Character: {}").format(infos["title"])
+
+ elif infos["type"] == PlotLetter:
+ return qApp.translate("references", "Plot: {}").format(infos["title"])
+
+ elif infos["type"] == WorldLetter:
+ return qApp.translate("references", "World: {name}{path}").format(
+ name=infos["title"],
+ path=" ({})".format(infos["path"]) if infos["path"] else "")
###############################################################################
diff --git a/manuskript/ui/views/storylineView.py b/manuskript/ui/views/storylineView.py
index ac149f70..a5f81362 100644
--- a/manuskript/ui/views/storylineView.py
+++ b/manuskript/ui/views/storylineView.py
@@ -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()