mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-17 11:22:28 +12:00
Ugly but working
This commit is contained in:
parent
5d69b46786
commit
c8391f771a
|
@ -840,8 +840,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.splitterOutlineV.setStretchFactor(0, 75)
|
||||
self.splitterOutlineV.setStretchFactor(1, 25)
|
||||
|
||||
# self.splitterRedacV.setStretchFactor(0, 55)
|
||||
# self.splitterRedacV.setStretchFactor(1, 25)
|
||||
self.splitterRedacV.setStretchFactor(0, 10)
|
||||
self.splitterRedacV.setStretchFactor(1, 100)
|
||||
|
||||
self.splitterRedacH.setStretchFactor(0, 30)
|
||||
self.splitterRedacH.setStretchFactor(1, 40)
|
||||
|
|
|
@ -836,11 +836,19 @@ class outlineItem():
|
|||
|
||||
return lst
|
||||
|
||||
def findItemsContaining(self, text, columns, mainWindow, caseSensitive=False):
|
||||
def findItemsContaining(self, text, columns, mainWindow=mainWindow(), caseSensitive=False):
|
||||
"""Returns a list if IDs of all subitems
|
||||
containing ``text`` in columns ``columns``
|
||||
(being a list of int).
|
||||
"""
|
||||
lst = self.itemContains(text, columns, mainWindow, caseSensitive)
|
||||
|
||||
for c in self.children():
|
||||
lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))
|
||||
|
||||
return lst
|
||||
|
||||
def itemContains(self, text, columns, mainWindow=mainWindow(), caseSensitive=False):
|
||||
lst = []
|
||||
text = text.lower() if not caseSensitive else text
|
||||
for c in columns:
|
||||
|
@ -863,9 +871,6 @@ class outlineItem():
|
|||
if not self.ID() in lst:
|
||||
lst.append(self.ID())
|
||||
|
||||
for c in self.children():
|
||||
lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))
|
||||
|
||||
return lst
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -21,30 +21,47 @@ RegEx = r"{(\w):(\d+):?.*?}"
|
|||
RegExNonCapturing = r"{\w:\d+:?.*?}"
|
||||
# The basic format of the references
|
||||
EmptyRef = "{{{}:{}:{}}}"
|
||||
EmptyRefSearchable = "{{{}:{}:"
|
||||
PersoLetter = "C"
|
||||
TextLetter = "T"
|
||||
PlotLetter = "P"
|
||||
WorldLetter = "W"
|
||||
|
||||
|
||||
def plotReference(ID):
|
||||
"""Takes the ID of a plot and returns a reference for that plot."""
|
||||
return EmptyRef.format(PlotLetter, ID, "")
|
||||
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, "")
|
||||
|
||||
|
||||
def persoReference(ID):
|
||||
"""Takes the ID of a character and returns a reference for that character."""
|
||||
return EmptyRef.format(PersoLetter, ID, "")
|
||||
def persoReference(ID, searchable=False):
|
||||
"""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(PersoLetter, ID, "")
|
||||
else:
|
||||
return EmptyRefSearchable.format(PersoLetter, ID, "")
|
||||
|
||||
|
||||
def textReference(ID):
|
||||
"""Takes the ID of an outline item and returns a reference for that item."""
|
||||
return EmptyRef.format(TextLetter, ID, "")
|
||||
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, "")
|
||||
|
||||
|
||||
def worldReference(ID):
|
||||
"""Takes the ID of a world item and returns a reference for that item."""
|
||||
return EmptyRef.format(WorldLetter, ID, "")
|
||||
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, "")
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
@ -375,7 +392,10 @@ def tooltip(ref):
|
|||
|
||||
item = idx.internalPointer()
|
||||
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
|
||||
if item.isFolder():
|
||||
tt = qApp.translate("references", "Folder: <b>{}</b>").format(item.title())
|
||||
else:
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
|
||||
tt += "<br><i>{}</i>".format(item.path())
|
||||
|
||||
return tt
|
||||
|
@ -454,6 +474,7 @@ def linkifyAllRefs(text):
|
|||
def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
|
||||
oM = mainWindow().mdlOutline
|
||||
listRefs = ""
|
||||
# Removes everything after the second ':': '{L:ID:random text}' → '{L:ID:'
|
||||
ref = ref[:ref.index(":", ref.index(":") + 1)]
|
||||
lst = oM.findItemsContaining(ref, [Outline.notes.value])
|
||||
for t in lst:
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import Qt, QTimer
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics
|
||||
from PyQt5.QtCore import Qt, QTimer, QRectF
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics, QFontMetricsF
|
||||
from PyQt5.QtWidgets import QWidget, QGraphicsScene, QGraphicsSimpleTextItem, QMenu, QAction, QGraphicsRectItem, \
|
||||
QGraphicsLineItem
|
||||
QGraphicsLineItem, QGraphicsEllipseItem
|
||||
|
||||
from manuskript.enums import Outline
|
||||
from manuskript.functions import randomColor
|
||||
from manuskript.models import references
|
||||
from manuskript.ui.views.storylineView_ui import Ui_storylineView
|
||||
|
||||
|
||||
|
@ -58,9 +60,10 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
if not self._mdlPlots or not self._mdlOutline or not self._mdlPersos:
|
||||
pass
|
||||
|
||||
LINE_HEIGHT = 32
|
||||
SPACING = 6
|
||||
LINE_HEIGHT = 18
|
||||
SPACING = 3
|
||||
TEXT_WIDTH = self.sldTxtSize.value()
|
||||
CIRCLE_WIDTH = 10
|
||||
LEVEL_HEIGHT = 12
|
||||
|
||||
s = self.scene
|
||||
|
@ -79,19 +82,22 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
|
||||
MAX_LEVEL = maxLevel(root)
|
||||
|
||||
# Get plots
|
||||
# Generate left entries
|
||||
# (As of now, plot only)
|
||||
plotsID = self._mdlPlots.getPlotsByImportance()
|
||||
plots = []
|
||||
trackedItems = []
|
||||
fm = QFontMetrics(s.font())
|
||||
max_name = 0
|
||||
|
||||
for importance in plotsID:
|
||||
for ID in importance:
|
||||
name = self._mdlPlots.getPlotNameByID(ID)
|
||||
plots.append((ID, name))
|
||||
ref = references.plotReference(ID, searchable=True)
|
||||
|
||||
trackedItems.append((ID, ref, name))
|
||||
max_name = max(fm.width(name), max_name)
|
||||
|
||||
ROWS_HEIGHT = len(plots) * (LINE_HEIGHT + SPACING )
|
||||
ROWS_HEIGHT = len(trackedItems) * (LINE_HEIGHT + SPACING )
|
||||
TITLE_WIDTH = max_name + 2 * SPACING
|
||||
|
||||
|
||||
|
@ -100,21 +106,26 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
s.addItem(outline)
|
||||
outline.setPos(TITLE_WIDTH + SPACING, 0)
|
||||
|
||||
# A Function to add a rect with centered text
|
||||
refCircles = [] # a list of all references, to be added later on the lines
|
||||
|
||||
# A Function to add a rect with centered elided text
|
||||
def addRectText(x, w, parent, text="", level=0, tooltip=""):
|
||||
deltaH = LEVEL_HEIGHT if level else 0
|
||||
r = OutlineRect(0, 0, w, parent.rect().height()-deltaH, parent)
|
||||
r = OutlineRect(0, 0, w, parent.rect().height()-deltaH, parent, title=text)
|
||||
r.setPos(x, deltaH)
|
||||
r.setToolTip(tooltip)
|
||||
|
||||
txt = QGraphicsSimpleTextItem(text, r)
|
||||
f = txt.font()
|
||||
f.setPointSize(8)
|
||||
fm = QFontMetricsF(f)
|
||||
elidedText = fm.elidedText(text, Qt.ElideMiddle, w)
|
||||
txt.setFont(f)
|
||||
txt.setText(elidedText)
|
||||
txt.setPos(r.boundingRect().center() - txt.boundingRect().center())
|
||||
txt.setY(0)
|
||||
return r
|
||||
|
||||
# A function to returns an item's width, by counting its children
|
||||
def itemWidth(item):
|
||||
if item.isFolder():
|
||||
r = 0
|
||||
|
@ -128,11 +139,34 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
delta = 0
|
||||
for child in item.children():
|
||||
w = itemWidth(child)
|
||||
|
||||
if child.isFolder():
|
||||
parent = addRectText(delta, w, rect, child.title(), level, tooltip=child.title())
|
||||
parent.setToolTip(references.tooltip(references.textReference(child.ID())))
|
||||
listItems(child, parent, level + 1)
|
||||
|
||||
else:
|
||||
addRectText(delta, TEXT_WIDTH, rect, "", level, tooltip=child.title())
|
||||
rectChild = addRectText(delta, TEXT_WIDTH, rect, "", level, tooltip=child.title())
|
||||
rectChild.setToolTip(references.tooltip(references.textReference(child.ID())))
|
||||
|
||||
# Find tracked references in that scene (or parent folders)
|
||||
for ID, ref, name in trackedItems:
|
||||
|
||||
result = []
|
||||
c = child
|
||||
while c:
|
||||
result += c.itemContains(ref, [Outline.notes.value])
|
||||
c = c.parent()
|
||||
|
||||
if result:
|
||||
ref2 = result[0]
|
||||
|
||||
# Create a RefCircle with the reference
|
||||
c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2)
|
||||
|
||||
# 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())))
|
||||
|
||||
delta += w
|
||||
|
||||
listItems(root, outline)
|
||||
|
@ -144,7 +178,7 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
itemsRect = s.addRect(0, 0, 0, 0)
|
||||
itemsRect.setPos(0, MAX_LEVEL * LEVEL_HEIGHT + SPACING)
|
||||
|
||||
for ID, name in plots:
|
||||
for ID, ref, name in trackedItems:
|
||||
color = randomColor()
|
||||
|
||||
# Rect
|
||||
|
@ -159,31 +193,63 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
txt.setPos(r.boundingRect().center() - txt.boundingRect().center())
|
||||
|
||||
# Line
|
||||
line = PlotLine(TITLE_WIDTH,
|
||||
r.mapToScene(r.rect().center()).y(),
|
||||
OUTLINE_WIDTH + TITLE_WIDTH + SPACING,
|
||||
r.mapToScene(r.rect().center()).y())
|
||||
line = PlotLine(0, 0,
|
||||
OUTLINE_WIDTH + SPACING, 0)
|
||||
line.setPos(TITLE_WIDTH, r.mapToScene(r.rect().center()).y())
|
||||
s.addItem(line)
|
||||
line.setPen(QPen(color, 5))
|
||||
line.setToolTip(self.tr("Plot: ") + name)
|
||||
|
||||
# We add the circles / references to text, on the line
|
||||
for ref2, circle, pos in refCircles:
|
||||
if ref2 == ref:
|
||||
circle.setParentItem(line)
|
||||
circle.setPos(pos.x(), 0)
|
||||
|
||||
# self.view.fitInView(0, 0, TOTAL_WIDTH, i * LINE_HEIGHT, Qt.KeepAspectRatioByExpanding) # KeepAspectRatio
|
||||
self.view.setSceneRect(0, 0, 0, 0)
|
||||
|
||||
|
||||
class OutlineRect(QGraphicsRectItem):
|
||||
def __init__(self, x, y, w, h, parent=None):
|
||||
def __init__(self, x, y, w, h, parent=None, title=None):
|
||||
QGraphicsRectItem.__init__(self, x, y, w, h, parent)
|
||||
self.setBrush(Qt.white)
|
||||
self.setAcceptHoverEvents(True)
|
||||
self._title = title
|
||||
|
||||
def hoverEnterEvent(self, QGraphicsSceneHoverEvent):
|
||||
def hoverEnterEvent(self, event):
|
||||
self.setBrush(Qt.lightGray)
|
||||
|
||||
def hoverLeaveEvent(self, QGraphicsSceneHoverEvent):
|
||||
def hoverLeaveEvent(self, event):
|
||||
self.setBrush(Qt.white)
|
||||
|
||||
|
||||
class RefCircle(QGraphicsEllipseItem):
|
||||
def __init__(self, x, y, diameter, parent=None, ID=None):
|
||||
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)
|
||||
|
||||
def multiplyDiameter(self, factor):
|
||||
r1 = self.rect()
|
||||
r2 = QRectF(0, 0, r1.width() * factor, r1.height() * factor)
|
||||
self.setRect(r2)
|
||||
self.setPos(self.pos() + r1.center() - r2.center())
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
print("Good News!", self._ref)
|
||||
references.open(self._ref)
|
||||
|
||||
def hoverEnterEvent(self, event):
|
||||
self.multiplyDiameter(2)
|
||||
|
||||
def hoverLeaveEvent(self, event):
|
||||
self.multiplyDiameter(.5)
|
||||
|
||||
|
||||
class PlotLine(QGraphicsLineItem):
|
||||
def __init__(self, x1, y1, x2, y2, parent=None):
|
||||
QGraphicsLineItem.__init__(self, x1, y1, x2, y2, parent)
|
||||
|
|
Loading…
Reference in a new issue