Ugly but working

This commit is contained in:
Olivier Keshavjee 2016-02-28 12:43:23 +01:00
parent 5d69b46786
commit c8391f771a
4 changed files with 132 additions and 40 deletions

View file

@ -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)

View file

@ -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
###############################################################################

View file

@ -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:

View file

@ -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)