manuskript/manuskript/ui/editors/fullScreenEditor.py

341 lines
12 KiB
Python
Raw Normal View History

2015-06-20 04:47:45 +12:00
#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
import os
from PyQt5.QtCore import Qt, QSize, QPoint, QRect, QEvent, QTimer
from PyQt5.QtGui import QFontMetrics, QColor, QBrush, QPalette, QPainter, QPixmap
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QFrame, QWidget, QPushButton, qApp, QStyle, QComboBox, QLabel, QScrollBar, \
QStyleOptionSlider, QHBoxLayout, QVBoxLayout
2015-06-20 04:47:45 +12:00
# Spell checker support
2016-02-07 00:34:22 +13:00
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import allPaths, drawProgress
from manuskript.ui.editors.locker import locker
from manuskript.ui.editors.textFormat import textFormat
from manuskript.ui.editors.themes import findThemePath, generateTheme, setThemeEditorDatas
from manuskript.ui.editors.themes import loadThemeDatas
from manuskript.ui.views.textEditView import textEditView
try:
import enchant
except ImportError:
enchant = None
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
class fullScreenEditor(QWidget):
2015-06-21 10:36:25 +12:00
def __init__(self, index, parent=None):
2015-06-20 04:47:45 +12:00
QWidget.__init__(self, parent)
self._background = None
2015-06-21 10:36:25 +12:00
self._index = index
2015-06-20 04:47:45 +12:00
self._theme = findThemePath(settings.fullScreenTheme)
self._themeDatas = loadThemeDatas(self._theme)
self.setMouseTracking(True)
self._geometries = {}
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
# Text editor
2016-02-07 00:34:22 +13:00
self.editor = textEditView(self,
index=index,
spellcheck=settings.spellcheck,
highlighting=True,
dict=settings.dict)
2015-06-20 04:47:45 +12:00
self.editor.setFrameStyle(QFrame.NoFrame)
self.editor.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.editor.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.editor.installEventFilter(self)
self.editor.setMouseTracking(True)
2015-06-21 07:35:57 +12:00
self.editor.setVerticalScrollBar(myScrollBar())
2015-06-20 04:47:45 +12:00
self.scrollBar = self.editor.verticalScrollBar()
self.scrollBar.setParent(self)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
# Top Panel
2015-06-21 07:35:57 +12:00
self.topPanel = myPanel(parent=self)
2016-02-07 00:34:22 +13:00
# self.topPanel.layout().addStretch(1)
# Spell checking
if enchant:
self.btnSpellCheck = QPushButton(self)
self.btnSpellCheck.setFlat(True)
self.btnSpellCheck.setIcon(QIcon.fromTheme("tools-check-spelling"))
self.btnSpellCheck.setCheckable(True)
self.btnSpellCheck.setChecked(self.editor.spellcheck)
self.btnSpellCheck.toggled.connect(self.editor.toggleSpellcheck)
self.topPanel.layout().addWidget(self.btnSpellCheck)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
self.topPanel.layout().addStretch(1)
2016-02-07 00:34:22 +13:00
# Formatting
self.textFormat = textFormat(self)
self.topPanel.layout().addWidget(self.textFormat)
self.topPanel.layout().addStretch(1)
2016-02-07 00:34:22 +13:00
self.btnClose = QPushButton(self)
self.btnClose.setIcon(qApp.style().standardIcon(QStyle.SP_DialogCloseButton))
self.btnClose.clicked.connect(self.close)
self.btnClose.setFlat(True)
self.topPanel.layout().addWidget(self.btnClose)
2016-02-07 00:34:22 +13:00
# Left Panel
self._locked = False
self.leftPanel = myPanel(vertical=True, parent=self)
self.locker = locker(self)
self.locker.lockChanged.connect(self.setLocked)
self.leftPanel.layout().addWidget(self.locker)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
# Bottom Panel
self.bottomPanel = myPanel(parent=self)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
self.bottomPanel.layout().addSpacing(24)
2015-06-21 07:35:57 +12:00
self.lstThemes = QComboBox(self)
self.lstThemes.setAttribute(Qt.WA_TranslucentBackground)
paths = allPaths("resources/themes")
for p in paths:
lst = [i for i in os.listdir(p) if os.path.splitext(i)[1] == ".theme"]
for t in lst:
themeIni = os.path.join(p, t)
self.lstThemes.addItem(os.path.splitext(t)[0])
2015-06-30 09:44:16 +12:00
self.lstThemes.setCurrentText(settings.fullScreenTheme)
2015-06-21 07:35:57 +12:00
self.lstThemes.currentTextChanged.connect(self.setTheme)
2015-06-21 10:36:25 +12:00
self.lstThemes.setMaximumSize(QSize(300, QFontMetrics(qApp.font()).height()))
self.bottomPanel.layout().addWidget(QLabel(self.tr("Theme:"), self))
self.bottomPanel.layout().addWidget(self.lstThemes)
self.bottomPanel.layout().addStretch(1)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
self.lblProgress = QLabel(self)
self.lblProgress.setMaximumSize(QSize(200, 14))
self.lblProgress.setMinimumSize(QSize(100, 14))
self.lblWC = QLabel(self)
self.bottomPanel.layout().addWidget(self.lblWC)
self.bottomPanel.layout().addWidget(self.lblProgress)
self.updateStatusBar()
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
self.bottomPanel.layout().addSpacing(24)
2016-02-07 00:34:22 +13:00
2015-06-23 20:50:19 +12:00
# Connection
self._index.model().dataChanged.connect(self.dataChanged)
2016-02-07 00:34:22 +13:00
# self.updateTheme()
2015-06-20 04:47:45 +12:00
self.showFullScreen()
2016-02-07 00:34:22 +13:00
# self.showMaximized()
# self.show()
def setLocked(self, val):
self._locked = val
self.btnClose.setVisible(not val)
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def setTheme(self, themeName):
2015-06-21 10:36:25 +12:00
settings.fullScreenTheme = themeName
2015-06-21 07:35:57 +12:00
self._theme = findThemePath(themeName)
2015-06-20 04:47:45 +12:00
self._themeDatas = loadThemeDatas(self._theme)
self.updateTheme()
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def updateTheme(self):
# Reinit stored geometries for hiding widgets
self._geometries = {}
2015-06-20 04:47:45 +12:00
rect = self.geometry()
self._background = generateTheme(self._themeDatas, rect)
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
setThemeEditorDatas(self.editor, self._themeDatas, self._background, rect)
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
# Colors
if self._themeDatas["Foreground/Color"] == self._themeDatas["Background/Color"] or \
2016-02-07 00:34:22 +13:00
self._themeDatas["Foreground/Opacity"] < 5:
self._bgcolor = QColor(self._themeDatas["Text/Color"])
self._fgcolor = QColor(self._themeDatas["Background/Color"])
2015-06-21 07:35:57 +12:00
else:
self._bgcolor = QColor(self._themeDatas["Foreground/Color"])
self._bgcolor.setAlpha(self._themeDatas["Foreground/Opacity"] * 255 / 100)
self._fgcolor = QColor(self._themeDatas["Text/Color"])
2015-06-21 10:36:25 +12:00
if self._themeDatas["Text/Color"] == self._themeDatas["Foreground/Color"]:
self._fgcolor = QColor(self._themeDatas["Background/Color"])
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
# ScrollBar
2015-06-20 04:47:45 +12:00
r = self.editor.geometry()
w = qApp.style().pixelMetric(QStyle.PM_ScrollBarExtent)
r.setWidth(w)
2015-06-21 10:36:25 +12:00
r.moveRight(rect.right() - rect.left())
2015-06-20 04:47:45 +12:00
self.scrollBar.setGeometry(r)
2016-02-07 00:34:22 +13:00
# self.scrollBar.setVisible(False)
self.hideWidget(self.scrollBar)
2015-06-21 02:45:54 +12:00
p = self.scrollBar.palette()
b = QBrush(self._background.copy(self.scrollBar.geometry()))
p.setBrush(QPalette.Base, b)
self.scrollBar.setPalette(p)
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
self.scrollBar.setColor(self._bgcolor)
2016-02-07 00:34:22 +13:00
# Left Panel
r = self.locker.geometry()
r.moveTopLeft(QPoint(
2016-02-07 00:34:22 +13:00
0,
self.geometry().height() / 2 - r.height() / 2
))
self.leftPanel.setGeometry(r)
self.hideWidget(self.leftPanel)
self.leftPanel.setColor(self._bgcolor)
2016-02-07 00:34:22 +13:00
# Top / Bottom Panels
2015-06-21 07:35:57 +12:00
r = QRect(0, 0, 0, 24)
r.setWidth(rect.width())
2016-02-07 00:34:22 +13:00
# r.moveLeft(rect.center().x() - r.width() / 2)
2015-06-21 07:35:57 +12:00
self.topPanel.setGeometry(r)
2016-02-07 00:34:22 +13:00
# self.topPanel.setVisible(False)
self.hideWidget(self.topPanel)
2015-06-21 10:36:25 +12:00
r.moveBottom(rect.bottom() - rect.top())
2015-06-21 07:35:57 +12:00
self.bottomPanel.setGeometry(r)
2016-02-07 00:34:22 +13:00
# self.bottomPanel.setVisible(False)
self.hideWidget(self.bottomPanel)
2015-06-21 07:35:57 +12:00
self.topPanel.setColor(self._bgcolor)
self.bottomPanel.setColor(self._bgcolor)
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
# Lst theme
2016-02-07 00:34:22 +13:00
# p = self.lstThemes.palette()
2015-06-21 10:36:25 +12:00
p = self.palette()
2015-06-21 07:35:57 +12:00
p.setBrush(QPalette.Button, self._bgcolor)
p.setBrush(QPalette.ButtonText, self._fgcolor)
p.setBrush(QPalette.WindowText, self._fgcolor)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
for panel in (self.bottomPanel, self.topPanel):
for i in range(panel.layout().count()):
item = panel.layout().itemAt(i)
2016-02-07 00:34:22 +13:00
if item.widget():
2015-06-21 10:36:25 +12:00
item.widget().setPalette(p)
2016-02-07 00:34:22 +13:00
# self.lstThemes.setPalette(p)
# self.lblWC.setPalette(p)
2015-06-21 07:35:57 +12:00
self.update()
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def paintEvent(self, event):
if self._background:
painter = QPainter(self)
2015-06-21 02:45:54 +12:00
painter.setClipRegion(event.region())
2015-06-20 04:47:45 +12:00
painter.drawPixmap(event.rect(), self._background, event.rect())
painter.end()
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def resizeEvent(self, event):
self.updateTheme()
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def keyPressEvent(self, event):
if event.key() in [Qt.Key_Escape, Qt.Key_F11] and \
2016-02-07 00:34:22 +13:00
not self._locked:
2015-06-20 04:47:45 +12:00
self.close()
else:
QWidget.keyPressEvent(self, event)
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def mouseMoveEvent(self, event):
r = self.geometry()
2016-02-07 00:34:22 +13:00
for w in [self.scrollBar, self.topPanel,
self.bottomPanel, self.leftPanel]:
2016-02-07 00:34:22 +13:00
# w.setVisible(w.geometry().contains(event.pos()))
if self._geometries[w].contains(event.pos()):
self.showWidget(w)
else:
self.hideWidget(w)
2016-02-07 00:34:22 +13:00
def hideWidget(self, widget):
if widget not in self._geometries:
self._geometries[widget] = widget.geometry()
widget.move(self.geometry().bottomRight())
2016-02-07 00:34:22 +13:00
def showWidget(self, widget):
if widget in self._geometries:
widget.move(self._geometries[widget].topLeft())
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def eventFilter(self, obj, event):
2015-06-21 10:36:25 +12:00
if obj == self.editor and event.type() == QEvent.Enter:
2016-02-07 00:34:22 +13:00
for w in [self.scrollBar, self.topPanel,
self.bottomPanel, self.leftPanel]:
2016-02-07 00:34:22 +13:00
# w.setVisible(False)
self.hideWidget(w)
2015-06-20 04:47:45 +12:00
return QWidget.eventFilter(self, obj, event)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
def dataChanged(self, topLeft, bottomRight):
if not self._index:
return
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateStatusBar()
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
def updateStatusBar(self):
if self._index:
item = self._index.internalPointer()
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
wc = item.data(Outline.wordCount.value)
goal = item.data(Outline.goal.value)
pg = item.data(Outline.goalPercentage.value)
2016-02-07 00:34:22 +13:00
2015-06-21 10:36:25 +12:00
if goal:
rect = self.lblProgress.geometry()
rect = QRect(QPoint(0, 0), rect.size())
self.px = QPixmap(rect.size())
self.px.fill(Qt.transparent)
p = QPainter(self.px)
drawProgress(p, rect, pg, 2)
p.end()
self.lblProgress.setPixmap(self.px)
self.lblWC.setText(self.tr("{} words / {}").format(wc, goal))
else:
2015-06-23 20:50:19 +12:00
self.lblProgress.hide()
self.lblWC.setText(self.tr("{} words").format(wc))
2016-02-07 00:34:22 +13:00
self.locker.setWordCount(wc)
if goal and not self.locker.isLocked():
if goal - wc > 0:
self.locker.spnWordTarget.setValue(goal - wc)
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
class myScrollBar(QScrollBar):
def __init__(self, color=Qt.white, parent=None):
QScrollBar.__init__(self, parent)
self._color = color
2016-02-07 00:34:22 +13:00
# self.setAttribute(Qt.WA_TranslucentBackground)
2015-06-21 02:45:54 +12:00
self.timer = QTimer()
2015-06-21 10:36:25 +12:00
self.timer.setInterval(500)
2015-06-21 02:45:54 +12:00
self.timer.setSingleShot(True)
self.timer.timeout.connect(lambda: self.parent().hideWidget(self))
2015-06-21 02:45:54 +12:00
self.valueChanged.connect(lambda v: self.timer.start())
self.valueChanged.connect(lambda: self.parent().showWidget(self))
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
def setColor(self, color):
self._color = color
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def paintEvent(self, event):
opt = QStyleOptionSlider()
self.initStyleOption(opt)
style = qApp.style()
painter = QPainter(self)
2016-02-07 00:34:22 +13:00
2015-06-21 02:45:54 +12:00
# Background (Necessary with Qt 5.2 it seems, not with 5.4)
2016-02-07 00:34:22 +13:00
# painter.save()
# painter.setPen(Qt.NoPen)
# painter.setBrush(self.palette().brush(QPalette.Base))
# painter.drawRect(event.rect())
# painter.restore()
# slider
2015-06-20 04:47:45 +12:00
r = style.subControlRect(style.CC_ScrollBar, opt, style.SC_ScrollBarSlider)
painter.fillRect(r, self._color)
painter.end()
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
class myPanel(QWidget):
def __init__(self, color=Qt.white, vertical=False, parent=None):
2015-06-20 04:47:45 +12:00
QWidget.__init__(self, parent)
self._color = color
self.show()
self.setAttribute(Qt.WA_TranslucentBackground)
if not vertical:
self.setLayout(QHBoxLayout())
else:
self.setLayout(QVBoxLayout())
2015-06-21 07:35:57 +12:00
self.layout().setContentsMargins(0, 0, 0, 0)
2016-02-07 00:34:22 +13:00
2015-06-21 07:35:57 +12:00
def setColor(self, color):
self._color = color
2016-02-07 00:34:22 +13:00
2015-06-20 04:47:45 +12:00
def paintEvent(self, event):
r = event.rect()
painter = QPainter(self)
2016-02-07 00:34:22 +13:00
painter.fillRect(r, self._color)