manuskript/manuskript/ui/views/corkDelegate.py

571 lines
21 KiB
Python
Raw Normal View History

#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
2017-10-15 04:11:17 +13:00
from PyQt5.QtCore import QSize, Qt, QRect, QPoint, QPointF
from PyQt5.QtGui import QMouseEvent, QFont, QPalette, QRegion, QFontMetrics, QColor, QIcon, QPolygonF
2016-02-07 00:34:22 +13:00
from PyQt5.QtWidgets import QStyledItemDelegate, QLineEdit, QPlainTextEdit, QFrame, qApp, QStyle
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import colorifyPixmap
from manuskript.functions import mainWindow
from manuskript.functions import mixColors
from manuskript.functions import outlineItemColors
class corkDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
2015-06-30 09:41:13 +12:00
self.factor = settings.corkSizeFactor / 100.
self.lastPos = None
self.editing = None
self.margin = 5
2016-02-07 00:34:22 +13:00
2017-10-15 04:11:17 +13:00
def newStyle(self):
return settings.corkStyle == "new"
def setCorkSizeFactor(self, v):
self.factor = v / 100.
2016-02-07 00:34:22 +13:00
def sizeHint(self, option, index):
2017-10-15 04:11:17 +13:00
if self.newStyle():
defaultSize = QSize(300, 210)
else:
defaultSize = QSize(300, 200)
return defaultSize * self.factor
2016-02-07 00:34:22 +13:00
def editorEvent(self, event, model, option, index):
# We catch the mouse position in the widget to know which part to edit
if type(event) == QMouseEvent:
2016-02-07 00:34:22 +13:00
self.lastPos = event.pos() # - option.rect.topLeft()
return QStyledItemDelegate.editorEvent(self, event, model, option, index)
2016-02-07 00:34:22 +13:00
def createEditor(self, parent, option, index):
self.updateRects(option, index)
2016-02-07 00:34:22 +13:00
if self.mainLineRect.contains(self.lastPos):
# One line summary
self.editing = Outline.summarySentence
edt = QLineEdit(parent)
edt.setFocusPolicy(Qt.StrongFocus)
edt.setFrame(False)
f = QFont(option.font)
2017-10-15 04:11:17 +13:00
if self.newStyle():
f.setBold(True)
else:
f.setItalic(True)
edt.setAlignment(Qt.AlignCenter)
edt.setPlaceholderText(self.tr("One line summary"))
edt.setFont(f)
return edt
2016-02-07 00:34:22 +13:00
elif self.titleRect.contains(self.lastPos):
# Title
self.editing = Outline.title
edt = QLineEdit(parent)
edt.setFocusPolicy(Qt.StrongFocus)
edt.setFrame(False)
f = QFont(option.font)
2017-10-15 04:11:17 +13:00
if self.newStyle():
f.setPointSize(f.pointSize() + 4)
else:
edt.setAlignment(Qt.AlignCenter)
f.setBold(True)
edt.setFont(f)
2016-02-07 00:34:22 +13:00
# edt.setGeometry(self.titleRect)
return edt
2016-02-07 00:34:22 +13:00
else: # self.mainTextRect.contains(self.lastPos):
# Summary
self.editing = Outline.summaryFull
edt = QPlainTextEdit(parent)
edt.setFocusPolicy(Qt.StrongFocus)
edt.setFrameShape(QFrame.NoFrame)
2016-03-02 21:57:43 +13:00
try:
# QPlainTextEdit.setPlaceholderText was introduced in Qt 5.3
edt.setPlaceholderText(self.tr("Full summary"))
except AttributeError:
pass
return edt
2016-02-07 00:34:22 +13:00
def updateEditorGeometry(self, editor, option, index):
2016-02-07 00:34:22 +13:00
if self.editing == Outline.summarySentence:
# One line summary
editor.setGeometry(self.mainLineRect)
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.title:
# Title
editor.setGeometry(self.titleRect)
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.summaryFull:
# Summary
editor.setGeometry(self.mainTextRect)
2016-02-07 00:34:22 +13:00
def setEditorData(self, editor, index):
item = index.internalPointer()
2016-02-07 00:34:22 +13:00
if self.editing == Outline.summarySentence:
# One line summary
editor.setText(item.data(Outline.summarySentence.value))
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.title:
# Title
editor.setText(index.data())
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.summaryFull:
# Summary
editor.setPlainText(item.data(Outline.summaryFull.value))
2016-02-07 00:34:22 +13:00
def setModelData(self, editor, model, index):
2016-02-07 00:34:22 +13:00
if self.editing == Outline.summarySentence:
# One line summary
model.setData(index.sibling(index.row(), Outline.summarySentence.value), editor.text())
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.title:
# Title
model.setData(index, editor.text(), Outline.title.value)
2016-02-07 00:34:22 +13:00
elif self.editing == Outline.summaryFull:
# Summary
model.setData(index.sibling(index.row(), Outline.summaryFull.value), editor.toPlainText())
2016-02-07 00:34:22 +13:00
def updateRects(self, option, index):
2017-10-15 04:11:17 +13:00
if self.newStyle():
self.updateRects_v2(option, index)
else:
self.updateRects_v1(option, index)
def updateRects_v2(self, option, index):
margin = self.margin * 2
iconSize = max(24 * self.factor, 18)
item = index.internalPointer()
fm = QFontMetrics(option.font)
h = fm.lineSpacing()
2017-10-15 04:11:17 +13:00
self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin)
2017-10-15 04:11:17 +13:00
top = 15 * self.factor
self.topRect = QRect(self.itemRect)
self.topRect.setHeight(top)
2017-10-15 04:11:17 +13:00
self.cardRect = QRect(self.itemRect.topLeft() + QPoint(0, top),
self.itemRect.bottomRight())
self.iconRect = QRect(self.cardRect.topLeft() + QPoint(margin, margin),
QSize(iconSize, iconSize))
self.labelRect = QRect(self.cardRect.topRight() - QPoint(margin + self.factor * 18, 1),
self.cardRect.topRight() + QPoint(- margin - self.factor * 4, self.factor * 24))
self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
self.labelRect.bottomLeft() - QPoint(margin, margin))
self.titleRect.setBottom(self.iconRect.bottom())
self.mainRect = QRect(self.iconRect.bottomLeft() + QPoint(0, margin),
self.cardRect.bottomRight() - QPoint(margin, 2*margin))
self.mainRect.setLeft(self.titleRect.left())
self.mainLineRect = QRect(self.mainRect.topLeft(),
self.mainRect.topRight() + QPoint(0, h))
self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
self.mainRect.bottomRight())
if not item.data(Outline.summarySentence.value):
self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())
2017-10-15 04:11:17 +13:00
def updateRects_v1(self, option, index):
margin = self.margin
2016-02-07 00:34:22 +13:00
iconSize = max(16 * self.factor, 12)
item = index.internalPointer()
self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin)
self.iconRect = QRect(self.itemRect.topLeft() + QPoint(margin, margin), QSize(iconSize, iconSize))
2015-06-10 08:05:03 +12:00
self.labelRect = QRect(self.itemRect.topRight() - QPoint(iconSize + margin, 0),
self.itemRect.topRight() + QPoint(0, iconSize + 2 * margin))
self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
self.labelRect.bottomLeft() - QPoint(margin, margin))
2016-02-07 00:34:22 +13:00
self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin),
2015-06-10 08:05:03 +12:00
QPoint(self.itemRect.right(), self.itemRect.bottom()))
self.topRect = QRect(self.itemRect.topLeft(), self.bottomRect.topRight())
self.mainRect = self.bottomRect.adjusted(margin, margin, -margin, -margin)
self.mainLineRect = QRect(self.mainRect.topLeft(),
self.mainRect.topRight() + QPoint(0, iconSize))
self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
self.mainRect.bottomRight())
if not item.data(Outline.summarySentence.value):
self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())
2016-04-12 01:21:49 +12:00
if item.data(Outline.label.value) in ["", "0", 0]:
2015-06-10 08:05:03 +12:00
self.titleRect.setBottomRight(self.labelRect.bottomRight() - QPoint(self.margin, self.margin))
2016-02-07 00:34:22 +13:00
def paint(self, p, option, index):
2017-10-15 04:11:17 +13:00
if self.newStyle():
self.paint_v2(p, option, index)
else:
self.paint_v1(p, option, index)
2017-10-15 04:11:17 +13:00
def paint_v2(self, p, option, index):
# QStyledItemDelegate.paint(self, p, option, index)
if not index.isValid():
return
item = index.internalPointer()
self.updateRects(option, index)
colors = outlineItemColors(item)
style = qApp.style()
def _rotate(angle):
p.translate(self.mainRect.center())
p.rotate(angle)
p.translate(-self.mainRect.center())
2017-10-15 04:11:17 +13:00
def drawRect(r):
p.save()
p.setBrush(Qt.gray)
p.drawRect(r)
p.restore()
# Draw background
cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled)
if cg == QPalette.Normal and not option.state & QStyle.State_Active:
cg = QPalette.Inactive
# Selection
if option.state & QStyle.State_Selected:
p.save()
p.setBrush(option.palette.brush(cg, QPalette.Highlight))
p.setPen(Qt.NoPen)
#p.drawRoundedRect(option.rect, 12, 12)
p.drawRect(option.rect)
p.restore()
# Background
p.save()
if settings.viewSettings["Cork"]["Background"] != "Nothing":
c = colors[settings.viewSettings["Cork"]["Background"]]
if c == QColor(Qt.transparent):
c = QColor(Qt.white)
col = mixColors(c, QColor(Qt.white), .2)
p.setBrush(col)
else:
p.setBrush(Qt.white)
2017-10-15 04:11:17 +13:00
p.setPen(Qt.NoPen)
p.drawRect(self.cardRect)
if item.isFolder():
itemPoly = QPolygonF([
self.topRect.topLeft(),
self.topRect.topLeft() + QPoint(self.topRect.width() * .35, 0),
self.cardRect.topLeft() + QPoint(self.topRect.width() * .45, 0),
self.cardRect.topRight(),
self.cardRect.bottomRight(),
self.cardRect.bottomLeft()
])
p.drawPolygon(itemPoly)
p.restore()
# Label color
if settings.viewSettings["Cork"]["Corner"] != "Nothing":
p.save()
color = colors[settings.viewSettings["Cork"]["Corner"]]
p.setPen(Qt.NoPen)
p.setBrush(color)
p.drawRect(self.labelRect)
w = self.labelRect.width()
poly = QPolygonF([
self.labelRect.bottomLeft() + QPointF(0, 1),
self.labelRect.bottomLeft() + QPointF(0, w / 2),
self.labelRect.bottomLeft() + QPointF(w / 2, 1),
self.labelRect.bottomRight() + QPointF(1, w / 2),
self.labelRect.bottomRight() + QPointF(1, 1),
])
p.drawPolygon(poly)
2017-10-15 04:11:17 +13:00
p.restore()
2017-10-15 04:11:17 +13:00
if settings.viewSettings["Cork"]["Corner"] == "Nothing" or \
color == Qt.transparent:
# No corner, so title can be full width
self.titleRect.setRight(self.mainRect.right())
# Draw the icon
iconRect = self.iconRect
mode = QIcon.Normal
if not option.state & style.State_Enabled:
mode = QIcon.Disabled
elif option.state & style.State_Selected:
mode = QIcon.Selected
# index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
if settings.viewSettings["Cork"]["Icon"] != "Nothing":
color = colors[settings.viewSettings["Cork"]["Icon"]]
colorifyPixmap(icon, color)
QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)
# Draw title
p.save()
text = index.data()
2017-10-15 04:11:17 +13:00
if text:
p.setPen(Qt.black)
2017-10-15 04:11:17 +13:00
if settings.viewSettings["Cork"]["Text"] != "Nothing":
col = colors[settings.viewSettings["Cork"]["Text"]]
if col == Qt.transparent:
col = Qt.black
p.setPen(col)
f = QFont(option.font)
f.setPointSize(f.pointSize() + 4)
f.setBold(True)
p.setFont(f)
fm = QFontMetrics(f)
elidedText = fm.elidedText(text, Qt.ElideRight, self.titleRect.width())
p.drawText(self.titleRect, Qt.AlignLeft | Qt.AlignVCenter, elidedText)
p.restore()
# One line summary background
lineSummary = item.data(Outline.summarySentence.value)
fullSummary = item.data(Outline.summaryFull.value)
# Border
if settings.viewSettings["Cork"]["Border"] != "Nothing":
p.save()
p.setBrush(Qt.NoBrush)
pen = p.pen()
pen.setWidth(2)
col = colors[settings.viewSettings["Cork"]["Border"]]
pen.setColor(col)
p.setPen(pen)
if item.isFolder():
p.drawPolygon(itemPoly)
else:
p.drawRect(self.cardRect)
p.restore()
# Draw status
status = item.data(Outline.status.value)
if status:
it = mainWindow().mdlStatus.item(int(status), 0)
if it != None:
p.save()
2017-10-16 01:58:51 +13:00
p.setClipRegion(QRegion(self.cardRect))
2017-10-15 04:11:17 +13:00
f = p.font()
f.setPointSize(f.pointSize() + 12)
f.setBold(True)
p.setFont(f)
p.setPen(QColor(Qt.red).lighter(170))
_rotate(-35)
p.drawText(self.cardRect, Qt.AlignCenter, it.text())
p.restore()
# Draw Summary
# One line
if lineSummary:
p.save()
f = QFont(option.font)
f.setBold(True)
p.setFont(f)
p.setPen(Qt.black)
2017-10-15 04:11:17 +13:00
fm = QFontMetrics(f)
elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
p.drawText(self.mainLineRect, Qt.AlignLeft | Qt.AlignVCenter, elidedText)
p.restore()
# Full summary
if fullSummary:
p.save()
2017-10-15 04:11:17 +13:00
p.setFont(option.font)
p.setPen(Qt.black)
2017-10-15 04:11:17 +13:00
p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
p.restore()
2017-10-15 04:11:17 +13:00
def paint_v1(self, p, option, index):
2016-02-07 00:34:22 +13:00
# QStyledItemDelegate.paint(self, p, option, index)
if not index.isValid():
return
2016-02-07 00:34:22 +13:00
item = index.internalPointer()
self.updateRects(option, index)
2015-06-16 09:15:10 +12:00
colors = outlineItemColors(item)
2016-02-07 00:34:22 +13:00
style = qApp.style()
2016-02-07 00:34:22 +13:00
def _rotate(angle):
p.translate(self.mainRect.center())
p.rotate(angle)
p.translate(-self.mainRect.center())
2016-02-07 00:34:22 +13:00
# Draw background
cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled)
if cg == QPalette.Normal and not option.state & QStyle.State_Active:
cg = QPalette.Inactive
2016-02-07 00:34:22 +13:00
# Selection
if option.state & QStyle.State_Selected:
p.save()
p.setBrush(option.palette.brush(cg, QPalette.Highlight))
p.setPen(Qt.NoPen)
p.drawRoundedRect(option.rect, 12, 12)
p.restore()
2016-02-07 00:34:22 +13:00
# Stack
if item.isFolder() and item.childCount() > 0:
p.save()
p.setBrush(Qt.white)
for i in reversed(range(3)):
2016-02-07 00:34:22 +13:00
p.drawRoundedRect(self.itemRect.adjusted(2 * i, 2 * i, -2 * i, 2 * i), 10, 10)
p.restore()
2016-02-07 00:34:22 +13:00
# Background
itemRect = self.itemRect
p.save()
2015-06-16 09:15:10 +12:00
if settings.viewSettings["Cork"]["Background"] != "Nothing":
c = colors[settings.viewSettings["Cork"]["Background"]]
col = mixColors(c, QColor(Qt.white), .2)
p.setBrush(col)
else:
p.setBrush(Qt.white)
pen = p.pen()
pen.setWidth(2)
p.setPen(pen)
p.drawRoundedRect(itemRect, 10, 10)
p.restore()
2016-02-07 00:34:22 +13:00
# Title bar
topRect = self.topRect
p.save()
if item.isFolder():
color = QColor(Qt.darkGreen)
else:
color = QColor(Qt.blue).lighter(175)
p.setPen(Qt.NoPen)
p.setBrush(color)
p.setClipRegion(QRegion(topRect))
p.drawRoundedRect(itemRect, 10, 10)
2016-02-07 00:34:22 +13:00
# p.drawRect(topRect)
p.restore()
2016-02-07 00:34:22 +13:00
# Label color
2015-06-16 09:15:10 +12:00
if settings.viewSettings["Cork"]["Corner"] != "Nothing":
p.save()
color = colors[settings.viewSettings["Cork"]["Corner"]]
p.setPen(Qt.NoPen)
p.setBrush(color)
p.setClipRegion(QRegion(self.labelRect))
p.drawRoundedRect(itemRect, 10, 10)
2016-02-07 00:34:22 +13:00
# p.drawRect(topRect)
2015-06-16 09:15:10 +12:00
p.restore()
2016-04-12 01:21:49 +12:00
if color != Qt.transparent:
p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())
2016-02-07 00:34:22 +13:00
# One line summary background
lineSummary = item.data(Outline.summarySentence.value)
fullSummary = item.data(Outline.summaryFull.value)
if lineSummary or not fullSummary:
m = self.margin
2016-02-07 00:34:22 +13:00
r = self.mainLineRect.adjusted(-m, -m, m, m / 2)
p.save()
p.setPen(Qt.NoPen)
p.setBrush(QColor("#EEE"))
p.drawRect(r)
p.restore()
2016-02-07 00:34:22 +13:00
# Border
p.save()
p.setBrush(Qt.NoBrush)
pen = p.pen()
pen.setWidth(2)
2015-06-16 09:15:10 +12:00
if settings.viewSettings["Cork"]["Border"] != "Nothing":
col = colors[settings.viewSettings["Cork"]["Border"]]
if col == Qt.transparent:
col = Qt.black
pen.setColor(col)
p.setPen(pen)
p.drawRoundedRect(itemRect, 10, 10)
p.restore()
2016-02-07 00:34:22 +13:00
# Draw the icon
iconRect = self.iconRect
mode = QIcon.Normal
if not option.state & style.State_Enabled:
mode = QIcon.Disabled
elif option.state & style.State_Selected:
mode = QIcon.Selected
2016-02-07 00:34:22 +13:00
# index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
2015-06-16 09:15:10 +12:00
icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
if settings.viewSettings["Cork"]["Icon"] != "Nothing":
color = colors[settings.viewSettings["Cork"]["Icon"]]
colorifyPixmap(icon, color)
QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)
2016-02-07 00:34:22 +13:00
# Draw title
p.save()
text = index.data()
titleRect = self.titleRect
if text:
2015-06-16 09:15:10 +12:00
if settings.viewSettings["Cork"]["Text"] != "Nothing":
col = colors[settings.viewSettings["Cork"]["Text"]]
if col == Qt.transparent:
col = Qt.black
p.setPen(col)
f = QFont(option.font)
2016-02-07 00:34:22 +13:00
# f.setPointSize(f.pointSize() + 1)
f.setBold(True)
p.setFont(f)
fm = QFontMetrics(f)
elidedText = fm.elidedText(text, Qt.ElideRight, titleRect.width())
p.drawText(titleRect, Qt.AlignCenter, elidedText)
p.restore()
2016-02-07 00:34:22 +13:00
# Draw the line
bottomRect = self.bottomRect
p.save()
2016-02-07 00:34:22 +13:00
# p.drawLine(itemRect.x(), iconRect.bottom() + margin,
# itemRect.right(), iconRect.bottom() + margin)
p.drawLine(bottomRect.topLeft(), bottomRect.topRight())
p.restore()
2016-02-07 00:34:22 +13:00
# Lines
2015-06-09 22:32:43 +12:00
if True:
p.save()
p.setPen(QColor("#EEE"))
fm = QFontMetrics(option.font)
h = fm.lineSpacing()
l = self.mainTextRect.topLeft() + QPoint(0, h)
while self.mainTextRect.contains(l):
p.drawLine(l, QPoint(self.mainTextRect.right(), l.y()))
l.setY(l.y() + h)
p.restore()
2016-02-07 00:34:22 +13:00
# Draw status
mainRect = self.mainRect
status = item.data(Outline.status.value)
if status:
2015-06-11 01:57:44 +12:00
it = mainWindow().mdlStatus.item(int(status), 0)
if it != None:
p.save()
p.setClipRegion(QRegion(mainRect))
f = p.font()
f.setPointSize(f.pointSize() + 12)
f.setBold(True)
p.setFont(f)
p.setPen(QColor(Qt.red).lighter(175))
_rotate(-35)
p.drawText(mainRect, Qt.AlignCenter, it.text())
p.restore()
2016-02-07 00:34:22 +13:00
# Draw Summary
# One line
if lineSummary:
p.save()
f = QFont(option.font)
f.setItalic(True)
p.setFont(f)
fm = QFontMetrics(f)
elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText)
p.restore()
2016-02-07 00:34:22 +13:00
# Full summary
if fullSummary:
p.setFont(option.font)
p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
2016-02-07 00:34:22 +13:00
# Debug
# for r in [self.itemRect, self.iconRect, self.titleRect, self.bottomRect, self.mainLineRect, self.mainTextRect]:
# p.drawRect(r)