manuskript/manuskript/ui/editors/themes.py
2016-02-06 08:38:33 +01:00

280 lines
9.8 KiB
Python

#!/usr/bin/env python
#--!-- coding: utf8 --!--
# Lots of stuff from here comes from the excellet focuswriter.
from qt import *
from enums import *
from functions import *
from ui.views.textEditView import *
import settings
import re
def loadThemeDatas(themeFile):
settings = QSettings(themeFile, QSettings.IniFormat)
_themeData = {}
# Theme name
_themeData["Name"] = getThemeName(themeFile)
# Window Background
loadThemeSetting(_themeData, settings, "Background/Color", "#000000")
loadThemeSetting(_themeData, settings, "Background/ImageFile", "")
loadThemeSetting(_themeData, settings, "Background/Type", 0)
# Text Background
loadThemeSetting(_themeData, settings, "Foreground/Color", "#ffffff")
loadThemeSetting(_themeData, settings, "Foreground/Opacity", 50)
loadThemeSetting(_themeData, settings, "Foreground/Margin", 40)
loadThemeSetting(_themeData, settings, "Foreground/Padding", 10)
loadThemeSetting(_themeData, settings, "Foreground/Position", 1)
loadThemeSetting(_themeData, settings, "Foreground/Rounding", 5)
loadThemeSetting(_themeData, settings, "Foreground/Width", 700)
# Text Options
loadThemeSetting(_themeData, settings, "Text/Color", "#ffffff")
loadThemeSetting(_themeData, settings, "Text/Font", qApp.font().toString())
loadThemeSetting(_themeData, settings, "Text/Misspelled", "#ff0000")
# Paragraph Options
loadThemeSetting(_themeData, settings, "Spacings/IndendFirstLine", False)
loadThemeSetting(_themeData, settings, "Spacings/LineSpacing", 100)
loadThemeSetting(_themeData, settings, "Spacings/ParagraphAbove", 0)
loadThemeSetting(_themeData, settings, "Spacings/ParagraphBelow", 0)
loadThemeSetting(_themeData, settings, "Spacings/TabWidth", 48)
return _themeData
def loadThemeSetting(datas, settings, key, default):
if settings.contains(key):
datas[key] = type(default)(settings.value(key))
else:
datas[key] = default
def getThemeName(theme):
settings = QSettings(theme, QSettings.IniFormat)
if settings.contains("Name"):
return settings.value("Name")
else:
return os.path.splitext(os.path.split(theme)[1])[0]
def themeTextRect(themeDatas, screenRect):
margin = themeDatas["Foreground/Margin"]
x = 0
y = margin
width = min(themeDatas["Foreground/Width"], screenRect.width() - 2 * margin)
height = screenRect.height() - 2 * margin
if themeDatas["Foreground/Position"] == 0: # Left
x = margin
elif themeDatas["Foreground/Position"] == 1: # Center
x = (screenRect.width() - width) / 2
elif themeDatas["Foreground/Position"] == 2: # Right
x = screenRect.width() - margin - width
elif themeDatas["Foreground/Position"] == 3: # Stretched
x = margin
width = screenRect.width() - 2 * margin
return QRect(x, y, width, height)
def createThemePreview(theme, screenRect, size=QSize(200, 120)):
if type(theme) == str and os.path.exists(theme):
# Theme is the path to an ini file
themeDatas = loadThemeDatas(theme)
else:
themeDatas = theme
pixmap = generateTheme(themeDatas, screenRect)
addThemePreviewText(pixmap, themeDatas, screenRect)
px = QPixmap(pixmap).scaled(size, Qt.KeepAspectRatio)
w = px.width() / 10
h = px.height() / 10
r = themeTextRect(themeDatas, screenRect)
painter = QPainter(px)
painter.drawPixmap(QRect(w, h, w*4, h*5), pixmap, QRect(r.topLeft() - QPoint(w/3, h/3), QSize(w*4, h*5)))
painter.setPen(Qt.white)
painter.drawRect(QRect(w, h, w*4, h*5))
painter.end()
return px
def findThemePath(themeName):
p = findFirstFile(re.escape("{}.theme".format(themeName)), "resources/themes")
if not p:
return findFirstFile(".*\.theme", "resources/themes")
else:
return p
def findBackground(filename):
return findFirstFile(re.escape(filename), "resources/backgrounds")
def findFirstFile(regex, path="resources"):
paths = allPaths(path)
for p in paths:
lst = os.listdir(p)
for l in lst:
if re.match(regex, l):
return os.path.join(p, l)
def generateTheme(themeDatas, screenRect):
# Window Background
px = QPixmap(screenRect.size())
px.fill(QColor(themeDatas["Background/Color"]))
painter = QPainter(px)
if themeDatas["Background/ImageFile"]:
path = findBackground(themeDatas["Background/ImageFile"])
_type = themeDatas["Background/Type"]
if path and _type > 0:
if _type == 1: # Tiled
painter.fillRect(screenRect, QBrush(QImage(path)))
else:
img = QImage(path)
scaled = img.size()
if _type == 3: # Stretched
scaled.scale(screenRect.size(), Qt.IgnoreAspectRatio)
elif _type == 4: # Scaled
scaled.scale(screenRect.size(), Qt.KeepAspectRatio)
elif _type == 5: # Zoomed
scaled.scale(screenRect.size(), Qt.KeepAspectRatioByExpanding)
painter.drawImage((screenRect.width() - scaled.width()) / 2, (screenRect.height() - scaled.height()) / 2, img.scaled(scaled))
# Text Background
textRect = themeTextRect(themeDatas, screenRect)
painter.save()
color = QColor(themeDatas["Foreground/Color"])
color.setAlpha(themeDatas["Foreground/Opacity"] * 255 / 100)
painter.setBrush(color)
painter.setPen(Qt.NoPen)
r = themeDatas["Foreground/Rounding"]
painter.drawRoundedRect(textRect, r, r)
painter.restore()
painter.end()
return px
def themeEditorGeometry(themeDatas, textRect):
padding = themeDatas["Foreground/Padding"]
x = textRect.x() + padding
y = textRect.y() + padding + themeDatas["Spacings/ParagraphAbove"]
width = textRect.width() - 2 * padding
height = textRect.height() - 2 * padding - themeDatas["Spacings/ParagraphAbove"]
return x, y, width, height
def getThemeBlockFormat(themeDatas):
bf = QTextBlockFormat()
bf.setLineHeight(themeDatas["Spacings/LineSpacing"], QTextBlockFormat.ProportionalHeight)
bf.setTextIndent(themeDatas["Spacings/TabWidth"] * 1 if themeDatas["Spacings/IndendFirstLine"] else 0)
bf.setTopMargin(themeDatas["Spacings/ParagraphAbove"])
bf.setBottomMargin(themeDatas["Spacings/ParagraphBelow"])
return bf
def setThemeEditorDatas(editor, themeDatas, pixmap, screenRect):
textRect = themeTextRect(themeDatas, screenRect)
x, y, width, height = themeEditorGeometry(themeDatas, textRect)
editor.setGeometry(x, y, width, height)
#p = editor.palette()
##p.setBrush(QPalette.Base, QBrush(pixmap.copy(x, y, width, height)))
#p.setBrush(QPalette.Base, QColor(Qt.transparent))
#p.setColor(QPalette.Text, QColor(themeDatas["Text/Color"]))
#p.setColor(QPalette.Highlight, QColor(themeDatas["Text/Color"]))
#p.setColor(QPalette.HighlightedText, Qt.black if qGray(QColor(themeDatas["Text/Color"]).rgb()) > 127 else Qt.white)
#editor.setPalette(p)
editor.setAttribute(Qt.WA_NoSystemBackground, True)
bf = getThemeBlockFormat(themeDatas)
editor.setDefaultBlockFormat(bf)
#b = editor.document().firstBlock()
#cursor = editor.textCursor()
#cursor.setBlockFormat(bf)
#while b.isValid():
#bf2 = b.blockFormat()
#bf2.merge(bf)
#cursor.setPosition(b.position())
##cursor.setPosition(b.position(), QTextCursor.KeepAnchor)
#cursor.setBlockFormat(bf2)
#b = b.next()
editor.setTabStopWidth(themeDatas["Spacings/TabWidth"])
editor.document().setIndentWidth(themeDatas["Spacings/TabWidth"])
editor.highlighter.setMisspelledColor(QColor(themeDatas["Text/Misspelled"]))
cf = QTextCharFormat()
#f = QFont()
#f.fromString(themeDatas["Text/Font"])
#cf.setFont(f)
editor.highlighter.setDefaultCharFormat(cf)
f = QFont()
f.fromString(themeDatas["Text/Font"])
#editor.setFont(f)
editor.setStyleSheet("""
background: transparent;
color: {foreground};
font-family: {ff};
font-size: {fs};
selection-color: {sc};
selection-background-color: {sbc};
""".format(
foreground=themeDatas["Text/Color"],
ff=f.family(),
fs="{}pt".format(str(f.pointSize())),
sc="black" if qGray(QColor(themeDatas["Text/Color"]).rgb()) > 127 else "white",
sbc=themeDatas["Text/Color"],
)
)
editor._fromTheme = True
def addThemePreviewText(pixmap, themeDatas, screenRect):
# Text
previewText = textEditView(highlighting=True)
previewText.setFrameStyle(QFrame.NoFrame)
previewText.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
previewText.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
f = QFile(appPath("resources/themes/preview.txt"))
f.open(QIODevice.ReadOnly)
previewText.setPlainText(QTextStream(f).readAll())
setThemeEditorDatas(previewText, themeDatas, pixmap, screenRect)
previewText.render(pixmap, previewText.pos())
## Text Background
##themeDatas["Foreground/Color"]
##themeDatas["Foreground/Opacity"]
##themeDatas["Foreground/Margin"]
##themeDatas["Foreground/Padding"]
##themeDatas["Foreground/Position"]
##themeDatas["Foreground/Rounding"]
##themeDatas["Foreground/Width"]
## Text Options
##themeDatas["Text/Color"]
##themeDatas["Text/Font"]
#themeDatas["Text/Misspelled"]
## Paragraph Options
##themeDatas["Spacings/IndendFirstLine"]
##themeDatas["Spacings/LineSpacing"]
##themeDatas["Spacings/ParagraphAbove"]
##themeDatas["Spacings/ParagraphBelow"]
##themeDatas["Spacings/TabWidth"]