manuskript/src/models/references.py

447 lines
15 KiB
Python
Raw Normal View History

#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import re
2015-07-03 03:33:05 +12:00
###############################################################################
# SHORT REFERENCES
###############################################################################
2015-07-06 19:45:28 +12:00
# A regex used to match references
2015-07-03 03:33:05 +12:00
RegEx = r"::(\w):(\d+?)::"
2015-07-06 19:45:28 +12:00
# A non-capturing regex used to identify references
2015-07-03 03:33:05 +12:00
RegExNonCapturing = r"::\w:\d+?::"
2015-07-06 19:45:28 +12:00
# The basic format of the references
2015-07-03 03:33:05 +12:00
EmptyRef = "::{}:{}::"
PersoLetter = "C"
TextLetter = "T"
PlotLetter = "P"
def plotReference(plotID):
2015-07-06 19:45:28 +12:00
"Takes the ID of a plot and returns a reference for that plot."
2015-07-03 03:33:05 +12:00
return EmptyRef.format(PlotLetter, plotID)
def persoReference(persoID):
2015-07-06 19:45:28 +12:00
"Takes the ID of a character and returns a reference for that character."
2015-07-03 03:33:05 +12:00
return EmptyRef.format(PersoLetter, persoID)
def textReference(outlineID):
2015-07-06 19:45:28 +12:00
"Takes the ID of an outline item and returns a reference for that item."
2015-07-03 03:33:05 +12:00
return EmptyRef.format(TextLetter, outlineID)
###############################################################################
# READABLE INFOS
###############################################################################
def infos(ref):
2015-07-06 19:45:28 +12:00
"""Returns a full paragraph in HTML format
containing detailed infos about the reference ``ref``.
"""
2015-07-03 03:33:05 +12:00
match = re.fullmatch(RegEx, ref)
2015-07-06 19:45:28 +12:00
if not match:
return qApp.translate("references", "Not a reference: {}.").format(ref)
_type = match.group(1)
_ref = match.group(2)
# A text or outine item
if _type == TextLetter:
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
2015-07-06 19:45:28 +12:00
if not idx.isValid():
return qApp.translate("references", "Unknown reference: {}.").format(ref)
item = idx.internalPointer()
#Titles
pathTitle = qApp.translate("references", "Path:")
statsTitle = qApp.translate("references", "Stats:")
POVTitle = qApp.translate("references", "POV:")
statusTitle = qApp.translate("references", "Status:")
labelTitle = qApp.translate("references", "Label:")
ssTitle = qApp.translate("references", "Short summary:")
lsTitle = qApp.translate("references", "Long summary:")
notesTitle = qApp.translate("references", "Notes:")
# The POV of the scene
POV = ""
if item.POV():
POV = "<a href='{ref}'>{text}</a>".format(
ref=persoReference(item.POV()),
text=mainWindow().mdlPersos.getPersoNameByID(item.POV()))
# The status of the scene
status = item.status()
if status:
status = mainWindow().mdlStatus.item(int(status), 0).text()
else:
status = ""
2015-06-30 22:27:43 +12:00
2015-07-06 19:45:28 +12:00
# The label of the scene
label = item.label()
if label:
label = mainWindow().mdlLabels.item(int(label), 0).text()
else:
label = ""
# The path of the scene
path = item.pathID()
pathStr = []
for _id, title in path:
pathStr.append("<a href='{ref}'>{text}</a>".format(
ref=textReference(_id),
text=title))
path = " > ".join(pathStr)
# Summaries and notes
ss = item.data(Outline.summarySentance.value)
ls = item.data(Outline.summaryFull.value)
notes = item.data(Outline.notes.value)
text = """<h1>{title}</h1>
<p><b>{pathTitle}</b> {path}</p>
<p><b>{statsTitle}</b> {stats}<br>
{POV}
{status}
{label}</p>
{ss}
{ls}
{notes}
""".format(
title=item.title(),
pathTitle=pathTitle,
path=path,
statsTitle=statsTitle,
stats=item.stats(),
POV="<b>{POVTitle}</b> {POV}<br>".format(
POVTitle=POVTitle,
POV=POV) if POV else "",
status="<b>{statusTitle}</b> {status}<br>".format(
statusTitle=statusTitle,
status=status) if status else "",
label="<b>{labelTitle}</b> {label}</p>".format(
labelTitle=labelTitle,
label=label) if label else "",
ss="<p><b>{ssTitle}</b> {ss}</p>".format(
ssTitle=ssTitle,
ss=ss.replace("\n", "<br>")) if ss else "",
ls="<p><b>{lsTitle}</b><br>{ls}</p>".format(
lsTitle=lsTitle,
ls=ls.replace("\n", "<br>")) if ls else "",
notes="<p><b>{notesTitle}</b><br>{notes}</p>".format(
notesTitle=notesTitle,
notes=linkifyAllRefs(basicT2TFormat(notes))) if notes else "",
)
return text
# A character
elif _type == PersoLetter:
m = mainWindow().mdlPersos
index = m.getIndexFromID(_ref)
name = m.name(index.row())
# Titles
basicTitle = qApp.translate("references", "Basic infos")
detailedTitle = qApp.translate("references", "Detailed infos")
POVof = qApp.translate("references", "POV of:")
referencedIn = qApp.translate("references", "Referenced in:")
# Goto (link)
goto = qApp.translate("references", "Go to {}.")
goto = goto.format(refToLink(ref))
# basic infos
basic = []
for i in [
(Perso.motivation, qApp.translate("references", "Motivation"), False),
(Perso.goal, qApp.translate("references", "Goal"), False),
(Perso.conflict, qApp.translate("references", "Conflict"), False),
(Perso.epiphany, qApp.translate("references", "Epiphany"), False),
(Perso.summarySentance, qApp.translate("references", "Short summary"), True),
(Perso.summaryPara, qApp.translate("references", "Longer summary"), True),
]:
val = m.data(index.sibling(index.row(), i[0].value))
if val:
basic .append("<b>{title}:</b>{n}{val}".format(
title=i[1],
n = "\n" if i[2] else " ",
val=val))
basic = "<br>".join(basic)
# detailed infos
detailed = []
for _name, _val in m.listPersoInfos(index):
detailed.append("<b>{}:</b> {}".format(
_name,
_val))
detailed = "<br>".join(detailed)
2015-07-01 00:01:32 +12:00
2015-07-06 19:45:28 +12:00
# list scenes of which it is POV
oM = mainWindow().mdlOutline
lst = oM.findItemsByPOV(_ref)
listPOV = ""
for t in lst:
idx = oM.getIndexByID(t)
listPOV += "<li><a href='{link}'>{text}</a></li>".format(
link=textReference(t),
text=oM.data(idx, Outline.title.value))
# List scenes where character is referenced
listRefs = ""
lst = oM.findItemsContaining(ref, [Outline.notes.value])
for t in lst:
idx = oM.getIndexByID(t)
listRefs += "<li><a href='{link}'>{text}</a></li>".format(
link=textReference(t),
text=oM.data(idx, Outline.title.value))
text = """<h1>{name}</h1>
{goto}
{basicInfos}
{detailedInfos}
{POV}
{references}
""".format(
name=name,
goto=goto,
basicInfos="<h2>{basicTitle}</h2>{basic}".format(
basicTitle=basicTitle,
basic=basic) if basic else "",
detailedInfos="<h2>{detailedTitle}</h2>{detailed}".format(
detailedTitle=detailedTitle,
detailed=detailed) if detailed else "",
POV="<h2>{POVof}</h2><ul>{listPOV}</ul>".format(
POVof=POVof,
listPOV=listPOV) if listPOV else "",
references="<h2>{referencedIn}</h2><ul>{listRefs}</ul>".format(
referencedIn=referencedIn,
listRefs=listRefs) if listRefs else "",
2015-07-01 00:01:32 +12:00
)
2015-07-06 19:45:28 +12:00
return text
# A plot
elif _type == PlotLetter:
m = mainWindow().mdlPlots
index = m.getIndexFromID(_ref)
name = m.getPlotNameByID(_ref)
2015-07-06 19:45:28 +12:00
# Titles
descriptionTitle = qApp.translate("references", "Description")
resultTitle = qApp.translate("references", "Result")
charactersTitle = qApp.translate("references", "Characters")
stepsTitle = qApp.translate("references", "Resolution steps")
# Goto (link)
goto = qApp.translate("references", "Go to {}.")
goto = goto.format(refToLink(ref))
# Description
description = m.data(index.sibling(index.row(),
Plot.description.value))
# Result
result = m.data(index.sibling(index.row(),
Plot.result.value))
2015-07-01 00:01:32 +12:00
2015-07-06 19:45:28 +12:00
# Characters
pM = mainWindow().mdlPersos
item = m.item(index.row(), Plot.persos.value)
characters = ""
if item:
for r in range(item.rowCount()):
ID = item.child(r, 0).text()
characters += "<li><a href='{link}'>{text}</a>".format(
link=persoReference(ID),
text=pM.getPersoNameByID(ID))
2015-07-01 00:01:32 +12:00
2015-07-06 19:45:28 +12:00
# Resolution steps
steps = ""
item = m.item(index.row(), Plot.subplots.value)
if item:
for r in range(item.rowCount()):
title = item.child(r, 0).text()
summary = item.child(r, 3).text()
steps += "<li><b>{title}:</b> {summary}</li>".format(
title=title,
summary=summary)
text = """<h1>{name}</h1>
{goto}
{characters}
{description}
{result}
{steps}
""".format(
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
result="<h2>{title}</h2>{text}".format(
title=resultTitle,
text=result) if result else "",
characters="<h2>{title}</h2><ul>{lst}</ul>".format(
title=charactersTitle,
lst=characters) if characters else "",
steps="<h2>{title}</h2><ul>{steps}</ul>".format(
title=stepsTitle,
steps=steps) if steps else "",
)
return text
else:
2015-06-27 22:20:05 +12:00
return qApp.translate("references", "Unknown reference: {}.").format(ref)
2015-07-03 03:33:05 +12:00
def tooltip(ref):
2015-07-06 19:45:28 +12:00
"Returns a tooltip in HTML for the reference ``ref``."
2015-07-03 03:33:05 +12:00
match = re.fullmatch(RegEx, ref)
2015-07-06 19:45:28 +12:00
if not match:
return qApp.translate("references", "Not a reference: {}.").format(ref)
_type = match.group(1)
_ref = match.group(2)
if _type == TextLetter:
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
2015-07-03 03:33:05 +12:00
2015-07-06 19:45:28 +12:00
if not idx.isValid():
return qApp.translate("references", "Unknown reference: {}.").format(ref)
2015-07-03 03:33:05 +12:00
2015-07-06 19:45:28 +12:00
item = idx.internalPointer()
tooltip = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
tooltip += "<br><i>{}</i>".format(item.path())
return tooltip
elif _type == PersoLetter:
m = mainWindow().mdlPersos
name = m.item(int(_ref), Perso.name.value).text()
return qApp.translate("references", "Character: <b>{}</b>").format(name)
2015-07-03 03:33:05 +12:00
2015-07-06 19:45:28 +12:00
elif _type == PlotLetter:
m = mainWindow().mdlPlots
name = m.getPlotNameByID(_ref)
return qApp.translate("references", "Plot: <b>{}</b>").format(name)
2015-07-03 03:33:05 +12:00
else:
return qApp.translate("references", "Unknown reference: {}.").format(ref)
###############################################################################
# FUNCTIONS
###############################################################################
2015-06-30 22:27:43 +12:00
def refToLink(ref):
2015-07-06 19:45:28 +12:00
"""Transforms the reference ``ref`` in a link displaying useful infos
about that reference. For character, character's name. For text item,
item's name, etc.
"""
2015-07-03 03:33:05 +12:00
match = re.fullmatch(RegEx, ref)
2015-06-30 22:27:43 +12:00
if match:
_type = match.group(1)
_ref = match.group(2)
text = ""
2015-07-03 03:33:05 +12:00
if _type == TextLetter:
2015-06-30 22:27:43 +12:00
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
if idx.isValid():
item = idx.internalPointer()
text = item.title()
2015-07-03 03:33:05 +12:00
elif _type == PersoLetter:
2015-06-30 22:27:43 +12:00
m = mainWindow().mdlPersos
text = m.item(int(_ref), Perso.name.value).text()
2015-07-06 19:45:28 +12:00
elif _type == PlotLetter:
m = mainWindow().mdlPlots
text = m.getPlotNameByID(_ref)
2015-06-30 22:27:43 +12:00
if text:
return "<a href='{ref}'>{text}</a>".format(
ref=ref,
text=text)
else:
return ref
def linkifyAllRefs(text):
2015-07-06 19:45:28 +12:00
"Takes all the references in ``text`` and transform them into HMTL links."
2015-07-03 03:33:05 +12:00
return re.sub(RegEx, lambda m: refToLink(m.group(0)), text)
2015-06-30 22:27:43 +12:00
2015-07-04 04:41:18 +12:00
def basicT2TFormat(text, formatting=True, EOL=True, titles=True):
2015-07-06 19:45:28 +12:00
"A very basic t2t formatter to display notes and texts."
2015-07-04 20:03:33 +12:00
text = text.splitlines()
for n in range(len(text)):
if formatting:
text[n] = re.sub("\*\*(.*?)\*\*", "<b>\\1</b>", text[n])
text[n] = re.sub("//(.*?)//", "<i>\\1</i>", text[n])
text[n] = re.sub("__(.*?)__", "<u>\\1</u>", text[n])
if titles:
for i in range(1, 6):
r1 = '^\s*{s}([^=].*[^=]){s}\s*$'.format(s="=" * i)
r2 = '^\s*{s}([^\+].*[^\+]){s}\s*$'.format(s="\\+" * i)
t = "<h{n}>\\1</h{n}>".format(n=i)
text[n] = re.sub(r1, t, text[n])
text[n] = re.sub(r2, t, text[n])
text = "\n".join(text)
2015-07-04 04:41:18 +12:00
if EOL:
text = text.replace("\n", "<br>")
return text
2015-07-03 03:33:05 +12:00
def open(ref):
2015-07-06 19:45:28 +12:00
"Identify ``ref`` and open it."
2015-07-03 03:33:05 +12:00
match = re.fullmatch(RegEx, ref)
2015-07-06 19:45:28 +12:00
if not match:
return
_type = match.group(1)
_ref = match.group(2)
if _type == PersoLetter:
mw = mainWindow()
item = mw.lstPersos.getItemByID(_ref)
2015-06-27 22:20:05 +12:00
2015-07-06 19:45:28 +12:00
if item:
mw.tabMain.setCurrentIndex(2)
mw.lstPersos.setCurrentItem(item)
return True
2015-06-27 22:20:05 +12:00
2015-07-06 19:45:28 +12:00
print("Ref not found")
return False
elif _type == TextLetter:
mw = mainWindow()
index = mw.mdlOutline.getIndexByID(_ref)
if index.isValid():
mw.mainEditor.setCurrentModelIndex(index, newTab=True)
return True
else:
2015-06-27 22:20:05 +12:00
print("Ref not found")
return False
2015-07-06 19:45:28 +12:00
elif _type == PlotLetter:
mw = mainWindow()
item = mw.lstPlots.getItemByID(_ref)
2015-06-27 22:20:05 +12:00
2015-07-06 19:45:28 +12:00
if item:
mw.tabMain.setCurrentIndex(3)
mw.lstPlots.setCurrentItem(item)
return True
2015-06-27 22:20:05 +12:00
2015-07-06 19:45:28 +12:00
print("Ref not found")
return False
print("Ref not implemented")
return False