manuskript/manuskript/models/references.py

675 lines
22 KiB
Python
Raw Normal View History

#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
import re
import logging
LOGGER = logging.getLogger(__name__)
2015-07-03 03:33:05 +12:00
###############################################################################
# SHORT REFERENCES
###############################################################################
2015-07-06 19:45:28 +12:00
# A regex used to match references
2016-02-07 00:34:22 +13:00
from PyQt5.QtWidgets import qApp
2017-11-15 03:22:16 +13:00
from PyQt5.QtGui import QColor
from PyQt5.QtCore import Qt
2016-02-07 00:34:22 +13:00
from manuskript.enums import Outline
from manuskript.enums import Character
2016-02-07 00:34:22 +13:00
from manuskript.enums import Plot
2016-03-07 04:10:25 +13:00
from manuskript.enums import PlotStep
from manuskript.functions import mainWindow, mixColors, safeTranslate
2017-11-15 03:22:16 +13:00
from manuskript.ui import style as S
2016-02-07 00:34:22 +13:00
RegEx = r"{(\w):(\d+):?.*?}"
2015-07-06 19:45:28 +12:00
# A non-capturing regex used to identify references
RegExNonCapturing = r"{\w:\d+:?.*?}"
2015-07-06 19:45:28 +12:00
# The basic format of the references
EmptyRef = "{{{}:{}:{}}}"
2016-02-29 00:43:23 +13:00
EmptyRefSearchable = "{{{}:{}:"
CharacterLetter = "C"
2015-07-03 03:33:05 +12:00
TextLetter = "T"
PlotLetter = "P"
WorldLetter = "W"
2015-07-03 03:33:05 +12:00
2017-11-15 03:22:16 +13:00
# Colors
TextHighlightColor = QColor(mixColors(QColor(Qt.blue).name(), S.window, .3))
CharacterHighlightColor = QColor(mixColors(QColor(Qt.yellow).name(), S.window, .3))
PlotHighlightColor = QColor(mixColors(QColor(Qt.red).name(), S.window, .3))
WorldHighlightColor = QColor(mixColors(QColor(Qt.green).name(), S.window, .3))
2016-02-07 00:34:22 +13:00
2016-02-29 00:43:23 +13:00
def plotReference(ID, searchable=False):
"""Takes the ID of a plot and returns a reference for that plot.
@searchable: returns a stripped version that allows simple text search."""
if not searchable:
return EmptyRef.format(PlotLetter, ID, "")
else:
return EmptyRefSearchable.format(PlotLetter, ID, "")
2015-07-03 03:33:05 +12:00
2016-02-07 00:34:22 +13:00
def characterReference(ID, searchable=False):
2016-02-29 00:43:23 +13:00
"""Takes the ID of a character and returns a reference for that character.
@searchable: returns a stripped version that allows simple text search."""
if not searchable:
return EmptyRef.format(CharacterLetter, ID, "")
2016-02-29 00:43:23 +13:00
else:
return EmptyRefSearchable.format(CharacterLetter, ID, "")
2015-07-03 03:33:05 +12:00
2016-02-07 00:34:22 +13:00
2016-02-29 00:43:23 +13:00
def textReference(ID, searchable=False):
"""Takes the ID of an outline item and returns a reference for that item.
@searchable: returns a stripped version that allows simple text search."""
if not searchable:
return EmptyRef.format(TextLetter, ID, "")
else:
return EmptyRefSearchable.format(TextLetter, ID, "")
2015-07-03 03:33:05 +12:00
2016-02-07 00:34:22 +13:00
2016-02-29 00:43:23 +13:00
def worldReference(ID, searchable=False):
"""Takes the ID of a world item and returns a reference for that item.
@searchable: returns a stripped version that allows simple text search."""
if not searchable:
return EmptyRef.format(WorldLetter, ID, "")
else:
return EmptyRefSearchable.format(WorldLetter, ID, "")
2016-02-07 00:34:22 +13:00
2015-07-03 03:33:05 +12:00
###############################################################################
# READABLE INFOS
###############################################################################
def infos(ref):
2017-11-15 03:22:16 +13:00
"""Returns a full paragraph in HTML format
2015-07-06 19:45:28 +12:00
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 safeTranslate(qApp, "references", "Not a reference: {}.").format(ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
_type = match.group(1)
_ref = match.group(2)
2016-02-07 00:34:22 +13:00
# A text or outline item
2015-07-06 19:45:28 +12:00
if _type == TextLetter:
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if not idx.isValid():
return safeTranslate(qApp, "references", "Unknown reference: {}.").format(ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
item = idx.internalPointer()
2016-02-07 00:34:22 +13:00
# Titles
pathTitle = safeTranslate(qApp, "references", "Path:")
statsTitle = safeTranslate(qApp, "references", "Stats:")
POVTitle = safeTranslate(qApp, "references", "POV:")
statusTitle = safeTranslate(qApp, "references", "Status:")
labelTitle = safeTranslate(qApp, "references", "Label:")
ssTitle = safeTranslate(qApp, "references", "Short summary:")
lsTitle = safeTranslate(qApp, "references", "Long summary:")
notesTitle = safeTranslate(qApp, "references", "Notes:")
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# The POV of the scene
POV = ""
if item.POV():
POV = "<a href='{ref}'>{text}</a>".format(
ref=characterReference(item.POV()),
text=mainWindow().mdlCharacter.getCharacterByID(item.POV()).name())
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# The status of the scene
status = item.status()
if status:
status = mainWindow().mdlStatus.item(int(status), 0).text()
else:
status = ""
2016-02-07 00:34:22 +13: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 = ""
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# The path of the scene
path = item.pathID()
pathStr = []
for _id, title in path:
pathStr.append("<a href='{ref}'>{text}</a>".format(
2016-02-07 00:34:22 +13:00
ref=textReference(_id),
text=title))
2015-07-06 19:45:28 +12:00
path = " > ".join(pathStr)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Summaries and notes
2017-11-16 08:58:12 +13:00
ss = item.data(Outline.summarySentence)
ls = item.data(Outline.summaryFull)
notes = item.data(Outline.notes)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
text = """<h1>{title}</h1>
<p><b>{pathTitle}</b> {path}</p>
<p><b>{statsTitle}</b> {stats}<br>
{POV}
{status}
{label}</p>
{ss}
{ls}
{notes}
2015-07-11 02:24:49 +12:00
{references}
2015-07-06 19:45:28 +12:00
""".format(
2016-02-07 00:34:22 +13:00
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.strip() else "",
ls="<p><b>{lsTitle}</b><br>{ls}</p>".format(
lsTitle=lsTitle,
ls=ls.replace("\n", "<br>")) if ls.strip() else "",
notes="<p><b>{notesTitle}</b><br>{notes}</p>".format(
notesTitle=notesTitle,
2016-03-30 22:00:27 +13:00
notes=linkifyAllRefs(notes)) if notes.strip() else "",
2016-02-07 00:34:22 +13:00
references=listReferences(ref)
)
2015-07-06 19:45:28 +12:00
return text
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# A character
elif _type == CharacterLetter:
m = mainWindow().mdlCharacter
c = m.getCharacterByID(int(_ref))
2021-02-22 11:45:34 +13:00
if c == None:
return safeTranslate(qApp, "references", "Unknown reference: {}.").format(ref)
2017-11-21 03:42:30 +13:00
index = c.index()
name = c.name()
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Titles
basicTitle = safeTranslate(qApp, "references", "Basic info")
detailedTitle = safeTranslate(qApp, "references", "Detailed info")
POVof = safeTranslate(qApp, "references", "POV of:")
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Goto (link)
goto = safeTranslate(qApp, "references", "Go to {}.")
2015-07-06 19:45:28 +12:00
goto = goto.format(refToLink(ref))
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# basic infos
basic = []
for i in [
(Character.motivation, safeTranslate(qApp, "references", "Motivation"), False),
(Character.goal, safeTranslate(qApp, "references", "Goal"), False),
(Character.conflict, safeTranslate(qApp, "references", "Conflict"), False),
(Character.epiphany, safeTranslate(qApp, "references", "Epiphany"), False),
(Character.summarySentence, safeTranslate(qApp, "references", "Short summary"), True),
(Character.summaryPara, safeTranslate(qApp, "references", "Longer summary"), True),
2016-02-07 00:34:22 +13:00
]:
2015-07-06 19:45:28 +12:00
val = m.data(index.sibling(index.row(), i[0].value))
2015-07-06 19:45:28 +12:00
if val:
2016-02-07 00:34:22 +13:00
basic.append("<b>{title}:</b>{n}{val}".format(
title=i[1],
n="\n" if i[2] else " ",
val=val))
2015-07-06 19:45:28 +12:00
basic = "<br>".join(basic)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# detailed infos
detailed = []
for _name, _val in c.listInfos():
2015-07-06 19:45:28 +12:00
detailed.append("<b>{}:</b> {}".format(
2016-02-07 00:34:22 +13:00
_name,
_val))
2015-07-06 19:45:28 +12:00
detailed = "<br>".join(detailed)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# list scenes of which it is POV
oM = mainWindow().mdlOutline
lst = oM.findItemsByPOV(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
listPOV = ""
for t in lst:
idx = oM.getIndexByID(t)
listPOV += "<li><a href='{link}'>{text}</a></li>".format(
2016-02-07 00:34:22 +13:00
link=textReference(t),
2017-11-16 08:58:12 +13:00
text=oM.data(idx, Outline.title))
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
text = """<h1>{name}</h1>
{goto}
{basicInfos}
{detailedInfos}
{POV}
{references}
""".format(
2016-02-07 00:34:22 +13:00
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=listReferences(ref)
)
2015-07-06 19:45:28 +12:00
return text
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# A plot
elif _type == PlotLetter:
m = mainWindow().mdlPlots
index = m.getIndexFromID(_ref)
name = m.getPlotNameByID(_ref)
2016-02-07 00:34:22 +13:00
2017-11-21 03:42:30 +13:00
if not index.isValid():
return safeTranslate(qApp, "references", "Unknown reference: {}.").format(ref)
2017-11-21 03:42:30 +13:00
2015-07-06 19:45:28 +12:00
# Titles
descriptionTitle = safeTranslate(qApp, "references", "Description")
resultTitle = safeTranslate(qApp, "references", "Result")
charactersTitle = safeTranslate(qApp, "references", "Characters")
stepsTitle = safeTranslate(qApp, "references", "Resolution steps")
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Goto (link)
goto = safeTranslate(qApp, "references", "Go to {}.")
2015-07-06 19:45:28 +12:00
goto = goto.format(refToLink(ref))
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Description
2016-02-07 00:34:22 +13:00
description = m.data(index.sibling(index.row(),
2017-11-16 09:05:48 +13:00
Plot.description))
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Result
2016-02-07 00:34:22 +13:00
result = m.data(index.sibling(index.row(),
2017-11-16 09:05:48 +13:00
Plot.result))
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Characters
pM = mainWindow().mdlCharacter
2017-11-16 09:05:48 +13:00
item = m.item(index.row(), Plot.characters)
2015-07-06 19:45:28 +12:00
characters = ""
if item:
for r in range(item.rowCount()):
ID = item.child(r, 0).text()
characters += "<li><a href='{link}'>{text}</a>".format(
link=characterReference(ID),
2016-04-09 01:30:14 +12:00
text=pM.getCharacterByID(ID).name())
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
# Resolution steps
steps = ""
2017-11-16 09:05:48 +13:00
item = m.item(index.row(), Plot.steps)
2015-07-06 19:45:28 +12:00
if item:
for r in range(item.rowCount()):
2017-11-16 09:05:48 +13:00
title = item.child(r, PlotStep.name).text()
summary = item.child(r, PlotStep.summary).text()
meta = item.child(r, PlotStep.meta).text()
2015-07-07 01:00:22 +12:00
if meta:
meta = " <span style='color:gray;'>({})</span>".format(meta)
steps += "<li><b>{title}</b>{summary}{meta}</li>".format(
2016-02-07 00:34:22 +13:00
title=title,
summary=": {}".format(summary) if summary else "",
meta=meta if meta else "")
2015-07-06 19:45:28 +12:00
text = """<h1>{name}</h1>
{goto}
{characters}
{description}
{result}
{steps}
{references}
2015-07-06 19:45:28 +12:00
""".format(
2016-02-07 00:34:22 +13:00
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 "",
references=listReferences(ref)
)
2015-07-06 19:45:28 +12:00
return text
2016-02-07 00:34:22 +13:00
# A World item
elif _type == WorldLetter:
m = mainWindow().mdlWorld
index = m.indexByID(_ref)
name = m.name(index)
2016-02-07 00:34:22 +13:00
2017-11-21 03:42:30 +13:00
if not index.isValid():
return safeTranslate(qApp, "references", "Unknown reference: {}.").format(ref)
2017-11-21 03:42:30 +13:00
# Titles
descriptionTitle = safeTranslate(qApp, "references", "Description")
passionTitle = safeTranslate(qApp, "references", "Passion")
conflictTitle = safeTranslate(qApp, "references", "Conflict")
2016-02-07 00:34:22 +13:00
# Goto (link)
goto = safeTranslate(qApp, "references", "Go to {}.")
goto = goto.format(refToLink(ref))
2016-02-07 00:34:22 +13:00
# Description
description = basicFormat(m.description(index))
2016-02-07 00:34:22 +13:00
# Passion
2016-02-07 00:34:22 +13:00
passion = basicFormat(m.passion(index))
# Conflict
2016-02-07 00:34:22 +13:00
conflict = basicFormat(m.conflict(index))
text = """<h1>{name}</h1>
{goto}
{description}
{passion}
{conflict}
{references}
""".format(
2016-02-07 00:34:22 +13:00
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
passion="<h2>{title}</h2>{text}".format(
title=passionTitle,
text=passion) if passion else "",
conflict="<h2>{title}</h2><ul>{lst}</ul>".format(
title=conflictTitle,
lst=conflict) if conflict else "",
references=listReferences(ref)
)
return text
2016-02-07 00:34:22 +13:00
else:
return safeTranslate(qApp, "references", "Unknown reference: {}.").format(ref)
2016-02-07 00:34:22 +13:00
2016-03-01 11:25:23 +13:00
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."""
2015-07-03 03:33:05 +12:00
match = re.fullmatch(RegEx, ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if not match:
2016-03-01 11:25:23 +13:00
return -1
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
_type = match.group(1)
_ref = match.group(2)
2016-02-07 00:34:22 +13:00
2016-03-01 11:25:23 +13:00
infos = {}
infos["ID"] = _ref
2015-07-06 19:45:28 +12:00
if _type == TextLetter:
2016-03-01 11:25:23 +13:00
infos["type"] = TextLetter
2015-07-06 19:45:28 +12:00
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if not idx.isValid():
2016-03-01 11:25:23 +13:00
return None
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
item = idx.internalPointer()
2016-02-07 00:34:22 +13:00
2016-02-29 00:43:23 +13:00
if item.isFolder():
2016-03-01 11:25:23 +13:00
infos["text_type"] = "folder"
2016-02-29 00:43:23 +13:00
else:
2016-03-01 11:25:23 +13:00
infos["text_type"] = "text"
2016-02-07 00:34:22 +13:00
2016-03-01 11:25:23 +13:00
infos["title"] = item.title()
infos["path"] = item.path()
return infos
2016-02-07 00:34:22 +13:00
elif _type == CharacterLetter:
2016-03-01 11:25:23 +13:00
infos["type"] = CharacterLetter
2016-03-01 11:25:23 +13:00
m = mainWindow().mdlCharacter
c = m.getCharacterByID(_ref)
if c:
infos["title"] = c.name()
infos["name"] = c.name()
2016-03-01 11:25:23 +13:00
return infos
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
elif _type == PlotLetter:
2016-03-01 11:25:23 +13:00
infos["type"] = PlotLetter
2015-07-06 19:45:28 +12:00
m = mainWindow().mdlPlots
name = m.getPlotNameByID(_ref)
2015-07-10 22:29:25 +12:00
if name:
2016-03-01 11:25:23 +13:00
infos["title"] = name
return infos
2016-02-07 00:34:22 +13:00
elif _type == WorldLetter:
2016-03-01 11:25:23 +13:00
infos["type"] = WorldLetter
m = mainWindow().mdlWorld
item = m.itemByID(_ref)
if item:
name = item.text()
path = m.path(item)
2016-03-01 11:25:23 +13:00
infos["title"] = name
infos["path"] = path
return infos
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 safeTranslate(qApp, "references", "<b>Unknown reference:</b> {}.").format(ref)
2016-03-01 11:25:23 +13:00
if infos == -1:
return safeTranslate(qApp, "references", "Not a reference: {}.").format(ref)
2016-03-01 11:25:23 +13:00
if infos["type"] == TextLetter:
if infos["text_type"] == "folder":
tt = safeTranslate(qApp, "references", "Folder: <b>{}</b>").format(infos["title"])
2016-03-01 11:25:23 +13:00
else:
tt = safeTranslate(qApp, "references", "Text: <b>{}</b>").format(infos["title"])
2016-03-01 11:25:23 +13:00
tt += "<br><i>{}</i>".format(infos["path"])
return tt
elif infos["type"] == CharacterLetter:
return safeTranslate(qApp, "references", "Character: <b>{}</b>").format(infos["title"])
2016-03-01 11:25:23 +13:00
elif infos["type"] == PlotLetter:
return safeTranslate(qApp, "references", "Plot: <b>{}</b>").format(infos["title"])
2016-02-07 00:34:22 +13:00
2016-03-01 11:25:23 +13:00
elif infos["type"] == WorldLetter:
return safeTranslate(qApp, "references", "World: <b>{name}</b>{path}").format(
2016-03-01 11:25:23 +13:00
name=infos["title"],
path=" <span style='color:gray;'>({})</span>".format(infos["path"]) if infos["path"] else "")
2016-02-07 00:34:22 +13:00
2015-07-03 03:33:05 +12:00
###############################################################################
# FUNCTIONS
###############################################################################
2016-02-07 00:34:22 +13:00
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()
2016-02-07 00:34:22 +13:00
elif _type == CharacterLetter:
m = mainWindow().mdlCharacter
2017-11-21 03:42:30 +13:00
c = m.getCharacterByID(int(_ref))
if c:
text = c.name()
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
elif _type == PlotLetter:
m = mainWindow().mdlPlots
text = m.getPlotNameByID(_ref)
2016-02-07 00:34:22 +13:00
elif _type == WorldLetter:
m = mainWindow().mdlWorld
2017-11-21 03:42:30 +13:00
item = m.itemByID(_ref)
if item:
text = item.text()
2016-02-07 00:34:22 +13:00
2015-06-30 22:27:43 +12:00
if text:
return "<a href='{ref}'>{text}</a>".format(
ref=ref,
text=text)
else:
return ref
2016-02-07 00:34:22 +13:00
2015-06-30 22:27:43 +12:00
def linkifyAllRefs(text):
2016-02-07 00:34:22 +13: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)
2016-02-07 00:34:22 +13:00
def findReferencesTo(ref, parent=None, recursive=True):
"""List of text items containing references ref, and returns IDs.
Starts from item parent. If None, starts from root."""
oM = mainWindow().mdlOutline
if parent == None:
parent = oM.rootItem
# Removes everything after the second ':': '{L:ID:random text}' → '{L:ID:'
ref = ref[:ref.index(":", ref.index(":") + 1)+1]
# Bare form '{L:ID}'
ref2 = ref[:-1] + "}"
# Since it's a simple search (no regex), we search for both.
2017-11-16 08:58:12 +13:00
lst = parent.findItemsContaining(ref, [Outline.notes], recursive=recursive)
lst += parent.findItemsContaining(ref2, [Outline.notes], recursive=recursive)
return lst
def listReferences(ref, title=safeTranslate(qApp, "references", "Referenced in:")):
oM = mainWindow().mdlOutline
listRefs = ""
lst = findReferencesTo(ref)
for t in lst:
idx = oM.getIndexByID(t)
listRefs += "<li><a href='{link}'>{text}</a></li>".format(
2016-02-07 00:34:22 +13:00
link=textReference(t),
2017-11-16 08:58:12 +13:00
text=oM.data(idx, Outline.title))
2016-02-07 00:34:22 +13:00
return "<h2>{title}</h2><ul>{ref}</ul>".format(
2016-02-07 00:34:22 +13:00
title=title,
ref=listRefs) if listRefs else ""
def basicFormat(text):
if not text:
return ""
text = text.replace("\n", "<br>")
text = linkifyAllRefs(text)
return text
2015-07-03 03:33:05 +12:00
def open(ref):
2016-02-07 00:34:22 +13: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
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
_type = match.group(1)
_ref = match.group(2)
2016-02-07 00:34:22 +13:00
if _type == CharacterLetter:
2015-07-06 19:45:28 +12:00
mw = mainWindow()
2016-04-09 01:30:14 +12:00
item = mw.lstCharacters.getItemByID(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if item:
2015-07-10 01:30:59 +12:00
mw.tabMain.setCurrentIndex(mw.TabPersos)
mw.lstCharacters.setCurrentItem(item)
2015-07-06 19:45:28 +12:00
return True
2016-02-07 00:34:22 +13:00
LOGGER.error("Character reference {} not found.".format(ref))
2015-07-06 19:45:28 +12:00
return False
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
elif _type == TextLetter:
mw = mainWindow()
index = mw.mdlOutline.getIndexByID(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if index.isValid():
2015-07-10 01:30:59 +12:00
mw.tabMain.setCurrentIndex(mw.TabRedac)
2015-07-06 19:45:28 +12:00
mw.mainEditor.setCurrentModelIndex(index, newTab=True)
return True
else:
LOGGER.error("Text reference {} not found.".format(ref))
2015-06-27 22:20:05 +12:00
return False
2016-02-07 00:34:22 +13:00
elif _type == PlotLetter:
2015-07-06 19:45:28 +12:00
mw = mainWindow()
item = mw.lstPlots.getItemByID(_ref)
2016-02-07 00:34:22 +13:00
2015-07-06 19:45:28 +12:00
if item:
2015-07-10 01:30:59 +12:00
mw.tabMain.setCurrentIndex(mw.TabPlots)
2015-07-06 19:45:28 +12:00
mw.lstPlots.setCurrentItem(item)
return True
2016-02-07 00:34:22 +13:00
LOGGER.error("Plot reference {} not found.".format(ref))
2015-07-06 19:45:28 +12:00
return False
2016-02-07 00:34:22 +13:00
elif _type == WorldLetter:
mw = mainWindow()
item = mw.mdlWorld.itemByID(_ref)
2016-02-07 00:34:22 +13:00
if item:
2015-07-10 01:30:59 +12:00
mw.tabMain.setCurrentIndex(mw.TabWorld)
mw.treeWorld.setCurrentIndex(
2016-02-07 00:34:22 +13:00
mw.mdlWorld.indexFromItem(item))
return True
2016-02-07 00:34:22 +13:00
LOGGER.error("World reference {} not found.".format(ref))
return False
2016-02-07 00:34:22 +13:00
LOGGER.error("Unable to identify reference type: {}.".format(ref))
2016-02-07 00:34:22 +13:00
return False