Cleaning up imports, at last

This commit is contained in:
Olivier Keshavjee 2016-02-06 12:34:22 +01:00
parent 9f0f60067a
commit 69e0ca93be
83 changed files with 3189 additions and 3032 deletions

View file

@ -1,4 +1,4 @@
UI := $(wildcard src/ui/*.ui) $(wildcard src/ui/*/*.ui) $(wildcard src/ui/*.qrc)
UI := $(wildcard manuskript/ui/*.ui) $(wildcard manuskript/ui/*/*.ui) $(wildcard manuskript/ui/*.qrc)
UIs= $(UI:.ui=.py) $(UI:.qrc=_rc.py)
TS := $(wildcard i18n/*.ts)
QMs= $(TS:.ts=.qm)
@ -6,22 +6,23 @@ QMs= $(TS:.ts=.qm)
ui: $(UIs)
run: $(UIs)
python3 src/main.py
# python3 manuskript/main.py
bin/manuskript
debug: $(UIs)
gdb --args python3 src/main.py
gdb --args python3 manuskript/main.py
lineprof:
kernprof -l -v src/main.py
kernprof -l -v manuskript/main.py
profile:
python3 -m cProfile -s 'cumtime' src/main.py | more
python3 -m cProfile -s 'cumtime' manuskript/main.py | more
compile:
cd src && python3 setup.py build_ext --inplace
cd manuskript && python3 setup.py build_ext --inplace
callgraph:
cd src; pycallgraph myoutput -- main.py
cd manuskript; pycallgraph myoutput -- main.py
translation:
pylupdate5 -noobsolete i18n/manuskript.pro

View file

@ -1,31 +1,32 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
import collections
from qt import *
from .html import htmlExporter
from .arbo import arboExporter
from .odt import odtExporter
from PyQt5.QtWidgets import qApp
from manuskript.exporter.arbo import arboExporter
from manuskript.exporter.html import htmlExporter
from manuskript.exporter.odt import odtExporter
formats = collections.OrderedDict([
#Format
# Readable name
# Class
# QFileDialog filter
# Format
# Readable name
# Class
# QFileDialog filter
('html', (
qApp.translate("exporter", "HTML"),
qApp.translate("exporter", "HTML"),
htmlExporter,
qApp.translate("exporter", "HTML Document (*.html)"))),
('arbo', (
qApp.translate("exporter", "Arborescence"),
qApp.translate("exporter", "Arborescence"),
arboExporter,
None)),
('odt', (
qApp.translate("exporter", "OpenDocument (LibreOffice)"),
('odt', (
qApp.translate("exporter", "OpenDocument (LibreOffice)"),
odtExporter,
qApp.translate("exporter", "OpenDocument (*.odt)"))),
('epub', (
"ePub (not yet)",
"ePub (not yet)",
None,
None)),
])
])

View file

@ -1,53 +1,48 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
import os
from manuskript.functions import mainWindow
class arboExporter():
requires = ["path"]
def __init__(self):
pass
def doCompile(self, path):
#FIXME: overwrites when items have identical names
# FIXME: overwrites when items have identical names
mw = mainWindow()
root = mw.mdlOutline.rootItem
def writeItem(item, path):
if item.isFolder():
path2 = os.path.join(path, item.title())
try:
os.mkdir(path2)
except FileExistsError:
pass
for c in item.children():
writeItem(c, path2)
else:
ext = ".t2t" if item.isT2T() else \
".html" if item.isHTML() else \
".txt"
".html" if item.isHTML() else \
".txt"
path2 = os.path.join(path, item.title() + ext)
f = open(path2, "w")
text = self.formatText(item.text(), item.type())
f.write(text)
for c in root.children():
writeItem(c, path)
def formatText(self, text, _type):
if _type == "t2t":
# Empty lines for headers
text = "\n\n\n" + text
return text

View file

@ -1,31 +1,28 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import subprocess
# --!-- coding: utf8 --!--
import re
import subprocess
class basicExporter():
def __init__(self):
pass
def runT2T(self, text, target="html"):
cmdl = ['txt2tags', '-t', target, '--enc=utf-8', '--no-headers', '-o', '-', '-']
cmd = subprocess.Popen(('echo', text), stdout=subprocess.PIPE)
try:
output = subprocess.check_output(cmdl, stdin=cmd.stdout, stderr=subprocess.STDOUT) # , cwd="/tmp"
output = subprocess.check_output(cmdl, stdin=cmd.stdout, stderr=subprocess.STDOUT) # , cwd="/tmp"
except subprocess.CalledProcessError as e:
print("Error!")
return text
cmd.wait()
return output.decode("utf-8")
def htmlBody(self, text):
text = text.replace("\n", "")
text = re.sub(r".*<body[^>]*?>(.*)</body>.*", "\\1", text)

View file

@ -1,45 +1,41 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from exporter.basic import basicExporter
# --!-- coding: utf8 --!--
from manuskript.exporter.basic import basicExporter
from manuskript.functions import mainWindow
class htmlExporter(basicExporter):
requires = ["filename"]
def __init__(self):
pass
def doCompile(self, filename):
mw = mainWindow()
root = mw.mdlOutline.rootItem
html = ""
def appendItem(item):
if item.isFolder():
html = ""
title = "<h{l}>{t}</h{l}>\n".format(
l = str(item.level() + 1),
t = item.title())
l=str(item.level() + 1),
t=item.title())
html += title
for c in item.children():
html += appendItem(c)
return html
else:
text = self.formatText(item.text(), item.type())
return text
for c in root.children():
html += appendItem(c)
template = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
@ -51,25 +47,25 @@ class htmlExporter(basicExporter):
{BODY}
</body>
</html>"""
f = open(filename, "w")
f.write(template.format(
TITLE="FIXME",
BODY=html))
TITLE="FIXME",
BODY=html))
def formatText(self, text, _type):
if not text:
return text
if _type == "t2t":
text = self.runT2T(text)
elif _type == "txt":
text = text.replace("\n", "<br>")
elif _type == "html":
# keep only body
text = self.htmlBody(text)
return text + "<br>"

View file

@ -1,75 +1,74 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from exporter.basic import basicExporter
# --!-- coding: utf8 --!--
import os
import sys
from PyQt5.QtGui import QTextDocument
from libs.odf.opendocument import OpenDocumentText
from libs.odf.text import H, P
from manuskript.exporter.basic import basicExporter
from manuskript.functions import appPath
from manuskript.functions import mainWindow
import sys, os
sys.path.append(os.path.join(appPath(), "libs"))
from odf.opendocument import OpenDocumentText
from odf.style import Style, TextProperties
from odf.text import H, P, Span
class odtExporter(basicExporter):
requires = ["filename"]
def __init__(self):
pass
def doCompile(self, filename):
mw = mainWindow()
root = mw.mdlOutline.rootItem
doc = OpenDocumentText()
def appendItem(item):
if item.isFolder():
self.addHeading(item.title(), item.level() + 1, doc)
for c in item.children():
appendItem(c)
else:
text = self.formatText(item.text(), item.type())
if text:
for l in text.split("\n"):
self.addParagraph(l, doc)
for c in root.children():
appendItem(c)
doc.save(filename)
def formatText(self, text, _type):
if not text:
return text
#if _type == "t2t":
#text = self.runT2T(text)
#elif _type == "txt":
#text = text.replace("\n", "<br>")
# if _type == "t2t":
# text = self.runT2T(text)
# elif _type == "txt":
# text = text.replace("\n", "<br>")
elif _type == "html":
doc = QTextDocument()
doc.setHtml(text)
text = doc.toPlainText()
#text = self.htmlBody(text)
# text = self.htmlBody(text)
return text
def addHeading(self, text, level, doc):
doc.text.addElement(H(outlinelevel=int(level), text=text))
return doc
def addParagraph(self, text, doc):
p = P(stylename="Text Body", text=text)
doc.text.addElement(p)
return doc
return doc

View file

@ -1,61 +1,59 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from exporter.basic import basicExporter
# --!-- coding: utf8 --!--
from PyQt5.QtGui import QTextDocument, QTextCursor, QTextDocumentWriter
from manuskript.exporter.basic import basicExporter
from manuskript.functions import mainWindow
class odtExporter(basicExporter):
requires = ["filename"]
def __init__(self):
pass
def doCompile(self, filename):
mw = mainWindow()
root = mw.mdlOutline.rootItem
doc = QTextDocument()
cursor = QTextCursor(doc)
def appendItem(item):
if item.isFolder():
cursor.setPosition(doc.characterCount() - 1)
title = "<h{l}>{t}</h{l}><br>\n".format(
l = str(item.level() + 1),
t = item.title())
l=str(item.level() + 1),
t=item.title())
cursor.insertHtml(title)
for c in item.children():
appendItem(c)
else:
text = self.formatText(item.text(), item.type())
cursor.setPosition(doc.characterCount() - 1)
cursor.insertHtml(text)
for c in root.children():
appendItem(c)
dw = QTextDocumentWriter(filename, "odt")
dw.write(doc)
def formatText(self, text, _type):
if not text:
return text
if _type == "t2t":
text = self.runT2T(text)
elif _type == "txt":
text = text.replace("\n", "<br>")
elif _type == "html":
text = self.htmlBody(text)
return text + "<br>"

View file

@ -1,12 +1,20 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from random import *
from enums import *
import os
from random import *
from PyQt5.QtCore import Qt, QRect, QStandardPaths, QObject
# Used to detect multiple connections
from PyQt5.QtGui import QBrush, QIcon, QPainter
from PyQt5.QtGui import QColor
from PyQt5.QtGui import QImage
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import qApp
from manuskript.enums import Outline
AUC = Qt.AutoConnection | Qt.UniqueConnection
MW = None
@ -70,7 +78,7 @@ def mainWindow():
return MW
def iconColor(icon):
"Returns a QRgb from a QIcon, assuming its all the same color"
"""Returns a QRgb from a QIcon, assuming its all the same color"""
px = icon.pixmap(5, 5)
if px.width() != 0:
return QColor(QImage(px).pixel(2, 2))
@ -86,7 +94,7 @@ def iconFromColorString(string):
return iconFromColor(QColor(string))
def randomColor(mix=None):
"Generates a random color. If mix (QColor) is given, mixes the random color and mix."
"""Generates a random color. If mix (QColor) is given, mixes the random color and mix."""
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
@ -106,36 +114,36 @@ def mixColors(col1, col2, f=.5):
return QColor(r, g, b)
def outlineItemColors(item):
"Takes an OutlineItem and returns a dict of colors."
colors = {}
mw = mainWindow()
# POV
colors["POV"] = QColor(Qt.transparent)
POV = item.data(Outline.POV.value)
for i in range(mw.mdlPersos.rowCount()):
if mw.mdlPersos.ID(i) == POV:
colors["POV"] = iconColor(mw.mdlPersos.icon(i))
# Label
lbl = item.data(Outline.label.value)
col = iconColor(mw.mdlLabels.item(toInt(lbl)).icon())
if col == Qt.black:
# Don't know why, but transparent is rendered as black
col = QColor(Qt.transparent)
colors["Label"] = col
# Progress
pg = item.data(Outline.goalPercentage.value)
colors["Progress"] = colorFromProgress(pg)
# Compile
if item.compile() in [0, "0"]:
colors["Compile"] = QColor(Qt.gray)
else:
colors["Compile"] = QColor(Qt.black)
return colors
"""Takes an OutlineItem and returns a dict of colors."""
colors = {}
mw = mainWindow()
# POV
colors["POV"] = QColor(Qt.transparent)
POV = item.data(Outline.POV.value)
for i in range(mw.mdlPersos.rowCount()):
if mw.mdlPersos.ID(i) == POV:
colors["POV"] = iconColor(mw.mdlPersos.icon(i))
# Label
lbl = item.data(Outline.label.value)
col = iconColor(mw.mdlLabels.item(toInt(lbl)).icon())
if col == Qt.black:
# Don't know why, but transparent is rendered as black
col = QColor(Qt.transparent)
colors["Label"] = col
# Progress
pg = item.data(Outline.goalPercentage.value)
colors["Progress"] = colorFromProgress(pg)
# Compile
if item.compile() in [0, "0"]:
colors["Compile"] = QColor(Qt.gray)
else:
colors["Compile"] = QColor(Qt.black)
return colors
def colorifyPixmap(pixmap, color):
# FIXME: ugly

View file

@ -1,10 +1,15 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from functions import *
from lxml import etree as ET
import zipfile
from PyQt5.QtCore import QModelIndex, Qt
from PyQt5.QtGui import QColor, QStandardItem
from PyQt5.QtWidgets import qApp
from lxml import etree as ET
from manuskript.functions import iconColor, iconFromColorString
try:
import zlib # Used with zipfile for compression
compression = zipfile.ZIP_DEFLATED

View file

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
import sys
from qt import *
from functions import *
import faulthandler
import sys
from PyQt5.QtCore import QLocale, QTranslator, QSettings
from PyQt5.QtWidgets import QApplication
from .functions import *
_version = "0.1"
@ -49,7 +50,7 @@ def run():
def launch():
from mainWindow import MainWindow
from .mainWindow import MainWindow
main = MainWindow()
main.show()

View file

@ -1,27 +1,33 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
from qt import *
from ui.mainWindow import *
from ui.helpLabel import helpLabel
from ui.compileDialog import compileDialog
from loadSave import *
from enums import *
from models.outlineModel import *
from models.persosModel import *
from models.plotModel import *
from models.worldModel import worldModel
from ui.views.outlineDelegates import outlinePersoDelegate
from ui.views.plotDelegate import plotDelegate
from ui.collapsibleDockWidgets import collapsibleDockWidgets
# from models.persosProxyModel import *
from functions import *
from settingsWindow import *
import settings
import imp
import os
from PyQt5.QtCore import pyqtSignal, QSignalMapper, QTimer, QSettings, Qt, QRegExp, QUrl
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QMainWindow, QHeaderView, qApp, QMenu, QActionGroup, QAction, QStyle
from manuskript import settings
from manuskript.enums import Perso, Subplot, Plot, World
from manuskript.functions import AUC, wordCount
from manuskript.loadSave import loadStandardItemModelXML, loadFilesFromZip
from manuskript.loadSave import saveFilesToZip
from manuskript.loadSave import saveStandardItemModelXML
from manuskript.models.outlineModel import outlineModel
from manuskript.models.persosModel import persosModel
from manuskript.models.plotModel import plotModel
from manuskript.models.worldModel import worldModel
from manuskript.settingsWindow import settingsWindow
from manuskript.ui.collapsibleDockWidgets import collapsibleDockWidgets
from manuskript.ui.compileDialog import compileDialog
from manuskript.ui.helpLabel import helpLabel
from manuskript.ui.mainWindow import Ui_MainWindow
from manuskript.ui.views.outlineDelegates import outlinePersoDelegate
from manuskript.ui.views.plotDelegate import plotDelegate
# Spellcheck support
from manuskript.ui.views.textEditView import textEditView
try:
import enchant
except ImportError:
@ -907,6 +913,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
w.setDict(settings.dict)
def openPyEnchantWebPage(self):
from PyQt5.QtGui import QDesktopServices
QDesktopServices.openUrl(QUrl("http://pythonhosted.org/pyenchant/"))
def toggleSpellcheck(self, val):

View file

@ -1,14 +1,22 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
from qt import *
from enums import *
from enum import Enum
from lxml import etree as ET
from functions import *
import settings
import locale
from PyQt5.QtCore import QAbstractItemModel, QMimeData
from PyQt5.QtCore import QModelIndex
from PyQt5.QtCore import QSize
from PyQt5.QtCore import QVariant
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QTextEdit, qApp
from manuskript import settings
from lxml import etree as ET
from manuskript.enums import Outline
from manuskript.functions import mainWindow, toInt, wordCount
locale.setlocale(locale.LC_ALL, '')
import time

View file

@ -1,9 +1,16 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QModelIndex, Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QColor, QPixmap, QIcon
from PyQt5.QtWidgets import QColorDialog
from manuskript.enums import Perso
from manuskript.enums import Plot
from manuskript.functions import iconColor
from manuskript.functions import mainWindow
from manuskript.functions import randomColor
from manuskript.functions import toInt
class persosModel(QStandardItemModel):
@ -11,8 +18,8 @@ class persosModel(QStandardItemModel):
QStandardItemModel.__init__(self, 0, 3, parent)
self.setHorizontalHeaderLabels([i.name for i in Plot])
self.mw = mainWindow()
#self._proxy = plotsProxyModel()
#self._proxy.setSourceModel(self)
# self._proxy = plotsProxyModel()
# self._proxy.setSourceModel(self)
###############################################################################
# PERSOS QUERRIES
@ -126,7 +133,7 @@ class persosModel(QStandardItemModel):
###############################################################################
def updatePersoColor(self, idx):
#idx = self.currentPersoIndex()
# idx = self.currentPersoIndex()
color = self.getPersoColorName(idx)
self.mw.btnPersoColor.setStyleSheet("background:{};".format(color))
@ -174,4 +181,3 @@ class persosModel(QStandardItemModel):
infos.append((name, val))
return infos

View file

@ -1,11 +1,8 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from manuskript import enums
from enum import Enum
from lxml import etree as ET
class persosProxyModel(QSortFilterProxyModel):

View file

@ -1,31 +1,38 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QModelIndex
from PyQt5.QtCore import QSignalMapper
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush
from PyQt5.QtGui import QStandardItem
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QAction, QMenu
from manuskript.enums import Plot
from manuskript.enums import Subplot
from manuskript.functions import toInt, mainWindow
class plotModel(QStandardItemModel):
def __init__(self, parent):
QStandardItemModel.__init__(self, 0, 3, parent)
self.setHorizontalHeaderLabels([i.name for i in Plot])
self.mw = mainWindow()
self.updatePlotPersoButton()
###############################################################################
# QUERIES
###############################################################################
###############################################################################
# QUERIES
###############################################################################
def getPlotsByImportance(self):
plots = [[], [], []]
for i in range(self.rowCount()):
importance = self.item(i, Plot.importance.value).text()
ID = self.item(i, Plot.ID.value).text()
plots[2-toInt(importance)].append(ID)
plots[2 - toInt(importance)].append(ID)
return plots
def getSubPlotsByID(self, ID):
index = self.getIndexFromID(ID)
if not index.isValid():
@ -39,7 +46,7 @@ class plotModel(QStandardItemModel):
summary = item.child(i, 3).text()
lst.append((_ID, name, summary))
return lst
def getPlotNameByID(self, ID):
for i in range(self.rowCount()):
_ID = self.item(i, Plot.ID.value).text()
@ -47,7 +54,7 @@ class plotModel(QStandardItemModel):
name = self.item(i, Plot.name.value).text()
return name
return None
def getSubPlotTextsByID(self, plotID, subplotRaw):
"""Returns a tuple (name, summary) for the suplot whose raw in the model
is ``subplotRaw``, of plot whose ID is ``plotID``.
@ -55,53 +62,54 @@ class plotModel(QStandardItemModel):
plotIndex = self.getIndexFromID(plotID)
name = plotIndex.child(subplotRaw, Plot.name.value).data()
summary = plotIndex.child(subplotRaw, 3).data() # 3 is for summary
return (name, summary)
return name, summary
def getIndexFromID(self, ID):
for i in range(self.rowCount()):
_ID = self.item(i, Plot.ID.value).text()
if _ID == ID or toInt(_ID) == ID:
return self.index(i, 0)
return QModelIndex()
def currentIndex(self):
i = self.mw.lstPlots.currentIndex()
if i .isValid():
if i.isValid():
return i
else:
return None
###############################################################################
# ADDING / REMOVING
###############################################################################
###############################################################################
# ADDING / REMOVING
###############################################################################
def addPlot(self):
p = QStandardItem(self.tr("New plot"))
_id = QStandardItem(self.getUniqueID())
importance = QStandardItem(str(0))
self.appendRow([p, _id, importance, QStandardItem("Persos"),
self.appendRow([p, _id, importance, QStandardItem("Persos"),
QStandardItem(), QStandardItem(), QStandardItem("Subplots")])
def getUniqueID(self, parent=QModelIndex()):
"Returns an unused ID"
"""Returns an unused ID"""
parentItem = self.itemFromIndex(parent)
vals = []
for i in range(self.rowCount(parent)):
index = self.index(i, Plot.ID.value, parent)
#item = self.item(i, Plot.ID.value)
# item = self.item(i, Plot.ID.value)
if index.isValid() and index.data():
vals.append(int(index.data()))
k = 0
while k in vals: k += 1
while k in vals:
k += 1
return str(k)
def removePlot(self, index):
self.takeRow(index.row())
###############################################################################
# SUBPLOTS
###############################################################################
###############################################################################
# SUBPLOTS
###############################################################################
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
@ -116,42 +124,42 @@ class plotModel(QStandardItemModel):
return ""
else:
return QStandardItemModel.headerData(self, section, orientation, role)
def data(self, index, role=Qt.DisplayRole):
if index.parent().isValid() and \
index.parent().column() == Plot.subplots.value and \
index.column() == Subplot.meta.value:
index.parent().column() == Plot.subplots.value and \
index.column() == Subplot.meta.value:
if role == Qt.TextAlignmentRole:
return Qt.AlignRight | Qt.AlignVCenter
elif role == Qt.ForegroundRole:
return QBrush(Qt.gray)
else:
return QStandardItemModel.data(self, index, role)
else:
return QStandardItemModel.data(self, index, role)
def addSubPlot(self):
index = self.mw.lstPlots.currentPlotIndex()
if not index.isValid():
return
parent = index.sibling(index.row(), Plot.subplots.value)
parentItem = self.item(index.row(), Plot.subplots.value)
if not parentItem:
return
p = QStandardItem(self.tr("New subplot"))
_id = QStandardItem(self.getUniqueID(parent))
summary = QStandardItem()
# Don't know why, if summary is in third position, then drag/drop deletes it...
parentItem.appendRow([p, _id, QStandardItem(), summary])
# Select last index
self.mw.lstSubPlots.setCurrentIndex(parent.child(self.rowCount(parent)-1, 0))
self.mw.lstSubPlots.setCurrentIndex(parent.child(self.rowCount(parent) - 1, 0))
def removeSubPlot(self):
index = self.mw.lstSubPlots.currentIndex()
if not index.isValid():
@ -159,33 +167,33 @@ class plotModel(QStandardItemModel):
parent = index.parent()
parentItem = self.itemFromIndex(parent)
parentItem.takeRow(index.row())
def flags(self, index):
parent = index.parent()
if parent.isValid(): # this is a subitem
return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled
if parent.isValid(): # this is a subitem
return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled
else:
return QStandardItemModel.flags(self, index)
###############################################################################
# PLOT PERSOS
###############################################################################
###############################################################################
# PLOT PERSOS
###############################################################################
def addPlotPerso(self, v):
index = self.mw.lstPlots.currentPlotIndex()
if index.isValid():
if not self.item(index.row(), Plot.persos.value):
self.setItem(index.row(), Plot.persos.value, QStandardItem())
item = self.item(index.row(), Plot.persos.value)
# We check that the PersoID is not in the list yet
for i in range(item.rowCount()):
if item.child(i).text() == str(v):
return
item.appendRow(QStandardItem(str(v)))
def removePlotPerso(self):
index = self.mw.lstPlotPerso.currentIndex()
if not index.isValid():
@ -193,26 +201,26 @@ class plotModel(QStandardItemModel):
parent = index.parent()
parentItem = self.itemFromIndex(parent)
parentItem.takeRow(index.row())
def updatePlotPersoButton(self):
menu = QMenu(self.mw)
menus = []
for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
m = QMenu(i, menu)
menus.append(m)
menu.addMenu(m)
mpr = QSignalMapper(menu)
for i in range(self.mw.mdlPersos.rowCount()):
a = QAction(self.mw.mdlPersos.name(i), menu)
a.setIcon(self.mw.mdlPersos.icon(i))
a.triggered.connect(mpr.map)
mpr.setMapping(a, int(self.mw.mdlPersos.ID(i)))
imp = toInt(self.mw.mdlPersos.importance(i))
menus[2-imp].addAction(a)
menus[2 - imp].addAction(a)
mpr.mapped.connect(self.addPlotPerso)
self.mw.btnAddPlotPerso.setMenu(menu)
self.mw.btnAddPlotPerso.setMenu(menu)

View file

@ -1,107 +1,109 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QModelIndex
from PyQt5.QtCore import QSortFilterProxyModel
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QBrush, QFont
from PyQt5.QtGui import QColor
from PyQt5.QtGui import QStandardItem
from manuskript.enums import Plot
from enum import Enum
from lxml import etree as ET
class plotsProxyModel(QSortFilterProxyModel):
newStatuses = pyqtSignal()
def __init__(self, parent=None):
QSortFilterProxyModel.__init__(self, parent)
#self.rootItem = QStandardItem()
# self.rootItem = QStandardItem()
self.p1 = QStandardItem(self.tr("Main"))
self.p2 = QStandardItem(self.tr("Secundary"))
self.p3 = QStandardItem(self.tr("Minors"))
self._cats = [
self.p1,
self.p2,
self.p3
]
]
def mapFromSource(self, sourceIndex):
if not sourceIndex.isValid():
return QModelIndex()
row = self._map.index(sourceIndex.row())
#item = sourceIndex.internalPointer()
# item = sourceIndex.internalPointer()
item = self.sourceModel().itemFromIndex(sourceIndex)
return self.createIndex(row, sourceIndex.column(), item)
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
if index.isValid() and not self.mapToSource(index).isValid():
return Qt.NoItemFlags#Qt.ItemIsEnabled
return Qt.NoItemFlags # Qt.ItemIsEnabled
else:
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
def mapToSource(self, proxyIndex):
if not proxyIndex.isValid():
return QModelIndex()
row = self._map[proxyIndex.row()]
if type(row) != int:
return QModelIndex()
#item = proxyIndex.internalPointer()
# item = proxyIndex.internalPointer()
item = self.sourceModel().item(row, proxyIndex.column())
return self.sourceModel().indexFromItem(item)
def setSourceModel(self, model):
QSortFilterProxyModel.setSourceModel(self, model)
self.sourceModel().dataChanged.connect(self.mapModelMaybe)
self.sourceModel().rowsInserted.connect(self.mapModel)
self.sourceModel().rowsRemoved.connect(self.mapModel)
self.sourceModel().rowsMoved.connect(self.mapModel)
self.mapModel()
def mapModelMaybe(self, topLeft, bottomRight):
if topLeft.column() <= Plot.importance.value <= bottomRight.column():
self.mapModel()
def mapModel(self):
self.beginResetModel()
src = self.sourceModel()
self._map = []
for i in range(len(self._cats)):
self._map.append(self._cats[i])
for p in range(src.rowCount()):
item = src.item(p, Plot.importance.value)
if item:
imp = int(item.text())
else:
imp = 0
if 2-imp == i:
if 2 - imp == i:
self._map.append(p)
self.endResetModel()
def data(self, index, role=Qt.DisplayRole):
if index.isValid() and not self.mapToSource(index).isValid():
row = index.row()
if role == Qt.DisplayRole:
return self._map[row].text()
elif role == Qt.ForegroundRole:
return QBrush(Qt.darkBlue)
elif role == Qt.BackgroundRole:
@ -110,32 +112,32 @@ class plotsProxyModel(QSortFilterProxyModel):
return Qt.AlignCenter
elif role == Qt.FontRole:
f = QFont()
#f.setPointSize(f.pointSize() + 1)
# f.setPointSize(f.pointSize() + 1)
f.setWeight(QFont.Bold)
return f
else:
#FIXME: sometimes, the name of the character is not displayed
# FIXME: sometimes, the name of the character is not displayed
return self.sourceModel().data(self.mapToSource(index), role)
def index(self, row, column, parent):
i = self._map[row]
if type(i) != int:
return self.createIndex(row, column, i)
else:
return self.mapFromSource(self.sourceModel().index(i, column, QModelIndex()))
def parent(self, index=QModelIndex()):
return QModelIndex()
def rowCount(self, parent=QModelIndex()):
return len(self._map)
def columnCount(self, parent=QModelIndex()):
return self.sourceModel().columnCount(QModelIndex())
def item(self, row, col, parent=QModelIndex()):
idx = self.mapToSource(self.index(row, col, parent))
return self.sourceModel().item(idx.row(), idx.column())
return self.sourceModel().item(idx.row(), idx.column())

View file

@ -1,9 +1,6 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
import re
###############################################################################
@ -11,6 +8,14 @@ import re
###############################################################################
# A regex used to match references
from PyQt5.QtWidgets import qApp
from manuskript.enums import Outline
from manuskript.enums import Perso
from manuskript.enums import Plot
from manuskript.enums import Subplot
from manuskript.functions import mainWindow
RegEx = r"{(\w):(\d+):?.*?}"
# A non-capturing regex used to identify references
RegExNonCapturing = r"{\w:\d+:?.*?}"
@ -21,21 +26,26 @@ TextLetter = "T"
PlotLetter = "P"
WorldLetter = "W"
def plotReference(ID):
"Takes the ID of a plot and returns a reference for that plot."
"""Takes the ID of a plot and returns a reference for that plot."""
return EmptyRef.format(PlotLetter, ID, "")
def persoReference(ID):
"Takes the ID of a character and returns a reference for that character."
"""Takes the ID of a character and returns a reference for that character."""
return EmptyRef.format(PersoLetter, ID, "")
def textReference(ID):
"Takes the ID of an outline item and returns a reference for that item."
"""Takes the ID of an outline item and returns a reference for that item."""
return EmptyRef.format(TextLetter, ID, "")
def worldReference(ID):
"Takes the ID of a world item and returns a reference for that item."
return EmptyRef.format(WordLetter, ID, "")
"""Takes the ID of a world item and returns a reference for that item."""
return EmptyRef.format(WorldLetter, ID, "")
###############################################################################
# READABLE INFOS
@ -48,21 +58,21 @@ def infos(ref):
match = re.fullmatch(RegEx, ref)
if not match:
return qApp.translate("references", "Not a reference: {}.").format(ref)
_type = match.group(1)
_ref = match.group(2)
# A text or outine item
if _type == TextLetter:
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
if not idx.isValid():
return qApp.translate("references", "Unknown reference: {}.").format(ref)
item = idx.internalPointer()
#Titles
# Titles
pathTitle = qApp.translate("references", "Path:")
statsTitle = qApp.translate("references", "Stats:")
POVTitle = qApp.translate("references", "POV:")
@ -71,42 +81,42 @@ def infos(ref):
ssTitle = qApp.translate("references", "Short summary:")
lsTitle = qApp.translate("references", "Long summary:")
notesTitle = qApp.translate("references", "Notes:")
# The POV of the scene
POV = ""
if item.POV():
POV = "<a href='{ref}'>{text}</a>".format(
ref=persoReference(item.POV()),
text=mainWindow().mdlPersos.getPersoNameByID(item.POV()))
ref=persoReference(item.POV()),
text=mainWindow().mdlPersos.getPersoNameByID(item.POV()))
# The status of the scene
status = item.status()
if status:
status = mainWindow().mdlStatus.item(int(status), 0).text()
else:
status = ""
# The label of the scene
label = item.label()
if label:
label = mainWindow().mdlLabels.item(int(label), 0).text()
else:
label = ""
# The path of the scene
path = item.pathID()
pathStr = []
for _id, title in path:
pathStr.append("<a href='{ref}'>{text}</a>".format(
ref=textReference(_id),
text=title))
ref=textReference(_id),
text=title))
path = " > ".join(pathStr)
# Summaries and notes
ss = item.data(Outline.summarySentance.value)
ls = item.data(Outline.summaryFull.value)
notes = item.data(Outline.notes.value)
text = """<h1>{title}</h1>
<p><b>{pathTitle}</b> {path}</p>
<p><b>{statsTitle}</b> {stats}<br>
@ -118,86 +128,86 @@ def infos(ref):
{notes}
{references}
""".format(
title=item.title(),
pathTitle=pathTitle,
path=path,
statsTitle=statsTitle,
stats=item.stats(),
POV="<b>{POVTitle}</b> {POV}<br>".format(
POVTitle=POVTitle,
POV=POV) if POV else "",
status="<b>{statusTitle}</b> {status}<br>".format(
statusTitle=statusTitle,
status=status) if status else "",
label="<b>{labelTitle}</b> {label}</p>".format(
labelTitle=labelTitle,
label=label) if label else "",
ss="<p><b>{ssTitle}</b> {ss}</p>".format(
ssTitle=ssTitle,
ss=ss.replace("\n", "<br>")) if ss.strip() else "",
ls="<p><b>{lsTitle}</b><br>{ls}</p>".format(
lsTitle=lsTitle,
ls=ls.replace("\n", "<br>")) if ls.strip() else "",
notes="<p><b>{notesTitle}</b><br>{notes}</p>".format(
notesTitle=notesTitle,
notes=linkifyAllRefs(basicT2TFormat(notes))) if notes.strip() else "",
references=listReferences(ref)
)
title=item.title(),
pathTitle=pathTitle,
path=path,
statsTitle=statsTitle,
stats=item.stats(),
POV="<b>{POVTitle}</b> {POV}<br>".format(
POVTitle=POVTitle,
POV=POV) if POV else "",
status="<b>{statusTitle}</b> {status}<br>".format(
statusTitle=statusTitle,
status=status) if status else "",
label="<b>{labelTitle}</b> {label}</p>".format(
labelTitle=labelTitle,
label=label) if label else "",
ss="<p><b>{ssTitle}</b> {ss}</p>".format(
ssTitle=ssTitle,
ss=ss.replace("\n", "<br>")) if ss.strip() else "",
ls="<p><b>{lsTitle}</b><br>{ls}</p>".format(
lsTitle=lsTitle,
ls=ls.replace("\n", "<br>")) if ls.strip() else "",
notes="<p><b>{notesTitle}</b><br>{notes}</p>".format(
notesTitle=notesTitle,
notes=linkifyAllRefs(basicT2TFormat(notes))) if notes.strip() else "",
references=listReferences(ref)
)
return text
# A character
elif _type == PersoLetter:
m = mainWindow().mdlPersos
index = m.getIndexFromID(_ref)
name = m.name(index.row())
# Titles
basicTitle = qApp.translate("references", "Basic infos")
detailedTitle = qApp.translate("references", "Detailed infos")
POVof = qApp.translate("references", "POV of:")
# Goto (link)
goto = qApp.translate("references", "Go to {}.")
goto = goto.format(refToLink(ref))
# basic infos
basic = []
for i in [
(Perso.motivation, qApp.translate("references", "Motivation"), False),
(Perso.goal, qApp.translate("references", "Goal"), False),
(Perso.conflict, qApp.translate("references", "Conflict"), False),
(Perso.epiphany, qApp.translate("references", "Epiphany"), False),
(Perso.summarySentance, qApp.translate("references", "Short summary"), True),
(Perso.motivation, qApp.translate("references", "Motivation"), False),
(Perso.goal, qApp.translate("references", "Goal"), False),
(Perso.conflict, qApp.translate("references", "Conflict"), False),
(Perso.epiphany, qApp.translate("references", "Epiphany"), False),
(Perso.summarySentance, qApp.translate("references", "Short summary"), True),
(Perso.summaryPara, qApp.translate("references", "Longer summary"), True),
]:
]:
val = m.data(index.sibling(index.row(), i[0].value))
if val:
basic .append("<b>{title}:</b>{n}{val}".format(
title=i[1],
n = "\n" if i[2] else " ",
val=val))
basic.append("<b>{title}:</b>{n}{val}".format(
title=i[1],
n="\n" if i[2] else " ",
val=val))
basic = "<br>".join(basic)
# detailed infos
detailed = []
for _name, _val in m.listPersoInfos(index):
detailed.append("<b>{}:</b> {}".format(
_name,
_val))
_name,
_val))
detailed = "<br>".join(detailed)
# list scenes of which it is POV
oM = mainWindow().mdlOutline
lst = oM.findItemsByPOV(_ref)
listPOV = ""
for t in lst:
idx = oM.getIndexByID(t)
listPOV += "<li><a href='{link}'>{text}</a></li>".format(
link=textReference(t),
text=oM.data(idx, Outline.title.value))
link=textReference(t),
text=oM.data(idx, Outline.title.value))
text = """<h1>{name}</h1>
{goto}
{basicInfos}
@ -205,45 +215,45 @@ def infos(ref):
{POV}
{references}
""".format(
name=name,
goto=goto,
basicInfos="<h2>{basicTitle}</h2>{basic}".format(
basicTitle=basicTitle,
basic=basic) if basic else "",
detailedInfos="<h2>{detailedTitle}</h2>{detailed}".format(
detailedTitle=detailedTitle,
detailed=detailed) if detailed else "",
POV="<h2>{POVof}</h2><ul>{listPOV}</ul>".format(
POVof=POVof,
listPOV=listPOV) if listPOV else "",
references=listReferences(ref)
)
name=name,
goto=goto,
basicInfos="<h2>{basicTitle}</h2>{basic}".format(
basicTitle=basicTitle,
basic=basic) if basic else "",
detailedInfos="<h2>{detailedTitle}</h2>{detailed}".format(
detailedTitle=detailedTitle,
detailed=detailed) if detailed else "",
POV="<h2>{POVof}</h2><ul>{listPOV}</ul>".format(
POVof=POVof,
listPOV=listPOV) if listPOV else "",
references=listReferences(ref)
)
return text
# A plot
elif _type == PlotLetter:
m = mainWindow().mdlPlots
index = m.getIndexFromID(_ref)
name = m.getPlotNameByID(_ref)
# Titles
descriptionTitle = qApp.translate("references", "Description")
resultTitle = qApp.translate("references", "Result")
charactersTitle = qApp.translate("references", "Characters")
stepsTitle = qApp.translate("references", "Resolution steps")
# Goto (link)
goto = qApp.translate("references", "Go to {}.")
goto = goto.format(refToLink(ref))
# Description
description = m.data(index.sibling(index.row(),
description = m.data(index.sibling(index.row(),
Plot.description.value))
# Result
result = m.data(index.sibling(index.row(),
Plot.result.value))
result = m.data(index.sibling(index.row(),
Plot.result.value))
# Characters
pM = mainWindow().mdlPersos
item = m.item(index.row(), Plot.persos.value)
@ -252,9 +262,9 @@ def infos(ref):
for r in range(item.rowCount()):
ID = item.child(r, 0).text()
characters += "<li><a href='{link}'>{text}</a>".format(
link=persoReference(ID),
text=pM.getPersoNameByID(ID))
link=persoReference(ID),
text=pM.getPersoNameByID(ID))
# Resolution steps
steps = ""
item = m.item(index.row(), Plot.subplots.value)
@ -266,10 +276,10 @@ def infos(ref):
if meta:
meta = " <span style='color:gray;'>({})</span>".format(meta)
steps += "<li><b>{title}</b>{summary}{meta}</li>".format(
title=title,
summary=": {}".format(summary) if summary else "",
meta = meta if meta else "")
title=title,
summary=": {}".format(summary) if summary else "",
meta=meta if meta else "")
text = """<h1>{name}</h1>
{goto}
{characters}
@ -278,48 +288,48 @@ def infos(ref):
{steps}
{references}
""".format(
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
result="<h2>{title}</h2>{text}".format(
title=resultTitle,
text=result) if result else "",
characters="<h2>{title}</h2><ul>{lst}</ul>".format(
title=charactersTitle,
lst=characters) if characters else "",
steps="<h2>{title}</h2><ul>{steps}</ul>".format(
title=stepsTitle,
steps=steps) if steps else "",
references=listReferences(ref, referenceTitle)
)
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
result="<h2>{title}</h2>{text}".format(
title=resultTitle,
text=result) if result else "",
characters="<h2>{title}</h2><ul>{lst}</ul>".format(
title=charactersTitle,
lst=characters) if characters else "",
steps="<h2>{title}</h2><ul>{steps}</ul>".format(
title=stepsTitle,
steps=steps) if steps else "",
references=listReferences(ref)
)
return text
# A World item
elif _type == WorldLetter:
m = mainWindow().mdlWorld
index = m.indexByID(_ref)
name = m.name(index)
# Titles
descriptionTitle = qApp.translate("references", "Description")
passionTitle = qApp.translate("references", "Passion")
conflictTitle = qApp.translate("references", "Conflict")
# Goto (link)
goto = qApp.translate("references", "Go to {}.")
goto = goto.format(refToLink(ref))
# Description
description = basicFormat(m.description(index))
# Passion
passion = basicFormat(m.passion(index))
passion = basicFormat(m.passion(index))
# Conflict
conflict = basicFormat(m.conflict(index))
conflict = basicFormat(m.conflict(index))
text = """<h1>{name}</h1>
{goto}
{description}
@ -327,60 +337,61 @@ def infos(ref):
{conflict}
{references}
""".format(
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
passion="<h2>{title}</h2>{text}".format(
title=passionTitle,
text=passion) if passion else "",
conflict="<h2>{title}</h2><ul>{lst}</ul>".format(
title=conflictTitle,
lst=conflict) if conflict else "",
references=listReferences(ref)
)
name=name,
goto=goto,
description="<h2>{title}</h2>{text}".format(
title=descriptionTitle,
text=description) if description else "",
passion="<h2>{title}</h2>{text}".format(
title=passionTitle,
text=passion) if passion else "",
conflict="<h2>{title}</h2><ul>{lst}</ul>".format(
title=conflictTitle,
lst=conflict) if conflict else "",
references=listReferences(ref)
)
return text
else:
return qApp.translate("references", "Unknown reference: {}.").format(ref)
def tooltip(ref):
"Returns a tooltip in HTML for the reference ``ref``."
"""Returns a tooltip in HTML for the reference ``ref``."""
match = re.fullmatch(RegEx, ref)
if not match:
return qApp.translate("references", "Not a reference: {}.").format(ref)
_type = match.group(1)
_ref = match.group(2)
if _type == TextLetter:
m = mainWindow().mdlOutline
idx = m.getIndexByID(_ref)
if not idx.isValid():
return qApp.translate("references", "Unknown reference: {}.").format(ref)
item = idx.internalPointer()
tooltip = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
tooltip += "<br><i>{}</i>".format(item.path())
return tooltip
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
tt += "<br><i>{}</i>".format(item.path())
return tt
elif _type == PersoLetter:
m = mainWindow().mdlPersos
item = m.item(int(_ref), Perso.name.value)
if item:
return qApp.translate("references", "Character: <b>{}</b>").format(item.text())
elif _type == PlotLetter:
m = mainWindow().mdlPlots
name = m.getPlotNameByID(_ref)
if name:
return qApp.translate("references", "Plot: <b>{}</b>").format(name)
elif _type == WorldLetter:
m = mainWindow().mdlWorld
item = m.itemByID(_ref)
@ -388,15 +399,16 @@ def tooltip(ref):
name = item.text()
path = m.path(item)
return qApp.translate("references", "World: <b>{name}</b>{path}").format(
name=name,
path=" <span style='color:gray;'>({})</span>".format(path) if path else "")
name=name,
path=" <span style='color:gray;'>({})</span>".format(path) if path else "")
return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
###############################################################################
# FUNCTIONS
###############################################################################
def refToLink(ref):
"""Transforms the reference ``ref`` in a link displaying useful infos
about that reference. For character, character's name. For text item,
@ -413,30 +425,32 @@ def refToLink(ref):
if idx.isValid():
item = idx.internalPointer()
text = item.title()
elif _type == PersoLetter:
m = mainWindow().mdlPersos
text = m.item(int(_ref), Perso.name.value).text()
elif _type == PlotLetter:
m = mainWindow().mdlPlots
text = m.getPlotNameByID(_ref)
elif _type == WorldLetter:
m = mainWindow().mdlWorld
text = m.itemByID(_ref).text()
if text:
return "<a href='{ref}'>{text}</a>".format(
ref=ref,
text=text)
else:
return ref
def linkifyAllRefs(text):
"Takes all the references in ``text`` and transform them into HMTL links."
"""Takes all the references in ``text`` and transform them into HMTL links."""
return re.sub(RegEx, lambda m: refToLink(m.group(0)), text)
def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
oM = mainWindow().mdlOutline
listRefs = ""
@ -445,22 +459,23 @@ def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
for t in lst:
idx = oM.getIndexByID(t)
listRefs += "<li><a href='{link}'>{text}</a></li>".format(
link=textReference(t),
text=oM.data(idx, Outline.title.value))
link=textReference(t),
text=oM.data(idx, Outline.title.value))
return "<h2>{title}</h2><ul>{ref}</ul>".format(
title=title,
ref=listRefs) if listRefs else ""
title=title,
ref=listRefs) if listRefs else ""
def basicT2TFormat(text, formatting=True, EOL=True, titles=True):
"A very basic t2t formatter to display notes and texts."
"""A very basic t2t formatter to display notes and texts."""
text = text.splitlines()
for n, line in enumerate(text):
if formatting:
line = re.sub("\*\*(.*?)\*\*", "<b>\\1</b>", line)
line = re.sub("//(.*?)//", "<i>\\1</i>", line)
line = re.sub("__(.*?)__", "<u>\\1</u>", line)
if titles:
for i in range(1, 6):
r1 = '^\s*{s}([^=].*[^=]){s}\s*$'.format(s="=" * i)
@ -472,9 +487,10 @@ def basicT2TFormat(text, formatting=True, EOL=True, titles=True):
text = "\n".join(text)
if EOL:
text = text.replace("\n", "<br>")
return text
def basicFormat(text):
if not text:
return ""
@ -482,31 +498,32 @@ def basicFormat(text):
text = linkifyAllRefs(text)
return text
def open(ref):
"Identify ``ref`` and open it."
"""Identify ``ref`` and open it."""
match = re.fullmatch(RegEx, ref)
if not match:
return
_type = match.group(1)
_ref = match.group(2)
if _type == PersoLetter:
mw = mainWindow()
item = mw.lstPersos.getItemByID(_ref)
if item:
mw.tabMain.setCurrentIndex(mw.TabPersos)
mw.lstPersos.setCurrentItem(item)
return True
print("Ref not found")
return False
elif _type == TextLetter:
mw = mainWindow()
index = mw.mdlOutline.getIndexByID(_ref)
if index.isValid():
mw.tabMain.setCurrentIndex(mw.TabRedac)
mw.mainEditor.setCurrentModelIndex(index, newTab=True)
@ -514,31 +531,31 @@ def open(ref):
else:
print("Ref not found")
return False
elif _type == PlotLetter:
elif _type == PlotLetter:
mw = mainWindow()
item = mw.lstPlots.getItemByID(_ref)
if item:
mw.tabMain.setCurrentIndex(mw.TabPlots)
mw.lstPlots.setCurrentItem(item)
return True
print("Ref not found")
return False
elif _type == WorldLetter:
elif _type == WorldLetter:
mw = mainWindow()
item = mw.mdlWorld.itemByID(_ref)
if item:
mw.tabMain.setCurrentIndex(mw.TabWorld)
mw.treeWorld.setCurrentIndex(
mw.mdlWorld.indexFromItem(item))
mw.mdlWorld.indexFromItem(item))
return True
print("Ref not found")
return False
print("Ref not implemented")
return False
return False

View file

@ -1,23 +1,27 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import collections
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QModelIndex
from PyQt5.QtCore import QSize
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItem, QBrush, QFontMetrics
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QMenu, QAction, qApp
from manuskript.enums import World
from manuskript.functions import mainWindow, lightBlue
class worldModel(QStandardItemModel):
def __init__(self, parent):
QStandardItemModel.__init__(self, 0, 3, parent)
self.mw = mainWindow()
###############################################################################
# SELECTION
###############################################################################
###############################################################################
# SELECTION
###############################################################################
def selectedItem(self):
"Returns the item selected in mw.treeWorld. invisibleRootItem if None."
"""Returns the item selected in mw.treeWorld. invisibleRootItem if None."""
index = self.selectedIndex()
item = self.itemFromIndex(index)
if item:
@ -26,57 +30,57 @@ class worldModel(QStandardItemModel):
return self.invisibleRootItem()
def selectedIndex(self):
"Returns the selected index in the treeView."
"""Returns the selected index in the treeView."""
if self.mw.treeWorld.selectedIndexes():
return self.mw.treeWorld.currentIndex()
else:
return QModelIndex()
def selectedIndexes(self):
return self.mw.treeWorld.selectedIndexes()
###############################################################################
# GETTERS
###############################################################################
###############################################################################
# GETTERS
###############################################################################
def ID(self, index):
"Returns the ID of the given index."
"""Returns the ID of the given index."""
index = index.sibling(index.row(), World.ID.value)
return self.data(index)
def name(self, index):
"Returns the name of the given index."
"""Returns the name of the given index."""
index = index.sibling(index.row(), World.name.value)
return self.data(index)
def description(self, index):
index = index.sibling(index.row(), World.description.value)
return self.data(index)
def conflict(self, index):
index = index.sibling(index.row(), World.conflict.value)
return self.data(index)
def passion(self, index):
index = index.sibling(index.row(), World.passion.value)
return self.data(index)
def itemID(self, item):
"Returns the ID of the given item."
"""Returns the ID of the given item."""
index = self.indexFromItem(item)
return self.ID(index)
def children(self, item):
"Returns a list of all item's children."
"""Returns a list of all item's children."""
c = []
for i in range(item.rowCount()):
c.append(item.child(i))
return c
def listAll(self):
"Returns a list of tupple ``(name, ID, path)`` for all items."
"""Returns a list of tupple ``(name, ID, path)`` for all items."""
lst = []
def readAll(item):
name = item.text()
ID = self.itemID(item)
@ -85,17 +89,18 @@ class worldModel(QStandardItemModel):
lst.append((name, ID, path))
for c in self.children(item):
readAll(c)
readAll(self.invisibleRootItem())
return lst
def indexByID(self, ID):
"Returns the index of item whose ID is ID."
"""Returns the index of item whose ID is ID."""
return self.indexFromItem(self.itemByID(ID))
def itemByID(self, ID):
"Returns the item whose ID is ID."
"""Returns the item whose ID is ID."""
def browse(item):
if self.itemID(item) == ID:
return item
@ -103,25 +108,25 @@ class worldModel(QStandardItemModel):
r = browse(c)
if r:
return r
r = browse(self.invisibleRootItem())
return r if r else None
def path(self, item):
"Returns the path to the item in the form of 'ancestor > ... > grand-parent > parent'."
"""Returns the path to the item in the form of 'ancestor > ... > grand-parent > parent'."""
path = []
while item.parent():
item = item.parent()
path.append(item.text())
path = " > ".join(path)
return path
###############################################################################
# ADDING AND REMOVE
###############################################################################
###############################################################################
# ADDING AND REMOVE
###############################################################################
def addItem(self, title=None, parent=None):
"Adds an item, and returns it."
"""Adds an item, and returns it."""
if not parent:
parent = self.selectedItem()
if not title:
@ -133,21 +138,22 @@ class worldModel(QStandardItemModel):
return name
def getUniqueID(self):
"Returns an unused ID"
"""Returns an unused ID"""
parentItem = self.invisibleRootItem()
vals = []
def collectIDs(item):
vals.append(int(self.itemID(item)))
for c in self.children(item):
collectIDs(c)
for c in self.children(parentItem):
collectIDs(c)
k = 0
while k in vals: k += 1
while k in vals:
k += 1
return str(k)
def removeItem(self):
@ -155,12 +161,12 @@ class worldModel(QStandardItemModel):
index = self.selectedIndexes()[0]
self.removeRows(index.row(), 1, index.parent())
###############################################################################
# TEMPLATES
###############################################################################
###############################################################################
# TEMPLATES
###############################################################################
def dataSets(self):
"Returns sets of empty data that can guide the writer for world building."
"""Returns sets of empty data that can guide the writer for world building."""
dataset = {
self.tr("Fantasy world building"): [
(self.tr("Physical"), [
@ -173,7 +179,7 @@ class worldModel(QStandardItemModel):
self.tr("History"),
self.tr("Races"),
self.tr("Diseases"),
]),
]),
(self.tr("Cultural"), [
self.tr("Customs"),
self.tr("Food"),
@ -196,34 +202,34 @@ class worldModel(QStandardItemModel):
self.tr("Demography"),
self.tr("Transportation"),
self.tr("Medicine"),
]),
]),
(self.tr("Magic system"), [
self.tr("Rules"),
self.tr("Organization"),
self.tr("Magical objects"),
self.tr("Magical places"),
self.tr("Magical races"),
]),
]),
self.tr("Important places"),
self.tr("Important objects"),
]
}
]
}
return dataset
def emptyDataMenu(self):
"Returns a menu with the empty data sets."
"""Returns a menu with the empty data sets."""
self.menu = QMenu("menu")
for name in self.dataSets():
a = QAction(name, self.menu)
a.triggered.connect(self.setEmptyData)
self.menu.addAction(a)
return self.menu
def setEmptyData(self):
"Called from the menu generated with ``emptyDataMenu``."
"""Called from the menu generated with ``emptyDataMenu``."""
act = self.sender()
data = self.dataSets()[act.text()]
def addItems(data, parent):
for d in data:
if len(d) == 1 or type(d) == str:
@ -231,39 +237,39 @@ class worldModel(QStandardItemModel):
else:
i = self.addItem(d[0], parent)
addItems(d[1], i)
addItems(data, None)
self.mw.treeWorld.expandAll()
###############################################################################
# APPEARANCE
###############################################################################
###############################################################################
# APPEARANCE
###############################################################################
def data(self, index, role=Qt.EditRole):
level = 0
i = index
while i.parent() != QModelIndex():
i = i.parent()
level += 1
if role == Qt.BackgroundRole:
if level == 0:
return QBrush(lightBlue())
if role == Qt.TextAlignmentRole:
if level == 0:
return Qt.AlignCenter
if role == Qt.FontRole:
if level in [0, 1]:
f = qApp.font()
f.setBold(True)
return f
if role == Qt.ForegroundRole:
if level == 0:
return QBrush(Qt.darkBlue)
if role == Qt.SizeHintRole:
fm = QFontMetrics(qApp.font())
h = fm.height()
@ -271,6 +277,5 @@ class worldModel(QStandardItemModel):
return QSize(0, h + 12)
elif level == 1:
return QSize(0, h + 6)
return QStandardItemModel.data(self, index, role)

View file

@ -1,8 +0,0 @@
# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *

View file

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
import pickle
import pprint
from enums import *
from qt import *
import collections
import pickle
from PyQt5.QtWidgets import qApp
from manuskript.enums import Outline
viewSettings = {
"Tree": {

View file

@ -1,41 +1,48 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from ui.settings import *
from enums import *
from functions import *
from ui.editors.themes import *
from ui.views.textEditView import *
import settings
# --!-- coding: utf8 --!--
import os
from PyQt5.QtCore import QSize, QSettings, QRegExp
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIntValidator, QIcon, QFont, QColor, QPixmap, QStandardItem, QPainter
from PyQt5.QtWidgets import QStyleFactory, QWidget, QStyle, QColorDialog, QListWidgetItem
from PyQt5.QtWidgets import qApp
# Spell checker support
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import allPaths, iconColor, writablePath, appPath
from manuskript.functions import mainWindow
from manuskript.ui.editors.themes import createThemePreview
from manuskript.ui.editors.themes import getThemeName
from manuskript.ui.editors.themes import loadThemeDatas
from manuskript.ui.settings_ui import Ui_Settings
from manuskript.ui.views.textEditView import textEditView
try:
import enchant
except ImportError:
enchant = None
class settingsWindow(QWidget, Ui_Settings):
def __init__(self, mainWindow):
QWidget.__init__(self)
self.setupUi(self)
self.mw = mainWindow
# UI
for i in range(self.lstMenu.count()):
item = self.lstMenu.item(i)
item.setSizeHint(QSize(item.sizeHint().width(), 42))
item.setTextAlignment(Qt.AlignCenter)
self.lstMenu.setMaximumWidth(150)
# General
self.cmbStyle.addItems(list(QStyleFactory.keys()))
self.cmbStyle.setCurrentIndex([i.lower() for i in list(QStyleFactory.keys())].index(qApp.style().objectName()))
self.cmbStyle.currentIndexChanged[str].connect(self.setStyle)
self.txtAutoSave.setValidator(QIntValidator(0, 999, self))
self.txtAutoSaveNoChanges.setValidator(QIntValidator(0, 999, self))
self.chkAutoSave.setChecked(settings.autoSave)
@ -51,12 +58,12 @@ class settingsWindow(QWidget, Ui_Settings):
autoLoad, last = self.mw.welcome.getAutoLoadValues()
self.chkAutoLoad.setChecked(autoLoad)
self.chkAutoLoad.stateChanged.connect(self.saveSettingsChanged)
dtt = [
("t2t", self.tr("Txt2Tags"), "text-x-script"),
("html", self.tr("Rich Text (html)"), "text-html"),
("txt", self.tr("Plain Text"), "text-x-generic"),
]
]
self.cmbDefaultTextType.clear()
for t in dtt:
self.cmbDefaultTextType.addItem(QIcon.fromTheme(t[2]), t[1], t[0])
@ -64,7 +71,7 @@ class settingsWindow(QWidget, Ui_Settings):
if i != -1:
self.cmbDefaultTextType.setCurrentIndex(i)
self.cmbDefaultTextType.currentIndexChanged.connect(self.saveSettingsChanged)
# Revisions
opt = settings.revisions
self.chkRevisionsKeep.setChecked(opt["keep"])
@ -81,7 +88,7 @@ class settingsWindow(QWidget, Ui_Settings):
self.spnRevisionsMonth.valueChanged.connect(self.revisionsSettingsChanged)
self.spnRevisionsEternity.setValue(60 * 60 * 24 * 7 / opt["rules"][None])
self.spnRevisionsEternity.valueChanged.connect(self.revisionsSettingsChanged)
# Views
self.tabViews.setCurrentIndex(0)
lst = ["Nothing", "POV", "Label", "Progress", "Compile"]
@ -89,12 +96,12 @@ class settingsWindow(QWidget, Ui_Settings):
item, part = self.viewSettingsDatas()[cmb]
cmb.setCurrentIndex(lst.index(settings.viewSettings[item][part]))
cmb.currentIndexChanged.connect(self.viewSettingsChanged)
for chk in self.outlineColumnsData():
col = self.outlineColumnsData()[chk]
chk.setChecked(col in settings.outlineViewColumns)
chk.stateChanged.connect(self.outlineColumnsChanged)
for item, what, value in [
(self.rdoTreeItemCount, "InfoFolder", "Count"),
(self.rdoTreeWC, "InfoFolder", "WC"),
@ -103,16 +110,16 @@ class settingsWindow(QWidget, Ui_Settings):
(self.rdoTreeTextWC, "InfoText", "WC"),
(self.rdoTreeTextProgress, "InfoText", "Progress"),
(self.rdoTreeTextNothing, "InfoText", "Nothing"),
]:
]:
item.setChecked(settings.viewSettings["Tree"][what] == value)
item.toggled.connect(self.treeViewSettignsChanged)
self.populatesCmbBackgrounds(self.cmbCorkImage)
self.setCorkImageDefault()
self.updateCorkColor()
self.cmbCorkImage.currentIndexChanged.connect(self.setCorkBackground)
self.btnCorkColor.clicked.connect(self.setCorkColor)
# Text editor
opt = settings.textEditor
self.setButtonColor(self.btnEditorFontColor, opt["fontColor"])
@ -128,10 +135,10 @@ class settingsWindow(QWidget, Ui_Settings):
self.spnEditorFontSize.setValue(f.pointSize())
self.spnEditorFontSize.valueChanged.connect(self.updateEditorSettings)
self.cmbEditorLineSpacing.setCurrentIndex(
0 if opt["lineSpacing"] == 100 else
1 if opt["lineSpacing"] == 150 else
2 if opt["lineSpacing"] == 200 else
3)
0 if opt["lineSpacing"] == 100 else
1 if opt["lineSpacing"] == 150 else
2 if opt["lineSpacing"] == 200 else
3)
self.cmbEditorLineSpacing.currentIndexChanged.connect(self.updateEditorSettings)
self.spnEditorLineSpacing.setValue(opt["lineSpacing"])
self.spnEditorLineSpacing.valueChanged.connect(self.updateEditorSettings)
@ -145,7 +152,7 @@ class settingsWindow(QWidget, Ui_Settings):
self.spnEditorParaAbove.valueChanged.connect(self.updateEditorSettings)
self.spnEditorParaBelow.setValue(opt["spacingBelow"])
self.spnEditorParaAbove.valueChanged.connect(self.updateEditorSettings)
# Labels
self.lstLabels.setModel(self.mw.mdlLabels)
self.lstLabels.setRowHidden(0, True)
@ -153,13 +160,13 @@ class settingsWindow(QWidget, Ui_Settings):
self.btnLabelAdd.clicked.connect(self.addLabel)
self.btnLabelRemove.clicked.connect(self.removeLabel)
self.btnLabelColor.clicked.connect(self.setLabelColor)
# Statuses
self.lstStatus.setModel(self.mw.mdlStatus)
self.lstStatus.setRowHidden(0, True)
self.btnStatusAdd.clicked.connect(self.addStatus)
self.btnStatusRemove.clicked.connect(self.removeStatus)
# Fullscreen
self._editingTheme = None
self.btnThemeEditOK.setIcon(qApp.style().standardIcon(QStyle.SP_DialogApplyButton))
@ -175,42 +182,41 @@ class settingsWindow(QWidget, Ui_Settings):
self.btnThemeAdd.clicked.connect(self.newTheme)
self.btnThemeEdit.clicked.connect(self.editTheme)
self.btnThemeRemove.clicked.connect(self.removeTheme)
def setTab(self, tab):
tabs = {
"General":0,
"Views":1,
"Labels":2,
"Status":3,
"Fullscreen":4,
}
"General": 0,
"Views": 1,
"Labels": 2,
"Status": 3,
"Fullscreen": 4,
}
if tab in tabs:
self.lstMenu.setCurrentRow(tabs[tab])
else:
self.lstMenu.setCurrentRow(tab)
####################################################################################################
# GENERAL #
####################################################################################################
####################################################################################################
# GENERAL #
####################################################################################################
def setStyle(self, style):
#Save style to Qt Settings
# Save style to Qt Settings
sttgs = QSettings(qApp.organizationName(), qApp.applicationName())
sttgs.setValue("applicationStyle", style)
qApp.setStyle(style)
def saveSettingsChanged(self):
if self.txtAutoSave.text() in ["", "0"]:
self.txtAutoSave.setText("1")
if self.txtAutoSaveNoChanges.text() in ["", "0"]:
self.txtAutoSaveNoChanges.setText("1")
sttgs = QSettings()
sttgs.setValue("autoLoad", True if self.chkAutoLoad.checkState() else False)
sttgs.sync()
settings.autoSave = True if self.chkAutoSave.checkState() else False
settings.autoSaveNoChanges = True if self.chkAutoSaveNoChanges.checkState() else False
settings.saveOnQuit = True if self.chkSaveOnQuit.checkState() else False
@ -220,10 +226,9 @@ class settingsWindow(QWidget, Ui_Settings):
self.mw.saveTimerNoChanges.setInterval(settings.autoSaveNoChangesDelay * 1000)
settings.defaultTextType = self.cmbDefaultTextType.currentData()
####################################################################################################
# REVISION #
####################################################################################################
####################################################################################################
# REVISION #
####################################################################################################
def revisionsSettingsChanged(self):
opt = settings.revisions
@ -234,10 +239,10 @@ class settingsWindow(QWidget, Ui_Settings):
opt["rules"][60 * 60 * 24] = 60 * 60 / self.spnRevisionsDay.value()
opt["rules"][60 * 60 * 24 * 30] = 60 * 60 * 24 / self.spnRevisionsMonth.value()
opt["rules"][None] = 60 * 60 * 24 * 7 / self.spnRevisionsEternity.value()
####################################################################################################
# VIEWS #
####################################################################################################
####################################################################################################
# VIEWS #
####################################################################################################
def viewSettingsDatas(self):
return {
@ -252,15 +257,15 @@ class settingsWindow(QWidget, Ui_Settings):
self.cmbCorkBackground: ("Cork", "Background"),
self.cmbCorkBorder: ("Cork", "Border"),
self.cmbCorkCorner: ("Cork", "Corner")
}
}
def viewSettingsChanged(self):
cmb = self.sender()
lst = ["Nothing", "POV", "Label", "Progress", "Compile"]
item, part = self.viewSettingsDatas()[cmb]
element = lst[cmb.currentIndex()]
self.mw.setViewSettings(item, part, element)
def outlineColumnsData(self):
return {
self.chkOutlineTitle: Outline.title.value,
@ -271,8 +276,8 @@ class settingsWindow(QWidget, Ui_Settings):
self.chkOutlineWordCount: Outline.wordCount.value,
self.chkOutlineGoal: Outline.goal.value,
self.chkOutlinePercentage: Outline.goalPercentage.value,
}
}
def outlineColumnsChanged(self):
chk = self.sender()
val = True if chk.checkState() else False
@ -281,11 +286,11 @@ class settingsWindow(QWidget, Ui_Settings):
settings.outlineViewColumns.append(col)
elif not val and col in settings.outlineViewColumns:
settings.outlineViewColumns.remove(col)
# Update views
self.mw.redacEditor.outlineView.hideColumns()
self.mw.treePlanOutline.hideColumns()
def treeViewSettignsChanged(self):
for item, what, value in [
(self.rdoTreeItemCount, "InfoFolder", "Count"),
@ -295,12 +300,12 @@ class settingsWindow(QWidget, Ui_Settings):
(self.rdoTreeTextWC, "InfoText", "WC"),
(self.rdoTreeTextProgress, "InfoText", "Progress"),
(self.rdoTreeTextNothing, "InfoText", "Nothing"),
]:
]:
if item.isChecked():
settings.viewSettings["Tree"][what] = value
self.mw.treeRedacOutline.viewport().update()
def setCorkColor(self):
color = QColor(settings.corkBackground["color"])
self.colorDialog = QColorDialog(color, self)
@ -310,10 +315,10 @@ class settingsWindow(QWidget, Ui_Settings):
self.updateCorkColor()
# Update Cork view
self.mw.mainEditor.updateCorkBackground()
def updateCorkColor(self):
self.btnCorkColor.setStyleSheet("background:{};".format(settings.corkBackground["color"]))
def setCorkBackground(self, i):
img = self.cmbCorkImage.itemData(i)
if img:
@ -322,11 +327,11 @@ class settingsWindow(QWidget, Ui_Settings):
settings.corkBackground["image"] = ""
# Update Cork view
self.mw.mainEditor.updateCorkBackground()
def populatesCmbBackgrounds(self, cmb):
#self.cmbDelegate = cmbPixmapDelegate()
#self.cmbCorkImage.setItemDelegate(self.cmbDelegate)
# self.cmbDelegate = cmbPixmapDelegate()
# self.cmbCorkImage.setItemDelegate(self.cmbDelegate)
paths = allPaths("resources/backgrounds")
cmb.clear()
cmb.addItem(QIcon.fromTheme("list-remove"), "", "")
@ -334,21 +339,21 @@ class settingsWindow(QWidget, Ui_Settings):
lst = os.listdir(p)
for l in lst:
if l.lower()[-4:] in [".jpg", ".png"] or \
l.lower()[-5:] in [".jpeg"]:
l.lower()[-5:] in [".jpeg"]:
px = QPixmap(os.path.join(p, l)).scaled(128, 64, Qt.KeepAspectRatio)
cmb.addItem(QIcon(px), "", os.path.join(p, l))
cmb.setIconSize(QSize(128, 64))
def setCorkImageDefault(self):
if settings.corkBackground["image"] != "":
i = self.cmbCorkImage.findData(settings.corkBackground["image"])
if i != -1:
self.cmbCorkImage.setCurrentIndex(i)
####################################################################################################
# VIEWS / EDITOR
####################################################################################################
####################################################################################################
# VIEWS / EDITOR
####################################################################################################
def updateEditorSettings(self):
# Store settings
@ -356,20 +361,20 @@ class settingsWindow(QWidget, Ui_Settings):
f.setPointSize(self.spnEditorFontSize.value())
settings.textEditor["font"] = f.toString()
settings.textEditor["lineSpacing"] = \
100 if self.cmbEditorLineSpacing.currentIndex() == 0 else\
150 if self.cmbEditorLineSpacing.currentIndex() == 1 else\
200 if self.cmbEditorLineSpacing.currentIndex() == 2 else\
100 if self.cmbEditorLineSpacing.currentIndex() == 0 else \
150 if self.cmbEditorLineSpacing.currentIndex() == 1 else \
200 if self.cmbEditorLineSpacing.currentIndex() == 2 else \
self.spnEditorLineSpacing.value()
self.spnEditorLineSpacing.setEnabled(self.cmbEditorLineSpacing.currentIndex() == 3)
settings.textEditor["tabWidth"] = self.spnEditorTabWidth.value()
settings.textEditor["indent"] = True if self.chkEditorIndent.checkState() else False
settings.textEditor["spacingAbove"] = self.spnEditorParaAbove.value()
settings.textEditor["spacingBelow"] = self.spnEditorParaBelow.value()
# Update font and defaultBlockFormat to all textEditView. Drastically.
for w in mainWindow().findChildren(textEditView, QRegExp(".*")):
w.loadFontSettings()
def choseEditorFontColor(self):
color = settings.textEditor["fontColor"]
self.colorDialog = QColorDialog(QColor(color), self)
@ -387,7 +392,7 @@ class settingsWindow(QWidget, Ui_Settings):
settings.textEditor["misspelled"] = color.name()
self.setButtonColor(self.btnEditorMisspelledColor, color.name())
self.updateEditorSettings()
def choseEditorBackgroundColor(self):
color = settings.textEditor["background"]
self.colorDialog = QColorDialog(QColor(color), self)
@ -396,40 +401,39 @@ class settingsWindow(QWidget, Ui_Settings):
settings.textEditor["background"] = color.name()
self.setButtonColor(self.btnEditorBackgroundColor, color.name())
self.updateEditorSettings()
####################################################################################################
# STATUS #
####################################################################################################
####################################################################################################
# STATUS #
####################################################################################################
def addStatus(self):
self.mw.mdlStatus.appendRow(QStandardItem(self.tr("New status")))
def removeStatus(self):
for i in self.lstStatus.selectedIndexes():
self.mw.mdlStatus.removeRows(i.row(), 1)
####################################################################################################
# LABELS #
####################################################################################################
####################################################################################################
# LABELS #
####################################################################################################
def updateLabelColor(self, index):
#px = QPixmap(64, 64)
#px.fill(iconColor(self.mw.mdlLabels.item(index.row()).icon()))
#self.btnLabelColor.setIcon(QIcon(px))
self.btnLabelColor.setStyleSheet("background:{};".format(iconColor(self.mw.mdlLabels.item(index.row()).icon()).name()))
# px = QPixmap(64, 64)
# px.fill(iconColor(self.mw.mdlLabels.item(index.row()).icon()))
# self.btnLabelColor.setIcon(QIcon(px))
self.btnLabelColor.setStyleSheet(
"background:{};".format(iconColor(self.mw.mdlLabels.item(index.row()).icon()).name()))
self.btnLabelColor.setEnabled(True)
def addLabel(self):
px = QPixmap(32, 32)
px.fill(Qt.transparent)
self.mw.mdlLabels.appendRow(QStandardItem(QIcon(px), self.tr("New label")))
def removeLabel(self):
for i in self.lstLabels.selectedIndexes():
self.mw.mdlLabels.removeRows(i.row(), 1)
def setLabelColor(self):
index = self.lstLabels.currentIndex()
color = iconColor(self.mw.mdlLabels.item(index.row()).icon())
@ -440,16 +444,16 @@ class settingsWindow(QWidget, Ui_Settings):
px.fill(color)
self.mw.mdlLabels.item(index.row()).setIcon(QIcon(px))
self.updateLabelColor(index)
####################################################################################################
# FULLSCREEN #
####################################################################################################
####################################################################################################
# FULLSCREEN #
####################################################################################################
def themeSelected(self, current, previous):
if current:
# UI updates
self.btnThemeEdit.setEnabled(current.data(Qt.UserRole+1))
self.btnThemeRemove.setEnabled(current.data(Qt.UserRole+1))
self.btnThemeEdit.setEnabled(current.data(Qt.UserRole + 1))
self.btnThemeRemove.setEnabled(current.data(Qt.UserRole + 1))
# Save settings
theme = current.data(Qt.UserRole)
settings.fullScreenTheme = os.path.splitext(os.path.split(theme)[1])[0]
@ -457,7 +461,7 @@ class settingsWindow(QWidget, Ui_Settings):
# UI updates
self.btnThemeEdit.setEnabled(False)
self.btnThemeRemove.setEnabled(False)
def newTheme(self):
path = writablePath("resources/themes")
name = self.tr("newtheme")
@ -468,41 +472,41 @@ class settingsWindow(QWidget, Ui_Settings):
name = os.path.join(path, "{}_{}.theme".format(name, i))
else:
name = os.path.join(path, "{}.theme".format(name))
settings = QSettings(name, QSettings.IniFormat)
settings.setValue("Name", self.tr("New theme"))
settings.sync()
self.populatesThemesList()
def editTheme(self):
item = self.lstThemes.currentItem()
theme = item.data(Qt.UserRole)
self.loadTheme(theme)
self.themeStack.setCurrentIndex(1)
def removeTheme(self):
item = self.lstThemes.currentItem()
theme = item.data(Qt.UserRole)
os.remove(theme)
self.populatesThemesList()
def populatesThemesList(self):
paths = allPaths("resources/themes")
current = settings.fullScreenTheme
self.lstThemes.clear()
for p in paths:
lst = [i for i in os.listdir(p) if os.path.splitext(i)[1] == ".theme"]
for t in lst:
theme = os.path.join(p, t)
editable = not appPath() in theme
n = getThemeName(theme)
item = QListWidgetItem(n)
item.setData(Qt.UserRole, theme)
item.setData(Qt.UserRole+1, editable)
item.setData(Qt.UserRole + 1, editable)
thumb = os.path.join(p, t.replace(".theme", ".jpg"))
px = QPixmap(200, 120)
px.fill(Qt.white)
@ -510,32 +514,32 @@ class settingsWindow(QWidget, Ui_Settings):
currentScreen = qApp.desktop().screenNumber(self)
screenRect = qApp.desktop().screenGeometry(currentScreen)
thumb = createThemePreview(theme, screenRect)
icon = QPixmap(thumb).scaled(200, 120, Qt.KeepAspectRatio)
painter = QPainter(px)
painter.drawPixmap(px.rect().center()-icon.rect().center(), icon)
painter.drawPixmap(px.rect().center() - icon.rect().center(), icon)
painter.end()
item.setIcon(QIcon(px))
self.lstThemes.addItem(item)
if current and current in t:
self.lstThemes.setCurrentItem(item)
current = None
self.lstThemes.setIconSize(QSize(200, 120))
if current: # the theme from settings wasn't found
# select the last from the list
# select the last from the list
self.lstThemes.setCurrentRow(self.lstThemes.count() - 1)
def loadTheme(self, theme):
self._editingTheme = theme
self._loadingTheme = True # So we don't generate preview while loading
# Load datas
self._themeData = loadThemeDatas(theme)
# Window Background
self.btnThemWindowBackgroundColor.clicked.connect(lambda: self.getThemeColor("Background/Color"))
try:
@ -545,7 +549,7 @@ class settingsWindow(QWidget, Ui_Settings):
self.populatesCmbBackgrounds(self.cmbThemeBackgroundImage)
self.cmbThemeBackgroundImage.currentIndexChanged.connect(self.updateThemeBackground)
self.cmbThemBackgroundType.currentIndexChanged.connect(lambda i: self.setSetting("Background/Type", i))
# Text Background
self.btnThemeTextBackgroundColor.clicked.connect(lambda: self.getThemeColor("Foreground/Color"))
self.spnThemeTextBackgroundOpacity.valueChanged.connect(lambda v: self.setSetting("Foreground/Opacity", v))
@ -554,7 +558,7 @@ class settingsWindow(QWidget, Ui_Settings):
self.cmbThemeTextPosition.currentIndexChanged.connect(lambda i: self.setSetting("Foreground/Position", i))
self.spnThemeTextRadius.valueChanged.connect(lambda v: self.setSetting("Foreground/Rounding", v))
self.spnThemeTextWidth.valueChanged.connect(lambda v: self.setSetting("Foreground/Width", v))
# Text Options
self.btnThemeTextColor.clicked.connect(lambda: self.getThemeColor("Text/Color"))
self.cmbThemeFont.currentFontChanged.connect(self.updateThemeFont)
@ -565,37 +569,37 @@ class settingsWindow(QWidget, Ui_Settings):
self.populatesFontSize()
self.cmbThemeFontSize.currentIndexChanged.connect(self.updateThemeFont)
self.btnThemeMisspelledColor.clicked.connect(lambda: self.getThemeColor("Text/Misspelled"))
# Paragraph Options
self.chkThemeIndent.stateChanged.connect(lambda v: self.setSetting("Spacings/IndendFirstLine", v!=0))
self.chkThemeIndent.stateChanged.connect(lambda v: self.setSetting("Spacings/IndendFirstLine", v != 0))
self.cmbThemeLineSpacing.currentIndexChanged.connect(self.updateLineSpacing)
self.cmbThemeLineSpacing.currentIndexChanged.connect(self.updateLineSpacing)
self.spnThemeLineSpacing.valueChanged.connect(lambda v: self.setSetting("Spacings/LineSpacing", v))
self.spnThemeParaAbove.valueChanged.connect(lambda v: self.setSetting("Spacings/ParagraphAbove", v))
self.spnThemeParaBelow.valueChanged.connect(lambda v: self.setSetting("Spacings/ParagraphBelow", v))
self.spnThemeTabWidth.valueChanged.connect(lambda v: self.setSetting("Spacings/TabWidth", v))
# Update UI
self.updateUIFromTheme()
# Generate preview
self._loadingTheme = False
self.updatePreview()
def setSetting(self, key, val):
self._themeData[key] = val
self.updatePreview()
def updateUIFromTheme(self):
self.txtThemeName.setText(self._themeData["Name"])
# Window Background
self.setButtonColor(self.btnThemWindowBackgroundColor, self._themeData["Background/Color"])
i = self.cmbThemeBackgroundImage.findData(self._themeData["Background/ImageFile"], flags=Qt.MatchContains)
if i != -1:
self.cmbThemeBackgroundImage.setCurrentIndex(i)
self.cmbThemBackgroundType.setCurrentIndex(self._themeData["Background/Type"])
# Text background
self.setButtonColor(self.btnThemeTextBackgroundColor, self._themeData["Foreground/Color"])
self.spnThemeTextBackgroundOpacity.setValue(self._themeData["Foreground/Opacity"])
@ -604,7 +608,7 @@ class settingsWindow(QWidget, Ui_Settings):
self.cmbThemeTextPosition.setCurrentIndex(self._themeData["Foreground/Position"])
self.spnThemeTextRadius.setValue(self._themeData["Foreground/Rounding"])
self.spnThemeTextWidth.setValue(self._themeData["Foreground/Width"])
# Text Options
self.setButtonColor(self.btnThemeTextColor, self._themeData["Text/Color"])
f = QFont()
@ -615,9 +619,9 @@ class settingsWindow(QWidget, Ui_Settings):
self.cmbThemeFontSize.setCurrentIndex(i)
else:
self.cmbThemeFontSize.addItem(str(f.pointSize()))
self.cmbThemeFontSize.setCurrentIndex(self.cmbThemeFontSize.count()-1)
self.cmbThemeFontSize.setCurrentIndex(self.cmbThemeFontSize.count() - 1)
self.setButtonColor(self.btnThemeMisspelledColor, self._themeData["Text/Misspelled"])
# Paragraph Options
self.chkThemeIndent.setCheckState(Qt.Checked if self._themeData["Spacings/IndendFirstLine"] else Qt.Unchecked)
self.spnThemeLineSpacing.setEnabled(False)
@ -634,22 +638,22 @@ class settingsWindow(QWidget, Ui_Settings):
self.spnThemeParaAbove.setValue(self._themeData["Spacings/ParagraphAbove"])
self.spnThemeParaBelow.setValue(self._themeData["Spacings/ParagraphBelow"])
self.spnThemeTabWidth.setValue(self._themeData["Spacings/TabWidth"])
def populatesFontSize(self):
self.cmbThemeFontSize.clear()
s = list(range(6, 13)) + list(range(14,29, 2)) + [36, 48, 72]
s = list(range(6, 13)) + list(range(14, 29, 2)) + [36, 48, 72]
for i in s:
self.cmbThemeFontSize.addItem(str(i))
def updateThemeFont(self, v):
f = self.cmbThemeFont.currentFont()
s = self.cmbThemeFontSize.itemText(self.cmbThemeFontSize.currentIndex())
if s:
f.setPointSize(int(s))
self._themeData["Text/Font"] = f.toString()
self.updatePreview()
def updateLineSpacing(self, i):
if i == 0:
self._themeData["Spacings/LineSpacing"] = 100
@ -661,16 +665,16 @@ class settingsWindow(QWidget, Ui_Settings):
self._themeData["Spacings/LineSpacing"] = self.spnThemeLineSpacing.value()
self.spnThemeLineSpacing.setEnabled(i == 3)
self.updatePreview()
def updateThemeBackground(self, i):
img = self.cmbCorkImage.itemData(i)
if img:
self._themeData["Background/ImageFile"] = os.path.split(img)[1]
else:
self._themeData["Background/ImageFile"] = ""
self.updatePreview()
def getThemeColor(self, key):
color = self._themeData[key]
self.colorDialog = QColorDialog(QColor(color), self)
@ -679,37 +683,37 @@ class settingsWindow(QWidget, Ui_Settings):
self._themeData[key] = color.name()
self.updateUIFromTheme()
self.updatePreview()
def updatePreview(self):
if self._loadingTheme:
return
currentScreen = qApp.desktop().screenNumber(self)
screen = qApp.desktop().screenGeometry(currentScreen)
px = createThemePreview(self._themeData, screen, self.lblPreview.size())
self.lblPreview.setPixmap(px)
def setButtonColor(self, btn, color):
btn.setStyleSheet("background:{};".format(color))
def saveTheme(self):
settings = QSettings(self._editingTheme, QSettings.IniFormat)
self._themeData["Name"] = self.txtThemeName.text()
for key in self._themeData:
settings.setValue(key, self._themeData[key])
settings.sync()
self.populatesThemesList()
self.themeStack.setCurrentIndex(0)
self._editingTheme = None
def cancelEdit(self):
self.themeStack.setCurrentIndex(0)
self._editingTheme = None
def resizeEvent(self, event):
QWidget.resizeEvent(self, event)
if self._editingTheme:
self.updatePreview()
self.updatePreview()

View file

@ -1,23 +1,26 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.cheatSheet_ui import *
from functions import *
import models.references as Ref
# --!-- coding: utf8 --!--
from PyQt5.QtCore import pyqtSignal, Qt, QTimer, QRect
from PyQt5.QtGui import QBrush, QCursor, QPalette, QFontMetrics
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QToolTip, QStyledItemDelegate, QStyle
from manuskript.enums import Perso
from manuskript.enums import Plot
from manuskript.functions import lightBlue
from manuskript.functions import mainWindow
from manuskript.ui.cheatSheet_ui import Ui_cheatSheet
from manuskript.models import references as Ref
class cheatSheet(QWidget, Ui_cheatSheet):
activated = pyqtSignal(str)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.splitter.setStretchFactor(0, 5)
self.splitter.setStretchFactor(1, 70)
self.txtFilter.textChanged.connect(self.updateListFromData)
self.txtFilter.returnPressed.connect(self.showInfos)
self.listDelegate = listCompleterDelegate(self)
@ -26,80 +29,80 @@ class cheatSheet(QWidget, Ui_cheatSheet):
self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.view.linkActivated.connect(self.openLink)
self.view.linkHovered.connect(self.linkHovered)
self.outlineModel = None
self.persoModel = None
self.plotModel = None
self.worldModel = None
self.populateTimer = QTimer(self)
self.populateTimer.setSingleShot(True)
self.populateTimer.setInterval(500)
self.populateTimer.timeout.connect(self.populate)
self.populateTimer.stop()
self.data = {}
self.populate()
def setModels(self):
mw = mainWindow()
self.outlineModel = mw.mdlOutline
self.persoModel = mw.mdlPersos
self.plotModel = mw.mdlPlots
self.worldModel = mw.mdlWorld
self.outlineModel.dataChanged.connect(self.populateTimer.start)
self.persoModel.dataChanged.connect(self.populateTimer.start)
self.plotModel.dataChanged.connect(self.populateTimer.start)
self.worldModel.dataChanged.connect(self.populateTimer.start)
self.populate()
def populate(self):
if self.persoModel:
d = []
for r in range(self.persoModel.rowCount()):
name = self.persoModel.item(r, Perso.name.value).text()
ID = self.persoModel.item(r, Perso.ID.value).text()
imp = self.persoModel.item(r, Perso.importance.value).text()
imp = [self.tr("Minor"), self.tr("Secondary"), self.tr("Main")][int(imp)]
d.append((name, ID, imp))
self.data[(self.tr("Characters"), Ref.PersoLetter)] = d
if self.outlineModel:
d = []
def addChildren(item):
for c in item.children():
d.append((c.title(), c.ID(), c.path()))
addChildren(c)
r = self.outlineModel.rootItem
addChildren(r)
self.data[(self.tr("Texts"), Ref.TextLetter)] = d
if self.plotModel:
d = []
for r in range(self.plotModel.rowCount()):
name = self.plotModel.item(r, Plot.name.value).text()
ID = self.plotModel.item(r, Plot.ID.value).text()
imp = self.plotModel.item(r, Plot.importance.value).text()
imp = [self.tr("Minor"), self.tr("Secondary"), self.tr("Main")][int(imp)]
d.append((name, ID, imp))
self.data[(self.tr("Plots"), Ref.PlotLetter)] = d
if self.worldModel:
d = self.worldModel.listAll()
self.data[(self.tr("World"), Ref.WorldLetter)] = d
self.updateListFromData()
def addCategory(self, title):
item = QListWidgetItem(title)
item.setBackground(QBrush(lightBlue()))
@ -109,7 +112,7 @@ class cheatSheet(QWidget, Ui_cheatSheet):
f.setBold(True)
item.setFont(f)
self.list.addItem(item)
def updateListFromData(self):
self.list.clear()
for cat in self.data:
@ -119,48 +122,48 @@ class cheatSheet(QWidget, Ui_cheatSheet):
for item in filtered:
i = QListWidgetItem(item[0])
i.setData(Qt.UserRole, Ref.EmptyRef.format(cat[1], item[1], item[0]))
i.setData(Qt.UserRole+1, item[2])
i.setData(Qt.UserRole + 1, item[2])
self.list.addItem(i)
self.list.setCurrentRow(1)
def showInfos(self):
i = self.list.currentItem()
ref = i.data(Qt.UserRole)
if ref:
self.view.setText(Ref.infos(ref))
def openLink(self, link):
Ref.open(link)
def linkHovered(self, link):
if link:
QToolTip.showText(QCursor.pos(), Ref.tooltip(link))
def keyPressEvent(self, event):
if event.key() in [Qt.Key_Up, Qt.Key_Down]:
self.list.keyPressEvent(event)
else:
QWidget.keyPressEvent(self, event)
class listCompleterDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole+1)
extra = index.data(Qt.UserRole + 1)
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Inactive, QPalette.Highlight))
title = index.data()
extra = " - {}".format(extra)
painter.drawText(option.rect, Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
w = fm.width(title)
r = QRect(option.rect)
@ -168,4 +171,4 @@ class listCompleterDelegate(QStyledItemDelegate):
painter.save()
painter.setPen(Qt.gray)
painter.drawText(r, Qt.AlignLeft, extra)
painter.restore()
painter.restore()

View file

@ -6,7 +6,7 @@
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtWidgets
class Ui_cheatSheet(object):
def setupUi(self, cheatSheet):

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QToolBar, QDockWidget, QAction, QToolButton, QSizePolicy, QStylePainter, \
QStyleOptionButton, QStyle
class collapsibleDockWidgets(QToolBar):
@ -14,7 +15,7 @@ class collapsibleDockWidgets(QToolBar):
Qt.RightDockWidgetArea: Qt.RightToolBarArea,
Qt.TopDockWidgetArea: Qt.TopToolBarArea,
Qt.BottomDockWidgetArea: Qt.BottomToolBarArea,
}
}
def __init__(self, area, parent, name=""):
QToolBar.__init__(self, parent)
@ -26,18 +27,18 @@ class collapsibleDockWidgets(QToolBar):
self.setFloatable(False)
self.setMovable(False)
#self.setAllowedAreas(self.TRANSPOSED_AREA[self._area])
# self.setAllowedAreas(self.TRANSPOSED_AREA[self._area])
self.parent().addToolBar(self.TRANSPOSED_AREA[self._area], self)
# Dock widgets
for d in self._dockWidgets():
b = verticalButton(self)
b.setDefaultAction(d.toggleViewAction())
self.addWidget(b)
self.addSeparator()
# Other widgets
self.otherWidgets = []
self.currentGroup = None
@ -47,41 +48,41 @@ class collapsibleDockWidgets(QToolBar):
for w in mw.findChildren(QDockWidget, None):
yield w
def addCustomWidget(self, text, widget, group=None):
def addCustomWidget(self, text, widget, group=None):
a = QAction(text, self)
a.setCheckable(True)
a.setChecked(widget.isVisible())
a.toggled.connect(widget.setVisible)
#widget.installEventFilter(self)
# widget.installEventFilter(self)
b = verticalButton(self)
b.setDefaultAction(a)
a2 = self.addWidget(b)
self.otherWidgets.append((b, a2, widget, group))
#def eventFilter(self, widget, event):
#if event.type() in [QEvent.Show, QEvent.Hide]:
#for btn, action, w, grp in self.otherWidgets:
#if w == widget:
#btn.defaultAction().setChecked(event.type() == QEvent.Show)
#return False
# def eventFilter(self, widget, event):
# if event.type() in [QEvent.Show, QEvent.Hide]:
# for btn, action, w, grp in self.otherWidgets:
# if w == widget:
# btn.defaultAction().setChecked(event.type() == QEvent.Show)
# return False
def setCurrentGroup(self, group):
self.currentGroup = group
for btn, action, widget, grp in self.otherWidgets:
if not grp == group or grp == None:
if not grp == group or grp is None:
action.setVisible(False)
else:
action.setVisible(True)
class verticalButton(QToolButton):
def __init__(self, parent):
QToolButton.__init__(self, parent)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
def sizeHint(self):
return QToolButton.sizeHint(self).transposed()
def paintEvent(self, event):
p = QStylePainter(self)
p.rotate(90)
@ -93,4 +94,4 @@ class verticalButton(QToolButton):
opt.state |= QStyle.State_On
s = opt.rect.size().transposed()
opt.rect.setSize(s)
p.drawControl(QStyle.CE_PushButton, opt)
p.drawControl(QStyle.CE_PushButton, opt)

View file

@ -1,31 +1,30 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QRect, QRectF
from PyQt5.QtGui import QColor, QBrush, QRegion, QTextOption, QFont
from PyQt5.QtWidgets import QSizePolicy, QGroupBox, QWidget, QStylePainter, QStyleOptionGroupBox, qApp, QVBoxLayout, \
QStyle, QStyleOptionFrame, QStyleOptionFocusRect
from qt import *
class collapsibleGroupBox(QGroupBox):
def __init__(self, parent=None):
QGroupBox.__init__(self)
self.toggled.connect(self.setExpanded)
self.tempWidget = QWidget()
self.customStyle = False
def setExpanded(self, val):
self.setCollapsed(not val)
def setCollapsed(self, val):
if val:
# Save layout
self.tempWidget.setLayout(self.layout())
# Set empty layout
l = QVBoxLayout()
#print(l.contentsMargins().left(), l.contentsMargins().bottom(), l.contentsMargins().top(), )
# print(l.contentsMargins().left(), l.contentsMargins().bottom(), l.contentsMargins().top(), )
l.setContentsMargins(0, 0, 0, 0)
self.setLayout(l)
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
@ -35,37 +34,37 @@ class collapsibleGroupBox(QGroupBox):
# Set saved layout
self.setLayout(self.tempWidget.layout())
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
def paintEvent(self, event):
if not self.customStyle:
return QGroupBox.paintEvent(self, event)
p = QStylePainter(self)
opt = QStyleOptionGroupBox()
self.initStyleOption(opt)
style = qApp.style()
groupBox = opt
#// Draw frame
# // Draw frame
textRect = style.subControlRect(style.CC_GroupBox, opt, style.SC_GroupBoxLabel)
checkBoxRect = style.subControlRect(style.CC_GroupBox, opt, style.SC_GroupBoxCheckBox)
p.save()
titleRect = style.subControlRect(style.CC_GroupBox, opt, style.SC_GroupBoxFrame)
#r.setBottom(style.subControlRect(style.CC_GroupBox, opt, style.SC_GroupBoxContents).top())
# r.setBottom(style.subControlRect(style.CC_GroupBox, opt, style.SC_GroupBoxContents).top())
titleRect.setHeight(textRect.height())
titleRect.moveTop(textRect.top())
p.setBrush(QBrush(QColor(Qt.blue).lighter(190)))
p.setPen(Qt.NoPen)
p.drawRoundedRect(titleRect, 10, 10)
p.restore()
if groupBox.subControls & QStyle.SC_GroupBoxFrame:
frame = QStyleOptionFrame()
#frame.operator=(groupBox)
# frame.operator=(groupBox)
frame.state = groupBox.state
frame.features = groupBox.features
frame.lineWidth = groupBox.lineWidth
@ -81,26 +80,26 @@ class collapsibleGroupBox(QGroupBox):
finalRect.adjust(-4 if ltr else 0, 0, 0 if ltr else 4, 0)
else:
finalRect = textRect
region -= QRegion(finalRect)
p.setClipRegion(region)
style.drawPrimitive(style.PE_FrameGroupBox, frame, p)
p.restore()
##// Draw title
# // Draw title
if groupBox.subControls & QStyle.SC_GroupBoxLabel and groupBox.text:
#textColor = QColor(groupBox.textColor)
#if textColor.isValid():
#p.setPen(textColor)
#alignment = int(groupBox.textAlignment)
#if not style.styleHint(QStyle.SH_UnderlineShortcut, opt):
#alignment |= Qt.TextHideMnemonic
# textColor = QColor(groupBox.textColor)
# if textColor.isValid():
# p.setPen(textColor)
# alignment = int(groupBox.textAlignment)
# if not style.styleHint(QStyle.SH_UnderlineShortcut, opt):
# alignment |= Qt.TextHideMnemonic
# style.drawItemText(p, textRect, Qt.TextShowMnemonic | Qt.AlignHCenter | alignment,
# groupBox.palette, groupBox.state & style.State_Enabled, groupBox.text,
# QPalette.NoRole if textColor.isValid() else QPalette.WindowText)
#style.drawItemText(p, textRect, Qt.TextShowMnemonic | Qt.AlignHCenter | alignment,
#groupBox.palette, groupBox.state & style.State_Enabled, groupBox.text,
#QPalette.NoRole if textColor.isValid() else QPalette.WindowText)
p.save()
topt = QTextOption(Qt.AlignHCenter | Qt.AlignVCenter)
f = QFont()
@ -112,15 +111,15 @@ class collapsibleGroupBox(QGroupBox):
if groupBox.state & style.State_HasFocus:
fropt = QStyleOptionFocusRect()
#fropt.operator=(groupBox)
# fropt.operator=(groupBox)
fropt.state = groupBox.state
fropt.rect = textRect
style.drawPrimitive(style.PE_FrameFocusRect, fropt, p)
#// Draw checkbox
#if groupBox.subControls & style.SC_GroupBoxCheckBox:
#box = QStyleOptionButton()
##box.operator=(groupBox)
#box.state = groupBox.state
#box.rect = checkBoxRect
#style.drawPrimitive(style.PE_IndicatorCheckBox, box, p)
# // Draw checkbox
# if groupBox.subControls & style.SC_GroupBoxCheckBox:
# box = QStyleOptionButton()
# box.operator=(groupBox)
# box.state = groupBox.state
# box.rect = checkBoxRect
# style.drawPrimitive(style.PE_IndicatorCheckBox, box, p)

View file

@ -1,10 +1,10 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QFrame, QPushButton, QVBoxLayout, QSizePolicy
from qt import *
class collapsibleGroupBox2(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.frame = QFrame(self)
@ -14,12 +14,12 @@ class collapsibleGroupBox2(QWidget):
self.switched = False
self.vPolicy = None
self.button.setStyleSheet("background: lightBlue;")
def resizeEvent(self, event):
if not self.switched:
self.switchLayout()
return QWidget.resizeEvent(self, event)
def switchLayout(self):
self.frame.setLayout(self.layout())
self.wLayout = QVBoxLayout(self)
@ -29,31 +29,31 @@ class collapsibleGroupBox2(QWidget):
self.button.toggled.connect(self.setExpanded)
self.frame.layout().setContentsMargins(5, 0, 5, 0)
self.switched = True
self.vPolicy = self.sizePolicy().verticalPolicy()
self.parent().layout().setAlignment(Qt.AlignTop)
self.setExpanded(self.button.isChecked())
def setFlat(self, val):
if val:
self.frame.setFrameShape(QFrame.NoFrame)
def setCheckable(self, val):
pass
def setTitle(self, title):
self.button.setText(title)
def setExpanded(self, val):
self.frame.setVisible(val)
if val:
self.setSizePolicy(QSizePolicy.Preferred, self.vPolicy)
else:
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
def saveState(self):
return self.button.isChecked()
def restoreState(self, val):
self.button.setChecked(val)
self.button.setChecked(val)

View file

@ -1,107 +1,102 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.compileDialog_ui import *
from functions import *
import os
import exporter
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, qApp, QFileDialog
from manuskript import exporter
from manuskript.ui.compileDialog_ui import Ui_compileDialog
class compileDialog(QDialog, Ui_compileDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.btnPath.clicked.connect(self.getPath)
self.btnFilename.clicked.connect(self.getFilename)
self.btnCompile.clicked.connect(self.doCompile)
self.cmbTargets.activated.connect(self.updateUI)
self.txtPath.setText("/home/olivier/Documents/Travail/Geekeries/Python/manuskript/ExportTest")
self.txtFilename.setText("/home/olivier/Documents/Travail/Geekeries/Python/manuskript/ExportTest/test.html")
self.populatesTarget()
self.updateUI()
###############################################################################
# UI
###############################################################################
###############################################################################
# UI
###############################################################################
def populatesTarget(self):
for code in exporter.formats:
self.cmbTargets.addItem(exporter.formats[code][0], code)
def updateUI(self):
target = self.cmbTargets.currentData()
if not exporter.formats[target][1]:
self.btnCompile.setEnabled(False)
requires = []
else:
self.btnCompile.setEnabled(True)
requires = exporter.formats[target][1].requires
self.wPath.setVisible("path" in requires)
self.wFilename.setVisible("filename" in requires)
def startWorking(self):
# Setting override cursor
qApp.setOverrideCursor(Qt.WaitCursor)
# Button
self.btnCompile.setEnabled(False)
self.txtBtn = self.btnCompile.text()
self.btnCompile.setText(self.tr("Working..."))
def stopWorking(self):
# Removing override cursor
qApp.restoreOverrideCursor()
# Button
self.btnCompile.setEnabled(True)
self.btnCompile.setText(self.txtBtn)
###############################################################################
# USER INPUTS
###############################################################################
###############################################################################
# USER INPUTS
###############################################################################
def getPath(self):
path = self.txtPath.text()
path = QFileDialog.getExistingDirectory(self, self.tr("Chose export folder"), path)
if path:
self.txtPath.setText(path)
def getFilename(self):
fn = self.txtFilename.text()
target = self.cmbTargets.currentData()
fltr = exporter.formats[target][2]
fn = QFileDialog.getSaveFileName(self, self.tr("Chose export target"), fn, fltr)
if fn[0]:
self.txtFilename.setText(fn[0])
###############################################################################
# COMPILE
###############################################################################
###############################################################################
# COMPILE
###############################################################################
def doCompile(self):
target = self.cmbTargets.currentData()
self.startWorking()
if target == "arbo":
compiler = exporter.formats[target][1]()
compiler.doCompile(self.txtPath.text())
elif target in ["html", "odt"]:
compiler = exporter.formats[target][1]()
compiler.doCompile(self.txtFilename.text())
self.stopWorking()

View file

@ -6,7 +6,7 @@
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtWidgets
class Ui_compileDialog(object):
def setupUi(self, compileDialog):

View file

@ -1,13 +1,15 @@
#!/usr/bin/python
# -*- coding: utf8 -*-
from qt import *
import re
from functions import *
import models.references as Ref
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QTextCursor, QColor, QFont, QSyntaxHighlighter, QTextBlockFormat, QTextCharFormat
import manuskript.models.references as Ref
class basicHighlighter(QSyntaxHighlighter):
def __init__(self, editor):
QSyntaxHighlighter.__init__(self, editor.document())
@ -19,21 +21,20 @@ class basicHighlighter(QSyntaxHighlighter):
def setDefaultBlockFormat(self, bf):
self._defaultBlockFormat = bf
self.rehighlight()
def setDefaultCharFormat(self, cf):
self._defaultCharFormat = cf
self.rehighlight()
def setMisspelledColor(self, color):
self._misspelledColor = color
def highlightBlock(self, text):
"""Apply syntax highlighting to the given block of text.
"""
self.highlightBlockBefore(text)
self.highlightBlockAfter(text)
def highlightBlockBefore(self, text):
"""Highlighting to do before anything else.
@ -43,16 +44,16 @@ class basicHighlighter(QSyntaxHighlighter):
bf = QTextBlockFormat(self._defaultBlockFormat)
bf.setAlignment(QTextCursor(self.currentBlock()).blockFormat().alignment())
QTextCursor(self.currentBlock()).setBlockFormat(bf)
#self.setFormat(0, len(text), self._defaultCharFormat)
# self.setFormat(0, len(text), self._defaultCharFormat)
def highlightBlockAfter(self, text):
"""Highlighting to do after everything else.
When subclassing basicHighlighter, you must call highlightBlockAfter
after your custom highlighting.
"""
# References
for txt in re.finditer(Ref.RegEx, text):
fmt = self.format(txt.start())
@ -66,11 +67,11 @@ class basicHighlighter(QSyntaxHighlighter):
fmt.setBackground(QBrush(QColor(Qt.red).lighter(170)))
elif txt.group(1) == Ref.WorldLetter:
fmt.setBackground(QBrush(QColor(Qt.green).lighter(170)))
self.setFormat(txt.start(),
txt.end() - txt.start(),
fmt)
txt.end() - txt.start(),
fmt)
# Spell checking
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
WORDS = '(?iu)[\w\']+'
@ -81,7 +82,4 @@ class basicHighlighter(QSyntaxHighlighter):
format.setUnderlineColor(self._misspelledColor)
format.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
self.setFormat(word_object.start(),
word_object.end() - word_object.start(), format)
word_object.end() - word_object.start(), format)

View file

@ -1,14 +1,12 @@
#!/usr/bin/python
# -*- coding: utf8 -*-
from qt import *
from PyQt5.QtGui import QTextBlockUserData
class blockUserData (QTextBlockUserData):
class blockUserData(QTextBlockUserData):
@staticmethod
def getUserData(block):
"Returns userData if it exists, or a blank one."
"""Returns userData if it exists, or a blank one."""
data = block.userData()
if data is None:
data = blockUserData()
@ -16,7 +14,7 @@ class blockUserData (QTextBlockUserData):
@staticmethod
def getUserState(block):
"Returns the block state."
"""Returns the block state."""
state = block.userState()
while state >= 100:
state -= 100 # +100 means in a list

View file

@ -1,17 +1,18 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.editors.completer_ui import *
from functions import *
import models.references as Ref
# --!-- coding: utf8 --!--
from PyQt5.QtCore import pyqtSignal, Qt, QRect
from PyQt5.QtGui import QBrush, QFontMetrics, QPalette
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QStyledItemDelegate, QStyle
from manuskript.functions import lightBlue
from manuskript.functions import mainWindow
from manuskript.ui.editors.completer_ui import Ui_completer
from manuskript.models import references as Ref
class completer(QWidget, Ui_completer):
activated = pyqtSignal(str)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
@ -23,20 +24,20 @@ class completer(QWidget, Ui_completer):
self.list.itemActivated.connect(self.submit)
self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.hide()
def popup(self, completion=""):
self.updateListFromData()
self.text.setText(completion)
self.text.setFocus(Qt.PopupFocusReason)
self.show()
def addCategory(self, title):
item = QListWidgetItem(title)
item.setBackground(QBrush(lightBlue()))
item.setForeground(QBrush(Qt.darkBlue))
item.setFlags(Qt.ItemIsEnabled)
self.list.addItem(item)
def updateListFromData(self):
data = mainWindow().cheatSheet.data
self.list.clear()
@ -47,41 +48,41 @@ class completer(QWidget, Ui_completer):
for item in filtered:
i = QListWidgetItem(item[0])
i.setData(Qt.UserRole, Ref.EmptyRef.format(cat[1], item[1], item[0]))
i.setData(Qt.UserRole+1, item[2])
i.setData(Qt.UserRole + 1, item[2])
self.list.addItem(i)
self.list.setCurrentRow(1)
self.text.setFocus(Qt.PopupFocusReason)
def submit(self):
i = self.list.currentItem()
self.activated.emit(i.data(Qt.UserRole))
self.hide()
def keyPressEvent(self, event):
if event.key() in [Qt.Key_Up, Qt.Key_Down]:
self.list.keyPressEvent(event)
else:
QWidget.keyPressEvent(self, event)
class listCompleterDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole+1)
extra = index.data(Qt.UserRole + 1)
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Inactive, QPalette.Highlight))
title = index.data()
extra = " - {}".format(extra)
painter.drawText(option.rect, Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
w = fm.width(title)
r = QRect(option.rect)
@ -89,4 +90,4 @@ class listCompleterDelegate(QStyledItemDelegate):
painter.save()
painter.setPen(Qt.gray)
painter.drawText(r, Qt.AlignLeft, extra)
painter.restore()
painter.restore()

View file

@ -6,7 +6,7 @@
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtWidgets
class Ui_completer(object):
def setupUi(self, completer):

View file

@ -1,20 +1,19 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.editors.editorWidget_ui import *
from ui.editors.fullScreenEditor import *
from ui.editors.textFormat import *
from ui.views.textEditView import *
from functions import *
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtCore import pyqtSignal, QModelIndex
from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QWidget, QFrame, QSpacerItem, QSizePolicy, QVBoxLayout
from manuskript import settings
from manuskript.functions import AUC, mainWindow
from manuskript.ui.editors.editorWidget_ui import Ui_editorWidget_ui
from manuskript.ui.views.textEditView import textEditView
class editorWidget(QWidget, Ui_editorWidget_ui):
toggledSpellcheck = pyqtSignal(bool)
dictChanged = pyqtSignal(str)
def __init__(self, parent):
QWidget.__init__(self, parent)
self.setupUi(self)
@ -29,11 +28,11 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.spellcheck = True
self.folderView = "cork"
self.mw = mainWindow()
#def setModel(self, model):
#self._model = model
#self.setView()
# def setModel(self, model):
# self._model = model
# self.setView()
def setFolderView(self, v):
oldV = self.folderView
if v == "cork":
@ -42,66 +41,67 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.folderView = "outline"
else:
self.folderView = "text"
# Saving value
settings.folderView = self.folderView
if oldV != self.folderView and self.currentIndex:
self.setCurrentModelIndex(self.currentIndex)
def setCorkSizeFactor(self, v):
self.corkView.itemDelegate().setCorkSizeFactor(v)
self.redrawCorkItems()
def redrawCorkItems(self):
r = self.corkView.rootIndex()
if r.isValid():
count = r.internalPointer().childCount()
else:
count = self.mw.mdlOutline.rootItem.childCount()
for c in range(count):
self.corkView.itemDelegate().sizeHintChanged.emit(r.child(c, 0))
def setView(self):
#index = mainWindow().treeRedacOutline.currentIndex()
## Couting the number of other selected items
#sel = []
#for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes():
#if i.column() != 0: continue
#if i not in sel: sel.append(i)
#if len(sel) != 0:
#item = index.internalPointer()
#else:
#index = QModelIndex()
#item = self.mw.mdlOutline.rootItem
#self.currentIndex = index
# index = mainWindow().treeRedacOutline.currentIndex()
# Couting the number of other selected items
# sel = []
# for i in mainWindow().treeRedacOutline.selectionModel().selection().indexes():
# if i.column() != 0: continue
# if i not in sel: sel.append(i)
# if len(sel) != 0:
# item = index.internalPointer()
# else:
# index = QModelIndex()
# item = self.mw.mdlOutline.rootItem
# self.currentIndex = index
if self.currentIndex.isValid():
item = self.currentIndex.internalPointer()
else:
item = self.mw.mdlOutline.rootItem
def addTitle(itm):
edt = textEditView(self, html="<h{l}>{t}</h{l}>".format(l=min(itm.level()+1, 5), t=itm.title()), autoResize=True)
edt = textEditView(self, html="<h{l}>{t}</h{l}>".format(l=min(itm.level() + 1, 5), t=itm.title()),
autoResize=True)
edt.setFrameShape(QFrame.NoFrame)
self.txtEdits.append(edt)
l.addWidget(edt)
def addLine():
line = QFrame(self.text)
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
l.addWidget(line)
def addText(itm):
edt = textEditView(self,
index=itm.index(),
spellcheck=self.spellcheck,
edt = textEditView(self,
index=itm.index(),
spellcheck=self.spellcheck,
dict=settings.dict,
highlighting=True,
autoResize=True)
@ -110,67 +110,67 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
edt.setStatusTip("{} ({})".format(itm.path(), itm.type()))
self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC)
self.dictChanged.connect(edt.setDict, AUC)
#edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
# edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
self.txtEdits.append(edt)
l.addWidget(edt)
def addChildren(itm):
for c in range(itm.childCount()):
child = itm.child(c)
if child.isFolder():
addTitle(child)
addChildren(child)
else:
addText(child)
addLine()
def addSpacer():
l.addItem(QSpacerItem(10, 1000, QSizePolicy.Minimum, QSizePolicy.Expanding))
# Display multiple selected items
#if len(sel) > 1 and False: # Buggy and not very useful, skip
#self.stack.setCurrentIndex(1)
#w = QWidget()
#l = QVBoxLayout(w)
#self.txtEdits = []
#for idx in sel:
#sItem = idx.internalPointer()
#addTitle(sItem)
#if sItem.isFolder():
#addChildren(sItem)
#else:
#addText(sItem)
#addLine()
#addSpacer()
#self.scroll.setWidget(w)
# Display multiple selected items
# if len(sel) > 1 and False: # Buggy and not very useful, skip
# self.stack.setCurrentIndex(1)
# w = QWidget()
# l = QVBoxLayout(w)
# self.txtEdits = []
# for idx in sel:
# sItem = idx.internalPointer()
# addTitle(sItem)
# if sItem.isFolder():
# addChildren(sItem)
# else:
# addText(sItem)
# addLine()
# addSpacer()
# self.scroll.setWidget(w)
if item and item.isFolder() and self.folderView == "text":
self.stack.setCurrentIndex(1)
w = QWidget()
l = QVBoxLayout(w)
w.setStyleSheet("background: {};".format(settings.textEditor["background"]))
#self.scroll.setWidgetResizable(False)
# self.scroll.setWidgetResizable(False)
self.txtEdits = []
if item != self.mw.mdlOutline.rootItem:
addTitle(item)
addChildren(item)
addSpacer()
self.scroll.setWidget(w)
elif item and item.isFolder() and self.folderView == "cork":
self.stack.setCurrentIndex(2)
self.corkView.setModel(self.mw.mdlOutline)
self.corkView.setRootIndex(self.currentIndex)
self.corkView.selectionModel().selectionChanged.connect(
lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC)
lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC)
self.corkView.clicked.connect(
lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC)
lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC)
elif item and item.isFolder() and self.folderView == "outline":
self.stack.setCurrentIndex(3)
self.outlineView.setModelPersos(mainWindow().mdlPersos)
@ -179,14 +179,14 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.outlineView.setModel(self.mw.mdlOutline)
self.outlineView.setRootIndex(self.currentIndex)
self.outlineView.selectionModel().selectionChanged.connect(
lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC)
lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC)
self.outlineView.clicked.connect(
lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC)
lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC)
else:
self.txtRedacText.setCurrentModelIndex(self.currentIndex)
self.stack.setCurrentIndex(0) # Single text item
self.stack.setCurrentIndex(0) # Single text item
try:
self.mw.mdlOutline.dataChanged.connect(self.modelDataChanged, AUC)
self.mw.mdlOutline.rowsInserted.connect(self.updateIndexFromID, AUC)
@ -194,54 +194,54 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.mw.mdlOutline.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC)
except TypeError:
pass
self.updateStatusBar()
def setCurrentModelIndex(self, index=None):
if index.isValid():
self.currentIndex = index
self.currentID = self.mw.mdlOutline.ID(index)
#self._model = index.model()
# self._model = index.model()
else:
self.currentIndex = QModelIndex()
self.setView()
def updateIndexFromID(self):
idx = self.mw.mdlOutline.getIndexByID(self.currentID)
if idx != self.currentIndex:
self.currentIndex = idx
self.setView()
def modelDataChanged(self, topLeft, bottomRight):
#if self.currentID:
#self.updateIndexFromID()
# if self.currentID:
# self.updateIndexFromID()
if not self.currentIndex:
return
if topLeft.row() <= self.currentIndex.row() <= bottomRight.row():
self.updateStatusBar()
def rowsAboutToBeRemoved(self, parent, first, last):
if self.currentIndex:
if self.currentIndex.parent() == parent and \
first <= self.currentIndex.row() <= last:
first <= self.currentIndex.row() <= last:
# Item deleted, close tab
self.mw.mainEditor.tab.removeTab(self.mw.mainEditor.tab.indexOf(self))
def updateStatusBar(self):
# Update progress
#if self.currentIndex and self.currentIndex.isValid():
#if self._model:
# if self.currentIndex and self.currentIndex.isValid():
# if self._model:
mw = mainWindow()
if not mw: return
if not mw:
return
mw.mainEditor.updateStats()
def toggleSpellcheck(self, v):
self.spellcheck = v
self.toggledSpellcheck.emit(v)
def setDict(self, dct):
self.currentDict = dct
self.dictChanged.emit(dct)
self.dictChanged.emit(dct)

View file

@ -37,7 +37,7 @@ class Ui_editorWidget_ui(object):
self.scroll.setWidgetResizable(True)
self.scroll.setObjectName("scroll")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 396, 296))
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 96, 26))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scroll.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout.addWidget(self.scroll)
@ -70,6 +70,6 @@ class Ui_editorWidget_ui(object):
_translate = QtCore.QCoreApplication.translate
editorWidget_ui.setWindowTitle(_translate("editorWidget_ui", "Form"))
from ui.views.corkView import corkView
from ui.views.outlineView import outlineView
from ui.views.textEditView import textEditView
from manuskript.ui.views.corkView import corkView
from manuskript.ui.views.outlineView import outlineView
from manuskript.ui.views.textEditView import textEditView

View file

@ -14,7 +14,16 @@
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -24,7 +33,16 @@
</property>
<widget class="QWidget" name="text">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -37,7 +55,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -53,8 +80,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>296</height>
<width>96</width>
<height>26</height>
</rect>
</property>
</widget>
@ -64,7 +91,16 @@
</widget>
<widget class="QWidget" name="cork">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -74,7 +110,16 @@
</widget>
<widget class="QWidget" name="outline">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -90,17 +135,17 @@
<customwidget>
<class>textEditView</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditView.h</header>
<header>manuskript.ui.views.textEditView.h</header>
</customwidget>
<customwidget>
<class>outlineView</class>
<extends>QTreeView</extends>
<header>ui.views.outlineView.h</header>
<header>manuskript.ui.views.outlineView.h</header>
</customwidget>
<customwidget>
<class>corkView</class>
<extends>QListView</extends>
<header>ui.views.corkView.h</header>
<header>manuskript.ui.views.corkView.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -1,24 +1,30 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.views.textEditView import *
from ui.editors.themes import *
from ui.editors.textFormat import *
from ui.editors.locker import locker
# --!-- coding: utf8 --!--
import os
from functions import *
import settings
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
# Spell checker support
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
class fullScreenEditor(QWidget):
def __init__(self, index, parent=None):
QWidget.__init__(self, parent)
self._background = None
@ -27,9 +33,9 @@ class fullScreenEditor(QWidget):
self._themeDatas = loadThemeDatas(self._theme)
self.setMouseTracking(True)
self._geometries = {}
# Text editor
self.editor = textEditView(self,
self.editor = textEditView(self,
index=index,
spellcheck=settings.spellcheck,
highlighting=True,
@ -42,11 +48,11 @@ class fullScreenEditor(QWidget):
self.editor.setVerticalScrollBar(myScrollBar())
self.scrollBar = self.editor.verticalScrollBar()
self.scrollBar.setParent(self)
# Top Panel
self.topPanel = myPanel(parent=self)
#self.topPanel.layout().addStretch(1)
# self.topPanel.layout().addStretch(1)
# Spell checking
if enchant:
self.btnSpellCheck = QPushButton(self)
@ -56,30 +62,30 @@ class fullScreenEditor(QWidget):
self.btnSpellCheck.setChecked(self.editor.spellcheck)
self.btnSpellCheck.toggled.connect(self.editor.toggleSpellcheck)
self.topPanel.layout().addWidget(self.btnSpellCheck)
self.topPanel.layout().addStretch(1)
# Formatting
self.textFormat = textFormat(self)
self.topPanel.layout().addWidget(self.textFormat)
self.topPanel.layout().addStretch(1)
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)
# 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)
# Bottom Panel
self.bottomPanel = myPanel(parent=self)
self.bottomPanel.layout().addSpacing(24)
self.lstThemes = QComboBox(self)
self.lstThemes.setAttribute(Qt.WA_TranslucentBackground)
@ -95,7 +101,7 @@ class fullScreenEditor(QWidget):
self.bottomPanel.layout().addWidget(QLabel(self.tr("Theme:"), self))
self.bottomPanel.layout().addWidget(self.lstThemes)
self.bottomPanel.layout().addStretch(1)
self.lblProgress = QLabel(self)
self.lblProgress.setMaximumSize(QSize(200, 14))
self.lblProgress.setMinimumSize(QSize(100, 14))
@ -103,162 +109,162 @@ class fullScreenEditor(QWidget):
self.bottomPanel.layout().addWidget(self.lblWC)
self.bottomPanel.layout().addWidget(self.lblProgress)
self.updateStatusBar()
self.bottomPanel.layout().addSpacing(24)
# Connection
self._index.model().dataChanged.connect(self.dataChanged)
#self.updateTheme()
# self.updateTheme()
self.showFullScreen()
#self.showMaximized()
#self.show()
# self.showMaximized()
# self.show()
def setLocked(self, val):
self._locked = val
self.btnClose.setVisible(not val)
def setTheme(self, themeName):
settings.fullScreenTheme = themeName
self._theme = findThemePath(themeName)
self._themeDatas = loadThemeDatas(self._theme)
self.updateTheme()
def updateTheme(self):
# Reinit stored geometries for hiding widgets
self._geometries = {}
rect = self.geometry()
self._background = generateTheme(self._themeDatas, rect)
setThemeEditorDatas(self.editor, self._themeDatas, self._background, rect)
# Colors
if self._themeDatas["Foreground/Color"] == self._themeDatas["Background/Color"] or \
self._themeDatas["Foreground/Opacity"] < 5:
self._bgcolor = QColor(self._themeDatas["Text/Color"])
self._fgcolor = QColor(self._themeDatas["Background/Color"])
self._themeDatas["Foreground/Opacity"] < 5:
self._bgcolor = QColor(self._themeDatas["Text/Color"])
self._fgcolor = QColor(self._themeDatas["Background/Color"])
else:
self._bgcolor = QColor(self._themeDatas["Foreground/Color"])
self._bgcolor.setAlpha(self._themeDatas["Foreground/Opacity"] * 255 / 100)
self._fgcolor = QColor(self._themeDatas["Text/Color"])
if self._themeDatas["Text/Color"] == self._themeDatas["Foreground/Color"]:
self._fgcolor = QColor(self._themeDatas["Background/Color"])
# ScrollBar
r = self.editor.geometry()
w = qApp.style().pixelMetric(QStyle.PM_ScrollBarExtent)
r.setWidth(w)
r.moveRight(rect.right() - rect.left())
self.scrollBar.setGeometry(r)
#self.scrollBar.setVisible(False)
# self.scrollBar.setVisible(False)
self.hideWidget(self.scrollBar)
p = self.scrollBar.palette()
b = QBrush(self._background.copy(self.scrollBar.geometry()))
p.setBrush(QPalette.Base, b)
self.scrollBar.setPalette(p)
self.scrollBar.setColor(self._bgcolor)
# Left Panel
r = self.locker.geometry()
r.moveTopLeft(QPoint(
0,
self.geometry().height() / 2 - r.height() / 2
))
0,
self.geometry().height() / 2 - r.height() / 2
))
self.leftPanel.setGeometry(r)
self.hideWidget(self.leftPanel)
self.leftPanel.setColor(self._bgcolor)
# Top / Bottom Panels
r = QRect(0, 0, 0, 24)
r.setWidth(rect.width())
#r.moveLeft(rect.center().x() - r.width() / 2)
# r.moveLeft(rect.center().x() - r.width() / 2)
self.topPanel.setGeometry(r)
#self.topPanel.setVisible(False)
# self.topPanel.setVisible(False)
self.hideWidget(self.topPanel)
r.moveBottom(rect.bottom() - rect.top())
self.bottomPanel.setGeometry(r)
#self.bottomPanel.setVisible(False)
# self.bottomPanel.setVisible(False)
self.hideWidget(self.bottomPanel)
self.topPanel.setColor(self._bgcolor)
self.bottomPanel.setColor(self._bgcolor)
# Lst theme
#p = self.lstThemes.palette()
# p = self.lstThemes.palette()
p = self.palette()
p.setBrush(QPalette.Button, self._bgcolor)
p.setBrush(QPalette.ButtonText, self._fgcolor)
p.setBrush(QPalette.WindowText, self._fgcolor)
for panel in (self.bottomPanel, self.topPanel):
for i in range(panel.layout().count()):
item = panel.layout().itemAt(i)
if item.widget():
if item.widget():
item.widget().setPalette(p)
#self.lstThemes.setPalette(p)
#self.lblWC.setPalette(p)
# self.lstThemes.setPalette(p)
# self.lblWC.setPalette(p)
self.update()
def paintEvent(self, event):
if self._background:
painter = QPainter(self)
painter.setClipRegion(event.region())
painter.drawPixmap(event.rect(), self._background, event.rect())
painter.end()
def resizeEvent(self, event):
self.updateTheme()
def keyPressEvent(self, event):
if event.key() in [Qt.Key_Escape, Qt.Key_F11] and \
not self._locked:
not self._locked:
self.close()
else:
QWidget.keyPressEvent(self, event)
def mouseMoveEvent(self, event):
r = self.geometry()
for w in [self.scrollBar, self.topPanel,
for w in [self.scrollBar, self.topPanel,
self.bottomPanel, self.leftPanel]:
#w.setVisible(w.geometry().contains(event.pos()))
# w.setVisible(w.geometry().contains(event.pos()))
if self._geometries[w].contains(event.pos()):
self.showWidget(w)
else:
self.hideWidget(w)
def hideWidget(self, widget):
if widget not in self._geometries:
self._geometries[widget] = widget.geometry()
widget.move(self.geometry().bottomRight())
def showWidget(self, widget):
if widget in self._geometries:
widget.move(self._geometries[widget].topLeft())
def eventFilter(self, obj, event):
if obj == self.editor and event.type() == QEvent.Enter:
for w in [self.scrollBar, self.topPanel,
for w in [self.scrollBar, self.topPanel,
self.bottomPanel, self.leftPanel]:
#w.setVisible(False)
# w.setVisible(False)
self.hideWidget(w)
return QWidget.eventFilter(self, obj, event)
def dataChanged(self, topLeft, bottomRight):
if not self._index:
return
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateStatusBar()
def updateStatusBar(self):
if self._index:
item = self._index.internalPointer()
wc = item.data(Outline.wordCount.value)
goal = item.data(Outline.goal.value)
pg = item.data(Outline.goalPercentage.value)
if goal:
rect = self.lblProgress.geometry()
rect = QRect(QPoint(0, 0), rect.size())
@ -272,45 +278,47 @@ class fullScreenEditor(QWidget):
else:
self.lblProgress.hide()
self.lblWC.setText(self.tr("{} words").format(wc))
self.locker.setWordCount(wc)
if not self.locker.isLocked():
if goal - wc > 0:
self.locker.spnWordTarget.setValue(goal - wc)
class myScrollBar(QScrollBar):
def __init__(self, color=Qt.white, parent=None):
QScrollBar.__init__(self, parent)
self._color = color
#self.setAttribute(Qt.WA_TranslucentBackground)
# self.setAttribute(Qt.WA_TranslucentBackground)
self.timer = QTimer()
self.timer.setInterval(500)
self.timer.setSingleShot(True)
self.timer.timeout.connect(lambda: self.parent().hideWidget(self))
self.valueChanged.connect(lambda v: self.timer.start())
self.valueChanged.connect(lambda: self.parent().showWidget(self))
def setColor(self, color):
self._color = color
def paintEvent(self, event):
opt = QStyleOptionSlider()
self.initStyleOption(opt)
style = qApp.style()
painter = QPainter(self)
# Background (Necessary with Qt 5.2 it seems, not with 5.4)
#painter.save()
#painter.setPen(Qt.NoPen)
#painter.setBrush(self.palette().brush(QPalette.Base))
#painter.drawRect(event.rect())
#painter.restore()
#slider
# painter.save()
# painter.setPen(Qt.NoPen)
# painter.setBrush(self.palette().brush(QPalette.Base))
# painter.drawRect(event.rect())
# painter.restore()
# slider
r = style.subControlRect(style.CC_ScrollBar, opt, style.SC_ScrollBarSlider)
painter.fillRect(r, self._color)
painter.end()
class myPanel(QWidget):
def __init__(self, color=Qt.white, vertical=False, parent=None):
QWidget.__init__(self, parent)
@ -322,11 +330,11 @@ class myPanel(QWidget):
else:
self.setLayout(QVBoxLayout())
self.layout().setContentsMargins(0, 0, 0, 0)
def setColor(self, color):
self._color = color
def paintEvent(self, event):
r = event.rect()
painter = QPainter(self)
painter.fillRect(r, self._color)
painter.fillRect(r, self._color)

View file

@ -1,19 +1,16 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.editors.locker_ui import Ui_locker
from functions import *
import models.references as Ref
# --!-- coding: utf8 --!--
from PyQt5.QtCore import pyqtSignal, QTimer
from PyQt5.QtWidgets import QWidget, qApp
from manuskript.ui.editors.locker_ui import Ui_locker
class locker(QWidget, Ui_locker):
locked = pyqtSignal()
unlocked = pyqtSignal()
lockChanged = pyqtSignal(bool)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
@ -21,7 +18,7 @@ class locker(QWidget, Ui_locker):
self._words = None
self._target = None
self._blackout = []
self.timer = QTimer(self)
self.timer.setSingleShot(True)
self.timer.timeout.connect(self.unlock)
@ -34,9 +31,9 @@ class locker(QWidget, Ui_locker):
self.rbtnTimeTarget.toggled.connect(self.spnTimeTarget.setVisible)
self.rbtnWordTarget.setChecked(True)
self.spnTimeTarget.setVisible(False)
self.btnLock.clicked.connect(self.lock)
def lock(self):
# Block others screens
desktop = qApp.desktop()
@ -49,24 +46,24 @@ class locker(QWidget, Ui_locker):
w.move(desktop.screenGeometry(d).topLeft())
w.showFullScreen()
self._blackout.append(w)
if self.rbtnWordTarget.isChecked():
self._target = self._words + self.spnWordTarget.value()
elif self.rbtnTimeTarget.isChecked():
self.timer.setInterval(self.spnTimeTarget.value() * 1000 * 60)
self.timer.start()
self.timerSec.start()
self.updateBtnText()
self.setEnabled(False)
self.locked.emit()
self.lockChanged.emit(True)
def unlock(self):
# Remove black screens
self._blackout.clear()
self.setEnabled(True)
self.btnLock.setText(self._btnText)
self.timer.stop()
@ -74,21 +71,21 @@ class locker(QWidget, Ui_locker):
self._target = None
self.unlocked.emit()
self.lockChanged.emit(False)
def isLocked(self):
return not self.isEnabled()
def setWordCount(self, wc):
self._words = wc
if self.isLocked():
self.updateBtnText()
if self._words >= self._target:
self.unlock()
def updateBtnText(self):
if not self._btnText:
self._btnText = self.btnLock.text()
# Time locked
if self.timer.remainingTime() != -1:
t = self.timer.remainingTime()
@ -103,12 +100,11 @@ class locker(QWidget, Ui_locker):
text = self.tr("{}:{}").format(str(mn), str(sec))
else:
text = self.tr("{} s.").format(str(t))
self.btnLock.setText(self.tr("{} remaining").format(
text))
text))
# Word locked
elif self._target != None:
elif self._target is not None:
self.btnLock.setText(self.tr("{} words remaining").format(
self._target - self._words))
self._target - self._words))

View file

@ -1,49 +1,56 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.editors.mainEditor_ui import *
from ui.editors.editorWidget import *
from functions import *
# --!-- coding: utf8 --!--
import locale
from PyQt5.QtCore import QModelIndex, QRect, QPoint
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QPainter
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import qApp
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import AUC, mainWindow, drawProgress
from manuskript.ui.editors.editorWidget import editorWidget
from manuskript.ui.editors.fullScreenEditor import fullScreenEditor
from manuskript.ui.editors.mainEditor_ui import Ui_mainEditor
locale.setlocale(locale.LC_ALL, '')
class mainEditor(QWidget, Ui_mainEditor):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self._updating = False
self.mw = mainWindow()
self.tab.tabCloseRequested.connect(self.closeTab)
self.tab.currentChanged.connect(self.tabChanged)
# Connections --------------------------------------------------------
self.sldCorkSizeFactor.valueChanged.connect(
self.setCorkSizeFactor, AUC)
self.setCorkSizeFactor, AUC)
self.btnRedacFolderCork.toggled.connect(
self.sldCorkSizeFactor.setVisible, AUC)
self.sldCorkSizeFactor.setVisible, AUC)
self.btnRedacFolderText.clicked.connect(
lambda v: self.setFolderView("text"), AUC)
lambda v: self.setFolderView("text"), AUC)
self.btnRedacFolderCork.clicked.connect(
lambda v: self.setFolderView("cork"), AUC)
lambda v: self.setFolderView("cork"), AUC)
self.btnRedacFolderOutline.clicked.connect(
lambda v: self.setFolderView("outline"), AUC)
lambda v: self.setFolderView("outline"), AUC)
self.btnRedacFullscreen.clicked.connect(
self.showFullScreen, AUC)
###############################################################################
# TABS
###############################################################################
self.showFullScreen, AUC)
###############################################################################
# TABS
###############################################################################
def currentEditor(self):
return self.tab.currentWidget()
def tabChanged(self, index):
if self.currentEditor():
index = self.currentEditor().currentIndex
@ -56,61 +63,61 @@ class mainEditor(QWidget, Ui_mainEditor):
else:
index = QModelIndex()
hidden = False
self._updating = True
self.mw.treeRedacOutline.setCurrentIndex(index)
self._updating = False
self.updateStats()
self.updateThingsVisible(index)
def closeTab(self, index):
#FIXME: submit data if textedit?
# FIXME: submit data if textedit?
w = self.tab.widget(index)
self.tab.removeTab(index)
w.deleteLater()
def allTabs(self):
return [self.tab.widget(i) for i in range(self.tab.count())]
###############################################################################
# SELECTION AND UPDATES
###############################################################################
###############################################################################
# SELECTION AND UPDATES
###############################################################################
def selectionChanged(self):
if self._updating:
return
if len(self.mw.treeRedacOutline.selectionModel().
selection().indexes()) == 0:
selection().indexes()) == 0:
idx = QModelIndex()
else:
idx = self.mw.treeRedacOutline.currentIndex()
self.setCurrentModelIndex(idx)
self.updateThingsVisible(idx)
def openIndexes(self, indexes, newTab=False):
for i in indexes:
self.setCurrentModelIndex(i, newTab)
def setCurrentModelIndex(self, index, newTab=False):
if not index.isValid():
title = self.tr("Root")
else:
title = index.internalPointer().title()
# Checking if tab is already openned
for w in self.allTabs():
if w.currentIndex == index:
self.tab.setCurrentWidget(w)
return
if qApp.keyboardModifiers() & Qt.ControlModifier:
newTab = True
if newTab or not self.tab.count():
editor = editorWidget(self)
editor.setCurrentModelIndex(index)
@ -119,28 +126,26 @@ class mainEditor(QWidget, Ui_mainEditor):
else:
self.currentEditor().setCurrentModelIndex(index)
self.tab.setTabText(self.tab.currentIndex(), title)
###############################################################################
# UI
###############################################################################
###############################################################################
# UI
###############################################################################
def updateThingsVisible(self, index):
if index.isValid():
visible = index.internalPointer().isFolder()
else:
visible = True
# Hides / show textFormat
self.textFormat.updateFromIndex(index)
self.btnRedacFolderText.setVisible(visible)
self.btnRedacFolderCork.setVisible(visible)
self.btnRedacFolderOutline.setVisible(visible)
self.sldCorkSizeFactor.setVisible(visible)
self.btnRedacFullscreen.setVisible(not visible)
def updateFolderViewButtons(self, view):
if view == "text":
self.btnRedacFolderText.setChecked(True)
@ -148,26 +153,26 @@ class mainEditor(QWidget, Ui_mainEditor):
self.btnRedacFolderCork.setChecked(True)
elif view == "outline":
self.btnRedacFolderOutline.setChecked(True)
def updateStats(self):
if not self.currentEditor():
return
index = self.currentEditor().currentIndex
if index.isValid():
item = index.internalPointer()
else:
item = self.mw.mdlOutline.rootItem
if not item:
item = self.mw.mdlOutline.rootItem
wc = item.data(Outline.wordCount.value)
goal = item.data(Outline.goal.value)
progress = item.data(Outline.goalPercentage.value)
#mw = qApp.activeWindow()
# mw = qApp.activeWindow()
if not wc:
wc = 0
if goal:
@ -181,53 +186,51 @@ class mainEditor(QWidget, Ui_mainEditor):
del p
self.lblRedacProgress.setPixmap(self.px)
self.lblRedacWC.setText(self.tr("{} words / {}").format(
locale.format("%d", wc, grouping=True),
locale.format("%d", goal, grouping=True)))
locale.format("%d", wc, grouping=True),
locale.format("%d", goal, grouping=True)))
else:
self.lblRedacProgress.hide()
self.lblRedacWC.setText(self.tr("{} words").format(
locale.format("%d", wc, grouping=True)))
###############################################################################
# VIEWS
###############################################################################
locale.format("%d", wc, grouping=True)))
###############################################################################
# VIEWS
###############################################################################
def setFolderView(self, view):
if self.currentEditor():
self.currentEditor().setFolderView(view)
def setCorkSizeFactor(self, val):
for w in self.allTabs():
w.setCorkSizeFactor(val)
settings.corkSizeFactor = val
def updateCorkView(self):
for w in self.allTabs():
w.corkView.viewport().update()
def updateCorkBackground(self):
for w in self.allTabs():
w.corkView.updateBackground()
def updateTreeView(self):
for w in self.allTabs():
w.outlineView.viewport().update()
def showFullScreen(self):
if self.currentEditor():
self._fullScreen = fullScreenEditor(self.currentEditor().currentIndex)
###############################################################################
# DICT AND STUFF LIKE THAT
###############################################################################
###############################################################################
# DICT AND STUFF LIKE THAT
###############################################################################
def setDict(self, dict):
print(dict)
for w in self.allTabs():
w.setDict(dict)
def toggleSpellcheck(self, val):
for w in self.allTabs():
w.toggleSpellcheck(val)

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/editors/mainEditor_ui.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
@ -94,4 +94,4 @@ class Ui_mainEditor(object):
self.btnRedacFolderOutline.setText(_translate("mainEditor", "Outline"))
self.btnRedacFullscreen.setShortcut(_translate("mainEditor", "F11"))
from ui.editors.textFormat import textFormat
from manuskript.ui.editors.textFormat import textFormat

View file

@ -201,7 +201,7 @@
<customwidget>
<class>textFormat</class>
<extends>QWidget</extends>
<header>ui.editors.textFormat.h</header>
<header>manuskript.ui.editors.textFormat.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View file

@ -1,9 +1,12 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from qt import *
import re
from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QTextCursor
def t2tFormatSelection(editor, style):
"""
Formats the current selection of ``editor`` in the format given by ``style``,
@ -54,7 +57,7 @@ def t2tFormatSelection(editor, style):
# Adjusts selection to exclude the markup
while text[start:start + 1] == formatChar:
start += 1
while text[end - 1:end] ==formatChar:
while text[end - 1:end] == formatChar:
end -= 1
# Get the text without formatting, and the array of format
@ -69,12 +72,12 @@ def t2tFormatSelection(editor, style):
# have some unformated text in the selection, so we format the
# whole selection
propperArray = propperArray[:tStart] + [1] * \
(tEnd - tStart) + propperArray[tEnd:]
(tEnd - tStart) + propperArray[tEnd:]
else:
# The whole selection is already formatted, so we remove the
# formatting
propperArray = propperArray[:tStart] + [0] * \
(tEnd - tStart) + propperArray[tEnd:]
(tEnd - tStart) + propperArray[tEnd:]
fArray = fArray[0:style] + [propperArray] + fArray[style + 1:]
@ -92,8 +95,9 @@ def t2tFormatSelection(editor, style):
editor.setTextCursor(cursor)
def t2tClearFormat(editor):
"Clears format on ``editor``'s current selection."
"""Clears format on ``editor``'s current selection."""
cursor = editor.textCursor()
cursor.beginEditBlock()
@ -105,6 +109,7 @@ def t2tClearFormat(editor):
cursor.endEditBlock()
editor.setTextCursor(cursor)
def textToFormatArray(text):
"""
Take some text and returns an array of array containing informations
@ -140,7 +145,7 @@ def textToFormatArray(text):
pos = r.indexIn(text, 0)
lastPos = 0
while pos >= 0:
#We have a winner
# We have a winner
rList += [0] * (pos - lastPos)
rList += [2] * 2
rList += [1] * len(r.cap(2))
@ -231,7 +236,7 @@ def reformatText(text, markupArray):
markup = ["**", "//", "__", "--", "``", "''"]
for k, m in enumerate(markupArray):
#m = markupArray[k]
# m = markupArray[k]
_open = False # Are we in an _openned markup
d = 0
alreadySeen = []
@ -256,7 +261,7 @@ def reformatText(text, markupArray):
for j, m2 in enumerate(markupArray):
# The other array still have the same length
if j > k:
#Insert 2 for bold, 3 for italic, etc.
# Insert 2 for bold, 3 for italic, etc.
m2.insert(i + d, k + 2)
m2.insert(i + d, k + 2)
alreadySeen = []
@ -267,24 +272,24 @@ def reformatText(text, markupArray):
for j, m2 in enumerate(markupArray):
# The other array still have the same length
if j > k:
#Insert 2 for bold, 3 for italic, etc.
# Insert 2 for bold, 3 for italic, etc.
m2.insert(i + d, k + 2)
m2.insert(i + d, k + 2)
text = rText
rText = ""
## Clean up
# Clean up
# Exclude first and last space of the markup
for markup in ["\*", "/", "_", "-", "`", "\'"]:
#r = QRegExp(r'(' + markup * 2 + ')(\s+)(.+)(' + markup * 2 + ')')
#r.setMinimal(True)
#text.replace(r, "\\2\\1\\3\\4")
# r = QRegExp(r'(' + markup * 2 + ')(\s+)(.+)(' + markup * 2 + ')')
# r.setMinimal(True)
# text.replace(r, "\\2\\1\\3\\4")
text = re.sub(r'(' + markup * 2 + ')(\s+?)(.+?)(' + markup * 2 + ')',
"\\2\\1\\3\\4",
text)
#r = QRegExp(r'(' + markup * 2 + ')(.+)(\s+)(' + markup * 2 + ')')
#r.setMinimal(True)
#text.replace(r, "\\1\\2\\4\\3")
# r = QRegExp(r'(' + markup * 2 + ')(.+)(\s+)(' + markup * 2 + ')')
# r.setMinimal(True)
# text.replace(r, "\\1\\2\\4\\3")
text = re.sub(r'(' + markup * 2 + ')(.+?)(\s+?)(' + markup * 2 + ')',
"\\1\\2\\4\\3",
text)
@ -293,7 +298,7 @@ def reformatText(text, markupArray):
def cleanFormat(text):
"Makes markup clean (removes doubles, etc.)"
"""Makes markup clean (removes doubles, etc.)"""
t, a = textToFormatArrayNoMarkup(text)
return reformatText(t, a)
@ -327,7 +332,7 @@ class State:
RAW_AREA_ENDS = 20
TAGGED_AREA_BEGINS = 21
TAGGED_AREA_ENDS = 22
#LINE
# LINE
COMMENT_LINE = 30
CODE_LINE = 31
RAW_LINE = 32
@ -346,7 +351,7 @@ class State:
# TABLE
TABLE_LINE = 50
TABLE_HEADER = 51
#OTHER
# OTHER
MARKUP = 60
LINKS = 61
MACRO = 62
@ -368,4 +373,4 @@ class State:
State.NUMBERED_TITLE_3: 3,
State.NUMBERED_TITLE_4: 4,
State.NUMBERED_TITLE_5: 5,
}.get(state, -1)
}.get(state, -1)

View file

@ -1,22 +1,26 @@
#!/usr/bin/python
# -*- coding: utf8 -*-
from qt import *
from ui.editors.t2tFunctions import *
from ui.editors.blockUserData import blockUserData
from ui.editors.t2tHighlighterStyle import t2tHighlighterStyle
from ui.editors.basicHighlighter import *
import re
# This is aiming at implementing every rule from www.txt2tags.org/rules.html
# But we're not there yet.
#FIXME: macro words not hilighted properly if at the begining of a line.
# FIXME: macro words not hilighted properly if at the begining of a line.
#TODO: parse %!postproc et !%preproc, et si la ligne se termine par une couleur en commentaire (%#FF00FF), utiliser cette couleur pour highlighter. Permet des règles customisées par document, facilement.
# TODO: parse %!postproc et !%preproc, et si la ligne se termine par une couleur en commentaire (%#FF00FF),
# utiliser cette couleur pour highlighter. Permet des règles customisées par document, facilement.
import re
from PyQt5.QtCore import QRegExp, QDir, QFileInfo
from PyQt5.QtGui import QTextBlockFormat, QTextCursor, QTextCharFormat, QBrush
from manuskript.ui.editors.basicHighlighter import basicHighlighter
from manuskript.ui.editors.blockUserData import blockUserData
from manuskript.ui.editors.t2tFunctions import State, textToFormatArray
from manuskript.ui.editors.t2tHighlighterStyle import t2tHighlighterStyle
class t2tHighlighter (basicHighlighter):
class t2tHighlighter(basicHighlighter):
"""Syntax highlighter for the Txt2Tags language.
"""
@ -25,9 +29,9 @@ class t2tHighlighter (basicHighlighter):
# Stupid variable that fixes the loss of QTextBlockUserData.
self.thisDocument = editor.document()
self.style = t2tHighlighterStyle(self.editor, self._defaultCharFormat, style)
self.inDocRules = []
rules = [
@ -63,25 +67,25 @@ class t2tHighlighter (basicHighlighter):
self._defaultCharFormat = cf
self.setStyle()
self.rehighlight()
def highlightBlock(self, text):
"""Apply syntax highlighting to the given block of text.
"""
basicHighlighter.highlightBlockBefore(self, text)
# Check if syntax highlighting is enabled
if self.style is None:
default = QTextBlockFormat()
QTextCursor(self.currentBlock()).setBlockFormat(default)
print("t2tHighlighter.py: is style supposed to be None?")
return
block = self.currentBlock()
oldState = blockUserData.getUserState(block)
self.identifyBlock(block)
# formatBlock prevent undo/redo from working
# TODO: find a todo/undo compatible way of formatting block
#self.formatBlock(block)
# self.formatBlock(block)
state = blockUserData.getUserState(block)
data = blockUserData.getUserData(block)
@ -89,14 +93,15 @@ class t2tHighlighter (basicHighlighter):
op = self.style.format(State.MARKUP)
#self.setFormat(0, len(text), self.style.format(State.DEFAULT))
# self.setFormat(0, len(text), self.style.format(State.DEFAULT))
# InDocRules: is it a settings which might have a specific rule,
# a comment which contains color infos, or a include conf?
# r'^%!p[or][se]t?proc[^\s]*\s*:\s*\'(.*)\'\s*\'.*\''
rlist = [QRegExp(r'^%!p[or][se]t?proc[^\s]*\s*:\s*((\'[^\']*\'|\"[^\"]*\")\s*(\'[^\']*\'|\"[^\"]*\"))'), # pre/postproc
QRegExp(r'^%.*\s\((.*)\)'), # comment
QRegExp(r'^%!includeconf:\s*([^\s]*)\s*')] # includeconf
rlist = [QRegExp(r'^%!p[or][se]t?proc[^\s]*\s*:\s*((\'[^\']*\'|\"[^\"]*\")\s*(\'[^\']*\'|\"[^\"]*\"))'),
# pre/postproc
QRegExp(r'^%.*\s\((.*)\)'), # comment
QRegExp(r'^%!includeconf:\s*([^\s]*)\s*')] # includeconf
for r in rlist:
if r.indexIn(text) != -1:
self.parseInDocRules()
@ -106,7 +111,7 @@ class t2tHighlighter (basicHighlighter):
State.BLOCKQUOTE_LINE,
State.HORIZONTAL_LINE,
State.HEADER_LINE,
]:
]:
if not inList and state == lineState:
self.setFormat(0, len(text), self.style.format(lineState))
@ -116,9 +121,9 @@ class t2tHighlighter (basicHighlighter):
(State.RAW_LINE, "\"\"\""),
(State.TAGGED_LINE, "'''"),
(State.SETTINGS_LINE, "%!")
]:
]:
if state == lineState and \
not (inList and state == State.SETTINGS_LINE):
not (inList and state == State.SETTINGS_LINE):
n = 0
# If it's a comment, we want to highlight all '%'.
if state == State.COMMENT_LINE:
@ -140,9 +145,9 @@ class t2tHighlighter (basicHighlighter):
setting = r.cap(1)
val = r.cap(2)
if setting == "target" and \
val in self.editor.main.targetsNames:
val in self.editor.main.targetsNames:
self.editor.fileWidget.preview.setPreferredTarget(val)
# Pre/postproc
r = QRegExp(r'^%!p[or][se]t?proc[^\s]*\s*:\s*((\'[^\']*\'|\"[^\"]*\")\s*(\'[^\']*\'|\"[^\"]*\"))')
if r.indexIn(text) != -1:
@ -161,15 +166,15 @@ class t2tHighlighter (basicHighlighter):
self.setFormat(i, 1, self.style.format(lineState))
# Lists
#if text == " p": print(data.isList())
# if text == " p": print(data.isList())
if data.isList():
r = QRegExp(r'^\s*[\+\-\:]? ?')
r.indexIn(text)
self.setFormat(0, r.matchedLength(), self.style.format(State.LIST_BULLET))
#if state == State.LIST_BEGINS:
#r = QRegExp(r'^\s*[+-:] ')
#r.indexIn(text)
#self.setFormat(0, r.matchedLength(), self.style.format(State.LIST_BULLET))
# if state == State.LIST_BEGINS:
# r = QRegExp(r'^\s*[+-:] ')
# r.indexIn(text)
# self.setFormat(0, r.matchedLength(), self.style.format(State.LIST_BULLET))
if state == State.LIST_ENDS:
self.setFormat(0, len(text), self.style.format(State.LIST_BULLET_ENDS))
@ -181,8 +186,8 @@ class t2tHighlighter (basicHighlighter):
if pos >= 0:
f = self.style.format(state)
# Uncomment for markup to be same size as title
#op = self.formats(preset="markup",
#base=self.formats(preset=state))
# op = self.formats(preset="markup",
# base=self.formats(preset=state))
self.setFormat(r.pos(2), len(r.cap(2)), f)
self.setFormat(r.pos(1), len(r.cap(1)), op)
self.setFormat(r.pos(3), len(r.cap(3)), op)
@ -193,7 +198,7 @@ class t2tHighlighter (basicHighlighter):
(State.CODE_AREA_BEGINS, State.CODE_AREA, State.CODE_AREA_ENDS),
(State.RAW_AREA_BEGINS, State.RAW_AREA, State.RAW_AREA_ENDS),
(State.TAGGED_AREA_BEGINS, State.TAGGED_AREA, State.TAGGED_AREA_ENDS),
]:
]:
if state == middle:
self.setFormat(0, len(text), self.style.format(middle))
@ -202,8 +207,8 @@ class t2tHighlighter (basicHighlighter):
# Inline formatting
if state not in [
#State.COMMENT_AREA,
#State.COMMENT_LINE,
# State.COMMENT_AREA,
# State.COMMENT_LINE,
State.RAW_AREA,
State.RAW_LINE,
State.CODE_AREA,
@ -212,7 +217,7 @@ class t2tHighlighter (basicHighlighter):
State.TAGGED_LINE,
State.SETTINGS_LINE,
State.HORIZONTAL_LINE,
] and state not in State.TITLES:
] and state not in State.TITLES:
formatArray = textToFormatArray(text)
# InDocRules
@ -224,10 +229,10 @@ class t2tHighlighter (basicHighlighter):
if "," in c:
c1, c2 = c.split(",")
self.setFormat(m.start(), l,
self.style.makeFormat(color=c1, bgcolor=c2, base=f))
self.style.makeFormat(color=c1, bgcolor=c2, base=f))
else:
self.setFormat(m.start(), l,
self.style.makeFormat(color=c, base=f))
self.style.makeFormat(color=c, base=f))
# Links
if state not in [State.COMMENT_LINE, State.COMMENT_AREA]:
@ -236,8 +241,8 @@ class t2tHighlighter (basicHighlighter):
pos = r.indexIn(text)
links = []
while pos >= 0:
#TODO: The text should not be formatted if [**not bold**]
#if max([k[pos] for k in formatArray]) == 0 or 1 == 1:
# TODO: The text should not be formatted if [**not bold**]
# if max([k[pos] for k in formatArray]) == 0 or 1 == 1:
self.setFormat(pos, 1,
self.style.format(State.MARKUP))
self.setFormat(pos + 1, len(r.cap(0)) - 1,
@ -247,29 +252,29 @@ class t2tHighlighter (basicHighlighter):
if r.pos(2) > 0:
_f = QTextCharFormat(self.style.format(State.LINKS))
_f.setForeground(QBrush(_f.foreground()
.color().lighter()))
.color().lighter()))
_f.setFontUnderline(True)
self.setFormat(r.pos(2), len(r.cap(2)), _f)
links.append([pos, len(r.cap(0))]) # To remember for the next highlighter (single links)
links.append([pos, len(r.cap(0))]) # To remember for the next highlighter (single links)
pos = r.indexIn(text, pos + 1)
# Links like www.theologeek.ch, http://www.fsf.org, ...
# FIXME: - "http://adresse et http://adresse" is detected also as italic
# - some error, like "http://adress.htm." also color the final "."
# - also: adresse@email.com, ftp://, www2, www3, etc.
# - But for now, does the job
r = QRegExp(r'http://[^\s]*|www\.[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+[^\s]*')
#r.setMinimal(True)
# r.setMinimal(True)
pos = r.indexIn(text)
while pos >= 0:
for k in links:
#print pos, k[0], k[1]
if pos > k[0] and pos < k[0] + k[1]: # already highlighted
# print pos, k[0], k[1]
if k[0] < pos < k[0] + k[1]: # already highlighted
break
else:
self.setFormat(pos, len(r.cap(0)), self.style.format(State.LINKS))
pos = r.indexIn(text, pos + 1)
# Bold, Italic, Underline, Code, Tagged, Strikeout
@ -288,40 +293,39 @@ class t2tHighlighter (basicHighlighter):
self.setFormat(pos, len(r.cap(0)),
self.style.format(State.MACRO))
pos = r.indexIn(text, pos + 1)
# Highlighted word (for search)
if self.editor.highlightWord:
if self.editor.highligtCS and self.editor.highlightWord in text or \
not self.editor.highlightCs and self.editor.highlightWord.lower() in text.lower():
#if self.editor.highlightCS:
#s = self.editor.highlightWord
#else:
#s = self.editor.highlightWord.toLower()
#print(s)
not self.editor.highlightCs and self.editor.highlightWord.lower() in text.lower():
# if self.editor.highlightCS:
# s = self.editor.highlightWord
# else:
# s = self.editor.highlightWord.toLower()
# print(s)
p = text.indexOf(self.editor.highlightWord, cs=self.editor.highlightCS)
while p >= 0:
self.setFormat(p, len(self.editor.highlightWord),
self.style.makeFormat(preset="higlighted", base=self.format(p)))
p = text.indexOf(self.editor.highlightWord, p + 1, cs=self.editor.highlightCS)
### Highlight Selection
### TODO: way to slow, find another way.
##sel = self.editor.textCursor().selectedText()
##if len(sel) > 5: self.keywordRules.append((QRegExp(sel), "selected"))
## Do keyword formatting
#for expression, style in self.keywordRules:
#expression.setMinimal( True )
#index = expression.indexIn(text, 0)
### Highlight Selection
### TODO: way to slow, find another way.
##sel = self.editor.textCursor().selectedText()
##if len(sel) > 5: self.keywordRules.append((QRegExp(sel), "selected"))
## Do keyword formatting
# for expression, style in self.keywordRules:
# expression.setMinimal( True )
# index = expression.indexIn(text, 0)
## There might be more than one on the same line
# while index >= 0:
# length = expression.cap(0).length()
# f = self.formats(preset=style, base=self.formats(index))
# self.setFormat(index, length, f)
# index = expression.indexIn(text, index + length)
## There might be more than one on the same line
#while index >= 0:
#length = expression.cap(0).length()
#f = self.formats(preset=style, base=self.formats(index))
#self.setFormat(index, length, f)
#index = expression.indexIn(text, index + length)
basicHighlighter.highlightBlockAfter(self, text)
def identifyBlock(self, block):
@ -333,20 +337,20 @@ class t2tHighlighter (basicHighlighter):
# Header Lines
# No header line here
#if block.blockNumber() == 0:
#block.setUserState(State.HEADER_LINE)
#return
#elif block.blockNumber() in [1, 2] and \
#self.document().findBlockByNumber(0).text():
#block.setUserState(State.HEADER_LINE)
#return
# if block.blockNumber() == 0:
# block.setUserState(State.HEADER_LINE)
# return
# elif block.blockNumber() in [1, 2] and \
# self.document().findBlockByNumber(0).text():
# block.setUserState(State.HEADER_LINE)
# return
state = 0
inList = False
blankLinesBefore = 0
#if text.contains(QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$')):
if QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$').indexIn(text) != -1:
# if text.contains(QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$')):
if QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$').indexIn(text) != -1:
state = State.LIST_BEGINS
# List stuff
@ -354,12 +358,12 @@ class t2tHighlighter (basicHighlighter):
inList = True
# listLevel and leadingSpaces
#FIXME: not behaving exactly correctly...
# FIXME: not behaving exactly correctly...
lastData = blockUserData.getUserData(block.previous())
if state == State.LIST_BEGINS:
leadingSpaces = QRegExp(r'[-+:]').indexIn(text, 0)
data.setLeadingSpaces(leadingSpaces)
data.setListSymbol(text[leadingSpaces])
if self.isList(block.previous()):
# The last block was also a list.
@ -380,13 +384,13 @@ class t2tHighlighter (basicHighlighter):
# Blank lines before (two = end of list)
blankLinesBefore = self.getBlankLines(block.previous())
if not QRegExp(r'^\s*$').indexIn(block.previous().text()) != -1 and \
not blockUserData.getUserState(block.previous()) in [State.COMMENT_LINE,
State.COMMENT_AREA, State.COMMENT_AREA_BEGINS,
State.COMMENT_AREA_ENDS]:
not blockUserData.getUserState(block.previous()) in [State.COMMENT_LINE,
State.COMMENT_AREA, State.COMMENT_AREA_BEGINS,
State.COMMENT_AREA_ENDS]:
blankLinesBefore = 0
elif not blockUserData.getUserState(block.previous()) in \
[State.COMMENT_LINE, State.COMMENT_AREA,
State.COMMENT_AREA_BEGINS, State.COMMENT_AREA_ENDS]:
[State.COMMENT_LINE, State.COMMENT_AREA,
State.COMMENT_AREA_BEGINS, State.COMMENT_AREA_ENDS]:
blankLinesBefore += 1
if blankLinesBefore == 2:
# End of list.
@ -401,7 +405,7 @@ class t2tHighlighter (basicHighlighter):
(State.CODE_AREA_BEGINS, State.CODE_AREA, State.CODE_AREA_ENDS, "^```\s*$"),
(State.RAW_AREA_BEGINS, State.RAW_AREA, State.RAW_AREA_ENDS, "^\"\"\"\s*$"),
(State.TAGGED_AREA_BEGINS, State.TAGGED_AREA, State.TAGGED_AREA_ENDS, '^\'\'\'\s*$'),
]:
]:
if QRegExp(marker).indexIn(text) != -1:
if blockUserData.getUserState(block.previous()) in [begins, middle]:
@ -423,8 +427,8 @@ class t2tHighlighter (basicHighlighter):
break
if state in [State.BLOCKQUOTE_LINE, State.LIST_ENDS]:
#FIXME: doesn't work exactly. Closes only the current level, not
#FIXME: the whole list.
# FIXME: doesn't work exactly. Closes only the current level, not
# FIXME: the whole list.
inList = False
if inList and not state == State.LIST_BEGINS:
@ -439,8 +443,8 @@ class t2tHighlighter (basicHighlighter):
"""
Formats the block according to its state.
"""
#TODO: Use QTextDocument format presets, and QTextBlock's
#TODO: blockFormatIndex. And move that in t2tHighlighterStyle.
# TODO: Use QTextDocument format presets, and QTextBlock's
# TODO: blockFormatIndex. And move that in t2tHighlighterStyle.
state = block.userState()
blockFormat = QTextBlockFormat()
@ -451,7 +455,7 @@ class t2tHighlighter (basicHighlighter):
QTextCursor(block).setBlockFormat(blockFormat)
def getBlankLines(self, block):
"Returns if there is a blank line before in the list."
"""Returns if there is a blank line before in the list."""
state = block.userState()
if state >= 200:
return 1
@ -459,9 +463,9 @@ class t2tHighlighter (basicHighlighter):
return 0
def isList(self, block):
"Returns TRUE if the block is in a list."
if block.userState() == State.LIST_BEGINS or\
block.userState() >= 100:
"""Returns TRUE if the block is in a list."""
if block.userState() == State.LIST_BEGINS or \
block.userState() >= 100:
return True
def setStyle(self, style="Default"):
@ -481,7 +485,7 @@ class t2tHighlighter (basicHighlighter):
self.inDocRules = []
t = self.thisDocument.toPlainText()
# Get all conf files
confs = []
lines = t.split("\n")
@ -489,26 +493,26 @@ class t2tHighlighter (basicHighlighter):
r = QRegExp(r'^%!includeconf:\s*([^\s]*)\s*')
if r.indexIn(l) != -1:
confs.append(r.cap(1))
# Try to load conf files
for c in confs:
try:
import codecs
f = self.editor.fileWidget.file
d = QDir.cleanPath(QFileInfo(f).absoluteDir().absolutePath()+"/"+c)
d = QDir.cleanPath(QFileInfo(f).absoluteDir().absolutePath() + "/" + c)
file = codecs.open(d, 'r', "utf-8")
except:
print(("Error: cannot open {}.".format(c)))
continue
# We add the content to the current lines of the current document
lines += file.readlines() #lines.extend(file.readlines())
#b = self.thisDocument.firstBlock()
continue
# We add the content to the current lines of the current document
lines += file.readlines() # lines.extend(file.readlines())
# b = self.thisDocument.firstBlock()
lastColor = ""
#while b.isValid():
# while b.isValid():
for l in lines:
text = l #b.text()
text = l # b.text()
r = QRegExp(r'^%!p[or][se]t?proc[^\s]*\s*:\s*(\'[^\']*\'|\"[^\"]*\")\s*(\'[^\']*\'|\"[^\"]*\")')
if r.indexIn(text) != -1:
rule = r.cap(1)[1:-1]
@ -517,27 +521,27 @@ class t2tHighlighter (basicHighlighter):
self.inDocRules.append((str(rule), lastColor))
# Check if previous block is a comment like it should
else:
previousText = lines[lines.indexOf(l)-1] #b.previous().text()
previousText = lines[lines.indexOf(l) - 1] # b.previous().text()
r = QRegExp(r'^%.*\s\((.*)\)')
if r.indexIn(previousText) != -1:
lastColor = r.cap(1)
self.inDocRules.append((str(rule), lastColor))
else:
lastColor = ""
#b = b.next()
# b = b.next()
if oldRules != self.inDocRules:
#Rules have changed, we need to rehighlight
#print("Rules have changed.", len(self.inDocRules))
#self.rehighlight() # Doesn't work (seg fault), why?
# Rules have changed, we need to rehighlight
# print("Rules have changed.", len(self.inDocRules))
# self.rehighlight() # Doesn't work (seg fault), why?
pass
#b = self.thisDocument.firstBlock()
#while b.isValid():
#for (r, c) in self.inDocRules:
#r = QRegExp(r)
#pos = r.indexIn(b.text())
#if pos >= 0:
#print("rehighlighting:", b.text())
#self.rehighlightBlock(b)
#break
#b = b.next()
# b = self.thisDocument.firstBlock()
# while b.isValid():
# for (r, c) in self.inDocRules:
# r = QRegExp(r)
# pos = r.indexIn(b.text())
# if pos >= 0:
# print("rehighlighting:", b.text())
# self.rehighlightBlock(b)
# break
# b = b.next()

View file

@ -1,14 +1,17 @@
#!/usr/bin/python
# -*- coding: utf8 -*-
from qt import *
from ui.editors.t2tFunctions import *
from ui.editors.blockUserData import blockUserData
#TODO: creates a general way to generate styles (and edit/import/export)
# TODO: creates a general way to generate styles (and edit/import/export)
from PyQt5.QtCore import QRegExp, Qt
from PyQt5.QtGui import QFont, QTextBlockFormat, QColor, QFontMetrics, QTextCharFormat
from PyQt5.QtWidgets import qApp
from manuskript.ui.editors.blockUserData import blockUserData
from manuskript.ui.editors.t2tFunctions import State
class t2tHighlighterStyle ():
class t2tHighlighterStyle():
"""Style for the Syntax highlighter for the Txt2Tags language.
"""
@ -21,15 +24,15 @@ class t2tHighlighterStyle ():
self._defaultCharFormat = charFormat
# Defaults
#self.defaultFontPointSize = self.editor.defaultFontPointSize
# self.defaultFontPointSize = self.editor.defaultFontPointSize
self.defaultFontFamily = qApp.font().family()
self.tabStopWidth = 40
self.setupEditor()
if self.name == "Default":
self.initDefaults()
#Temporary other theme
# Temporary other theme
elif self.name == "Monospace":
self.defaultFontFamily = "Monospace"
self.initDefaults()
@ -46,42 +49,42 @@ class t2tHighlighterStyle ():
def initDefaults(self):
self.styles = {}
for i in [State.CODE_AREA,
State.CODE_LINE,
State.COMMENT_AREA,
State.COMMENT_LINE,
State.SETTINGS_LINE,
State.BLOCKQUOTE_LINE,
State.RAW_AREA,
State.RAW_LINE,
State.TAGGED_AREA,
State.TAGGED_LINE,
State.TITLE_1,
State.TITLE_2,
State.TITLE_3,
State.TITLE_4,
State.TITLE_5,
State.NUMBERED_TITLE_1,
State.NUMBERED_TITLE_2,
State.NUMBERED_TITLE_3,
State.NUMBERED_TITLE_4,
State.NUMBERED_TITLE_5,
State.TABLE_HEADER,
State.TABLE_LINE,
State.HORIZONTAL_LINE,
State.MARKUP,
State.LIST_BULLET,
State.LIST_BULLET_ENDS,
State.LINKS,
State.MACRO,
State.DEFAULT,
State.HEADER_LINE]:
State.CODE_LINE,
State.COMMENT_AREA,
State.COMMENT_LINE,
State.SETTINGS_LINE,
State.BLOCKQUOTE_LINE,
State.RAW_AREA,
State.RAW_LINE,
State.TAGGED_AREA,
State.TAGGED_LINE,
State.TITLE_1,
State.TITLE_2,
State.TITLE_3,
State.TITLE_4,
State.TITLE_5,
State.NUMBERED_TITLE_1,
State.NUMBERED_TITLE_2,
State.NUMBERED_TITLE_3,
State.NUMBERED_TITLE_4,
State.NUMBERED_TITLE_5,
State.TABLE_HEADER,
State.TABLE_LINE,
State.HORIZONTAL_LINE,
State.MARKUP,
State.LIST_BULLET,
State.LIST_BULLET_ENDS,
State.LINKS,
State.MACRO,
State.DEFAULT,
State.HEADER_LINE]:
self.styles[i] = self.makeFormat(preset=i)
def format(self, state):
return self.styles[state]
def beautifyFormat(self, base, beautifiers):
"Apply beautifiers given in beautifiers array to format"
"""Apply beautifiers given in beautifiers array to format"""
if max(beautifiers) == 2:
return self.makeFormat(preset=State.MARKUP, base=base)
else:
@ -100,21 +103,21 @@ class t2tHighlighterStyle ():
return base
def formatBlock(self, block, state):
"Apply transformation to given block."
"""Apply transformation to given block."""
blockFormat = QTextBlockFormat()
if state == State.BLOCKQUOTE_LINE:
# Number of tabs
n = block.text().indexOf(QRegExp(r'[^\t]'), 0)
blockFormat.setIndent(0)
blockFormat.setTextIndent(-self.tabStopWidth * n)
blockFormat.setLeftMargin(self.tabStopWidth * n)
#blockFormat.setRightMargin(self.editor.contentsRect().width()
# - self.editor.lineNumberAreaWidth()
# - fm.width("X") * self.editor.LimitLine
#+ self.editor.tabStopWidth())
# blockFormat.setRightMargin(self.editor.contentsRect().width()
# - self.editor.lineNumberAreaWidth()
# - fm.width("X") * self.editor.LimitLine
# + self.editor.tabStopWidth())
blockFormat.setAlignment(Qt.AlignJustify)
if self.name == "Default" :
if self.name == "Default":
blockFormat.setTopMargin(5)
blockFormat.setBottomMargin(5)
elif state == State.HEADER_LINE:
@ -126,32 +129,33 @@ class t2tHighlighterStyle ():
else:
blockFormat.setBackground(QColor("#EEEEFA"))
n = blockUserData.getUserData(block).leadingSpaces() + 1
f = QFontMetrics(QFont(self.defaultFontFamily,
self._defaultCharFormat.font().pointSize()))
fm = f.width(" " * n +
blockUserData.getUserData(block).listSymbol())
blockFormat.setTextIndent(-fm)
blockFormat.setLeftMargin(fm)
if blockUserData.getUserState(block) == State.LIST_BEGINS and\
self.name == "Default":
if blockUserData.getUserState(block) == State.LIST_BEGINS and \
self.name == "Default":
blockFormat.setTopMargin(5)
return blockFormat
def makeFormat(self, color='', style='', size='', base='', fixedPitch='',
preset='', title_level='', bgcolor=''):
preset='', title_level='', bgcolor=''):
"""
Returns a QTextCharFormat with the given attributes, using presets.
"""
_color = QColor()
#_format = QTextCharFormat()
#_format.setFont(self.editor.font())
#size = _format.fontPointSize()
# _format = QTextCharFormat()
# _format.setFont(self.editor.font())
# size = _format.fontPointSize()
_format = QTextCharFormat(self._defaultCharFormat)
# Base
if base: _format = base
if base:
_format = base
# Presets
if preset in [State.CODE_AREA, State.CODE_LINE, "code"]:
@ -165,15 +169,15 @@ class t2tHighlighterStyle ():
color = "darkGreen"
if preset in [State.SETTINGS_LINE, "setting", State.MACRO]:
#style = "italic"
# style = "italic"
color = "magenta"
if preset in [State.BLOCKQUOTE_LINE]:
color = "red"
if preset in [State.HEADER_LINE]:
size = size * 2
#print size
size *= 2
# print size
if preset in [State.RAW_AREA, State.RAW_LINE, "raw"]:
color = "blue"
@ -198,7 +202,7 @@ class t2tHighlighterStyle ():
color = "red"
style = "bold"
fixedPitch = True
if preset == State.LIST_BULLET_ENDS:
color = "darkGray"
fixedPitch = True
@ -211,18 +215,18 @@ class t2tHighlighterStyle ():
fixedPitch = True
if preset == State.LINKS:
color="blue"
#style="underline"
color = "blue"
# style="underline"
if preset == "selected":
_format.setBackground(QColor("yellow"))
if preset == "higlighted":
bgcolor = "yellow"
#if preset == State.DEFAULT:
#size = self.defaultFontPointSize
#_format.setFontFamily(self.defaultFontFamily)
# if preset == State.DEFAULT:
# size = self.defaultFontPointSize
# _format.setFontFamily(self.defaultFontFamily)
# Manual formatting
if color:
@ -244,5 +248,5 @@ class t2tHighlighterStyle ():
_format.setFontPointSize(size)
if fixedPitch:
_format.setFontFixedPitch(True)
return _format

View file

@ -1,30 +1,30 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.editors.textFormat_ui import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QAction
from manuskript.enums import Outline
from manuskript.models.outlineModel import outlineModel
from manuskript.ui.editors.textFormat_ui import Ui_textFormat
class textFormat(QWidget, Ui_textFormat):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self._textEdit = None
formats = {
"Bold": [self.btnBold, "format-text-bold", self.tr("CTRL+B")],
"Italic": [self.btnItalic, "format-text-italic", self.tr("CTRL+I")],
"Bold": [self.btnBold, "format-text-bold", self.tr("CTRL+B")],
"Italic": [self.btnItalic, "format-text-italic", self.tr("CTRL+I")],
"Underline": [self.btnUnderlined, "format-text-underline", self.tr("CTRL+U")],
"Clear": [self.btnClear, "edit-clear", self.tr("CTRL+P")],
"Left": [self.btnLeft, "format-justify-left", self.tr("CTRL+L")],
"Center": [self.btnCenter, "format-justify-center", self.tr("CTRL+E")],
"Right": [self.btnRight, "format-justify-right", self.tr("CTRL+R")],
"Justify": [self.btnJustify, "format-justify-fill", self.tr("CTRL+J")],
}
"Clear": [self.btnClear, "edit-clear", self.tr("CTRL+P")],
"Left": [self.btnLeft, "format-justify-left", self.tr("CTRL+L")],
"Center": [self.btnCenter, "format-justify-center", self.tr("CTRL+E")],
"Right": [self.btnRight, "format-justify-right", self.tr("CTRL+R")],
"Justify": [self.btnJustify, "format-justify-fill", self.tr("CTRL+J")],
}
for f in formats:
val = formats[f]
a = QAction(QIcon.fromTheme(val[1]), f, self)
@ -32,41 +32,40 @@ class textFormat(QWidget, Ui_textFormat):
a.setToolTip("Format {} ({})".format(f, val[2]))
a.triggered.connect(self.setFormat)
val[0].setDefaultAction(a)
def setTextEdit(self, textEdit):
self._textEdit = textEdit
def updateFromIndex(self, index):
if not index.isValid():
self.setVisible(False)
return
if type(index.model()) != outlineModel:
self.setVisible(False)
return
return
if index.column() not in [Outline.text.value, Outline.notes.value]:
self.setVisible(False)
return
return
self.setVisible(True)
item = index.internalPointer()
self.align.setVisible(True)
self.format.setVisible(True)
if item.isFolder():
self.setVisible(False)
return
elif item.isText():
self.align.setVisible(False)
self.format.setVisible(False)
elif item.isT2T():
self.align.setVisible(False)
def setFormat(self):
act = self.sender()
if self._textEdit:
self._textEdit.applyFormat(act.text())
self._textEdit.applyFormat(act.text())

View file

@ -1,27 +1,30 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- 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 os
import re
from PyQt5.QtCore import QSettings, QRect, QSize, Qt, QPoint, QFile, QIODevice, QTextStream
from PyQt5.QtGui import QPixmap, QPainter, QColor, QBrush, QImage, QTextBlockFormat, QTextCharFormat, QFont, qGray
from PyQt5.QtWidgets import qApp, QFrame
from manuskript.functions import allPaths, appPath
from manuskript.ui.views.textEditView import textEditView
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)
@ -30,43 +33,45 @@ def loadThemeDatas(themeFile):
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
@ -77,33 +82,35 @@ def themeTextRect(themeDatas, screenRect):
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.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.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:
@ -111,9 +118,11 @@ def findThemePath(themeName):
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:
@ -121,35 +130,36 @@ def findFirstFile(regex, path="resources"):
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
if _type == 1: # Tiled
painter.fillRect(screenRect, QBrush(QImage(path)))
else:
img = QImage(path)
scaled = img.size()
if _type == 3: # Stretched
if _type == 3: # Stretched
scaled.scale(screenRect.size(), Qt.IgnoreAspectRatio)
elif _type == 4: # Scaled
elif _type == 4: # Scaled
scaled.scale(screenRect.size(), Qt.KeepAspectRatio)
elif _type == 5: # Zoomed
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))
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)
@ -158,19 +168,20 @@ def generateTheme(themeDatas, screenRect):
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)
@ -178,51 +189,51 @@ def getThemeBlockFormat(themeDatas):
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 = 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)
# 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()
# 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)
# 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.setFont(f)
editor.setStyleSheet("""
background: transparent;
color: {foreground};
@ -236,15 +247,13 @@ def setThemeEditorDatas(editor, themeDatas, pixmap, screenRect):
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)
@ -253,11 +262,11 @@ def addThemePreviewText(pixmap, themeDatas, screenRect):
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"]
@ -266,15 +275,15 @@ def addThemePreviewText(pixmap, themeDatas, screenRect):
##themeDatas["Foreground/Position"]
##themeDatas["Foreground/Rounding"]
##themeDatas["Foreground/Width"]
## Text Options
##themeDatas["Text/Color"]
##themeDatas["Text/Font"]
#themeDatas["Text/Misspelled"]
# themeDatas["Text/Misspelled"]
## Paragraph Options
##themeDatas["Spacings/IndendFirstLine"]
##themeDatas["Spacings/LineSpacing"]
##themeDatas["Spacings/ParagraphAbove"]
##themeDatas["Spacings/ParagraphBelow"]
##themeDatas["Spacings/TabWidth"]
##themeDatas["Spacings/TabWidth"]

View file

@ -1,20 +1,16 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QLabel, QSizePolicy
from qt import *
class helpLabel(QLabel):
def __init__(self, text=None, parent=None):
QLabel.__init__(self, text, parent)
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
self.setStatusTip(self.tr("If you don't wanna see me, you can hide me in Help menu."))
self.setStyleSheet("""
QLabel {
background-color:lightYellow;
@ -23,4 +19,4 @@ class helpLabel(QLabel):
margin: 3px;
padding:10px;
color:gray;
}""")
}""")

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/mainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
@ -40,8 +40,8 @@ class Ui_MainWindow(object):
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.page_4)
self.horizontalLayout_2.setSpacing(0)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setSpacing(0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.tabMain = QtWidgets.QTabWidget(self.page_4)
self.tabMain.setDocumentMode(True)
@ -352,7 +352,7 @@ class Ui_MainWindow(object):
self.btnRmPerso.setObjectName("btnRmPerso")
self.horizontalLayout_14.addWidget(self.btnRmPerso)
self.txtPersosFilter = QtWidgets.QLineEdit(self.groupBox)
self.txtPersosFilter.setProperty("clearButtonEnabled", True)
self.txtPersosFilter.setClearButtonEnabled(True)
self.txtPersosFilter.setObjectName("txtPersosFilter")
self.horizontalLayout_14.addWidget(self.txtPersosFilter)
self.verticalLayout_8.addLayout(self.horizontalLayout_14)
@ -536,7 +536,7 @@ class Ui_MainWindow(object):
self.btnRmPlot.setObjectName("btnRmPlot")
self.horizontalLayout_15.addWidget(self.btnRmPlot)
self.txtPlotFilter = QtWidgets.QLineEdit(self.groupBox_2)
self.txtPlotFilter.setProperty("clearButtonEnabled", True)
self.txtPlotFilter.setClearButtonEnabled(True)
self.txtPlotFilter.setObjectName("txtPlotFilter")
self.horizontalLayout_15.addWidget(self.txtPlotFilter)
self.verticalLayout_10.addLayout(self.horizontalLayout_15)
@ -732,7 +732,7 @@ class Ui_MainWindow(object):
self.btnRmWorld.setObjectName("btnRmWorld")
self.horizontalLayout_19.addWidget(self.btnRmWorld)
self.txtWorldFilter = QtWidgets.QLineEdit(self.frame_3)
self.txtWorldFilter.setProperty("clearButtonEnabled", True)
self.txtWorldFilter.setClearButtonEnabled(True)
self.txtWorldFilter.setObjectName("txtWorldFilter")
self.horizontalLayout_19.addWidget(self.txtWorldFilter)
self.btnWorldEmptyData = QtWidgets.QPushButton(self.frame_3)
@ -799,7 +799,6 @@ class Ui_MainWindow(object):
self.layoutWidget = QtWidgets.QWidget(self.splitterOutlineH)
self.layoutWidget.setObjectName("layoutWidget")
self.verticalLayout_14 = QtWidgets.QVBoxLayout(self.layoutWidget)
self.verticalLayout_14.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_14.setObjectName("verticalLayout_14")
self.splitterOutlineV = QtWidgets.QSplitter(self.layoutWidget)
self.splitterOutlineV.setOrientation(QtCore.Qt.Vertical)
@ -979,7 +978,7 @@ class Ui_MainWindow(object):
self.horizontalLayout_12.addWidget(self.stack)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1145, 21))
self.menubar.setGeometry(QtCore.QRect(0, 0, 1145, 30))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
@ -1215,52 +1214,52 @@ class Ui_MainWindow(object):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_20), _translate("MainWindow", "Outline"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Labels"))
self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabDebug), _translate("MainWindow", "Debug"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuRecents.setTitle(_translate("MainWindow", "Recents"))
self.menuMode.setTitle(_translate("MainWindow", "Mode"))
self.menuFile.setTitle(_translate("MainWindow", "Fi&le"))
self.menuRecents.setTitle(_translate("MainWindow", "&Recents"))
self.menuMode.setTitle(_translate("MainWindow", "&Mode"))
self.menuHelp.setTitle(_translate("MainWindow", "Help"))
self.menuTools.setTitle(_translate("MainWindow", "Tools"))
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
self.menuView.setTitle(_translate("MainWindow", "View"))
self.dckCheatSheet.setWindowTitle(_translate("MainWindow", "Cheat sheet"))
self.dckSearch.setWindowTitle(_translate("MainWindow", "Search"))
self.actOpen.setText(_translate("MainWindow", "Open"))
self.menuView.setTitle(_translate("MainWindow", "&View"))
self.dckCheatSheet.setWindowTitle(_translate("MainWindow", "&Cheat sheet"))
self.dckSearch.setWindowTitle(_translate("MainWindow", "Sea&rch"))
self.actOpen.setText(_translate("MainWindow", "&Open"))
self.actOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
self.actSave.setText(_translate("MainWindow", "Save"))
self.actSave.setText(_translate("MainWindow", "&Save"))
self.actSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
self.actSaveAs.setText(_translate("MainWindow", "Save as..."))
self.actSaveAs.setText(_translate("MainWindow", "Sa&ve as..."))
self.actSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S"))
self.actQuit.setText(_translate("MainWindow", "Quit"))
self.actQuit.setText(_translate("MainWindow", "&Quit"))
self.actQuit.setShortcut(_translate("MainWindow", "Ctrl+Q"))
self.actShowHelp.setText(_translate("MainWindow", "Show help texts"))
self.actShowHelp.setText(_translate("MainWindow", "&Show help texts"))
self.actShowHelp.setShortcut(_translate("MainWindow", "Ctrl+Shift+B"))
self.actSpellcheck.setText(_translate("MainWindow", "Spellcheck"))
self.actSpellcheck.setText(_translate("MainWindow", "&Spellcheck"))
self.actSpellcheck.setShortcut(_translate("MainWindow", "F9"))
self.actLabels.setText(_translate("MainWindow", "Labels..."))
self.actStatus.setText(_translate("MainWindow", "Status..."))
self.actLabels.setText(_translate("MainWindow", "&Labels..."))
self.actStatus.setText(_translate("MainWindow", "&Status..."))
self.actViewTree.setText(_translate("MainWindow", "Tree"))
self.actModeNorma.setText(_translate("MainWindow", "Normal"))
self.actModeSimple.setText(_translate("MainWindow", "Simple"))
self.actModeFractal.setText(_translate("MainWindow", "Fractal"))
self.actModeNorma.setText(_translate("MainWindow", "&Normal"))
self.actModeSimple.setText(_translate("MainWindow", "&Simple"))
self.actModeFractal.setText(_translate("MainWindow", "&Fractal"))
self.actViewCork.setText(_translate("MainWindow", "Index cards"))
self.actViewOutline.setText(_translate("MainWindow", "Outline"))
self.actSettings.setText(_translate("MainWindow", "Settings"))
self.actSettings.setText(_translate("MainWindow", "S&ettings"))
self.actSettings.setShortcut(_translate("MainWindow", "F8"))
self.actCloseProject.setText(_translate("MainWindow", "Close project"))
self.actCompile.setText(_translate("MainWindow", "Compile"))
self.actCloseProject.setText(_translate("MainWindow", "&Close project"))
self.actCompile.setText(_translate("MainWindow", "Co&mpile"))
self.actCompile.setShortcut(_translate("MainWindow", "F6"))
from ui.views.basicItemView import basicItemView
from ui.views.plotTreeView import plotTreeView
from ui.search import search
from ui.views.textEditCompleter import textEditCompleter
from ui.views.treeView import treeView
from ui.editors.mainEditor import mainEditor
from ui.views.outlineView import outlineView
from ui.views.lineEditView import lineEditView
from ui.views.textEditView import textEditView
from ui.welcome import welcome
from ui.sldImportance import sldImportance
from ui.cheatSheet import cheatSheet
from ui.views.metadataView import metadataView
from ui.views.persoTreeView import persoTreeView
from manuskript.ui.cheatSheet import cheatSheet
from manuskript.ui.editors.mainEditor import mainEditor
from manuskript.ui.search import search
from manuskript.ui.sldImportance import sldImportance
from manuskript.ui.views.basicItemView import basicItemView
from manuskript.ui.views.lineEditView import lineEditView
from manuskript.ui.views.metadataView import metadataView
from manuskript.ui.views.outlineView import outlineView
from manuskript.ui.views.persoTreeView import persoTreeView
from manuskript.ui.views.plotTreeView import plotTreeView
from manuskript.ui.views.textEditCompleter import textEditCompleter
from manuskript.ui.views.textEditView import textEditView
from manuskript.ui.views.treeView import treeView
from manuskript.ui.welcome import welcome

View file

@ -103,7 +103,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -706,7 +715,7 @@
<property name="placeholderText">
<string>Filter</string>
</property>
<property name="clearButtonEnabled" stdset="0">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
@ -1055,7 +1064,7 @@
<property name="placeholderText">
<string>Filter</string>
</property>
<property name="clearButtonEnabled" stdset="0">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
@ -1416,7 +1425,7 @@
<property name="placeholderText">
<string>Filter</string>
</property>
<property name="clearButtonEnabled" stdset="0">
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
@ -1658,7 +1667,16 @@
<string>Redaction</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_15">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -1668,7 +1686,16 @@
</property>
<widget class="QWidget" name="treeRedacWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_30">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -1850,19 +1877,21 @@
<x>0</x>
<y>0</y>
<width>1145</width>
<height>21</height>
<height>30</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
<string>Fi&amp;le</string>
</property>
<widget class="QMenu" name="menuRecents">
<property name="title">
<string>Recents</string>
<string>&amp;Recents</string>
</property>
<property name="icon">
<iconset theme="folder-recent"/>
<iconset theme="folder-recent">
<normaloff/>
</iconset>
</property>
</widget>
<addaction name="actOpen"/>
@ -1877,7 +1906,7 @@
</widget>
<widget class="QMenu" name="menuMode">
<property name="title">
<string>Mode</string>
<string>&amp;Mode</string>
</property>
<addaction name="actModeNorma"/>
<addaction name="actModeSimple"/>
@ -1905,7 +1934,7 @@
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
<string>&amp;View</string>
</property>
</widget>
<addaction name="menuFile"/>
@ -1918,7 +1947,7 @@
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dckCheatSheet">
<property name="windowTitle">
<string>Cheat sheet</string>
<string>&amp;Cheat sheet</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
@ -1940,7 +1969,7 @@
</widget>
<widget class="QDockWidget" name="dckSearch">
<property name="windowTitle">
<string>Search</string>
<string>Sea&amp;rch</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
@ -1966,7 +1995,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Open</string>
<string>&amp;Open</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
@ -1978,7 +2007,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Save</string>
<string>&amp;Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
@ -1990,7 +2019,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Save as...</string>
<string>Sa&amp;ve as...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
@ -2002,7 +2031,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Quit</string>
<string>&amp;Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
@ -2020,7 +2049,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Show help texts</string>
<string>&amp;Show help texts</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+B</string>
@ -2038,7 +2067,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Spellcheck</string>
<string>&amp;Spellcheck</string>
</property>
<property name="shortcut">
<string>F9</string>
@ -2046,12 +2075,12 @@
</action>
<action name="actLabels">
<property name="text">
<string>Labels...</string>
<string>&amp;Labels...</string>
</property>
</action>
<action name="actStatus">
<property name="text">
<string>Status...</string>
<string>&amp;Status...</string>
</property>
</action>
<action name="actViewTree">
@ -2067,7 +2096,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Normal</string>
<string>&amp;Normal</string>
</property>
</action>
<action name="actModeSimple">
@ -2075,7 +2104,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Simple</string>
<string>&amp;Simple</string>
</property>
</action>
<action name="actModeFractal">
@ -2083,7 +2112,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Fractal</string>
<string>&amp;Fractal</string>
</property>
</action>
<action name="actViewCork">
@ -2102,7 +2131,7 @@
<normaloff>../../../../../../../.designer/backup</normaloff>../../../../../../../.designer/backup</iconset>
</property>
<property name="text">
<string>Settings</string>
<string>S&amp;ettings</string>
</property>
<property name="shortcut">
<string>F8</string>
@ -2115,12 +2144,12 @@
</iconset>
</property>
<property name="text">
<string>Close project</string>
<string>&amp;Close project</string>
</property>
</action>
<action name="actCompile">
<property name="text">
<string>Compile</string>
<string>Co&amp;mpile</string>
</property>
<property name="shortcut">
<string>F6</string>
@ -2131,79 +2160,79 @@
<customwidget>
<class>textEditView</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditView.h</header>
<header>manuskript.ui.views.textEditView.h</header>
</customwidget>
<customwidget>
<class>lineEditView</class>
<extends>QLineEdit</extends>
<header>ui.views.lineEditView.h</header>
<header>manuskript.ui.views.lineEditView.h</header>
</customwidget>
<customwidget>
<class>outlineView</class>
<extends>QTreeView</extends>
<header>ui.views.outlineView.h</header>
<header>manuskript.ui.views.outlineView.h</header>
</customwidget>
<customwidget>
<class>sldImportance</class>
<extends>QWidget</extends>
<header>ui.sldImportance.h</header>
<header>manuskript.ui.sldImportance.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>treeView</class>
<extends>QTreeView</extends>
<header>ui.views.treeView.h</header>
<header>manuskript.ui.views.treeView.h</header>
</customwidget>
<customwidget>
<class>metadataView</class>
<extends>QWidget</extends>
<header>ui.views.metadataView.h</header>
<header>manuskript.ui.views.metadataView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>basicItemView</class>
<extends>QWidget</extends>
<header>ui.views.basicItemView.h</header>
<header>manuskript.ui.views.basicItemView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>plotTreeView</class>
<extends>QTreeWidget</extends>
<header>ui.views.plotTreeView.h</header>
<header>manuskript.ui.views.plotTreeView.h</header>
</customwidget>
<customwidget>
<class>welcome</class>
<extends>QWidget</extends>
<header>ui.welcome.h</header>
<header>manuskript.ui.welcome.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>mainEditor</class>
<extends>QWidget</extends>
<header>ui.editors.mainEditor.h</header>
<header>manuskript.ui.editors.mainEditor.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>persoTreeView</class>
<extends>QTreeWidget</extends>
<header>ui.views.persoTreeView.h</header>
<header>manuskript.ui.views.persoTreeView.h</header>
</customwidget>
<customwidget>
<class>cheatSheet</class>
<extends>QWidget</extends>
<header>ui.cheatSheet.h</header>
<header>manuskript.ui.cheatSheet.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>search</class>
<extends>QWidget</extends>
<header>ui.search.h</header>
<header>manuskript.ui.search.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>textEditCompleter</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditCompleter.h</header>
<header>manuskript.ui.views.textEditCompleter.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -1,24 +1,26 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.revisions_ui import *
from functions import *
import models.references as Ref
# --!-- coding: utf8 --!--
import datetime
import difflib
import re
from PyQt5.QtCore import Qt, QTimer, QRect
from PyQt5.QtGui import QPalette, QFontMetrics
from PyQt5.QtWidgets import QWidget, QMenu, QActionGroup, QAction, QListWidgetItem, QStyledItemDelegate, QStyle
from manuskript.enums import Outline
from manuskript.ui.revisions_ui import Ui_revisions
from manuskript.models import references as Ref
class revisions(QWidget, Ui_revisions):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.splitter.setStretchFactor(0, 5)
self.splitter.setStretchFactor(1, 70)
self.listDelegate = listCompleterDelegate(self)
self.list.setItemDelegate(self.listDelegate)
self.list.itemActivated.connect(self.showDiff)
@ -28,79 +30,79 @@ class revisions(QWidget, Ui_revisions):
self.btnDelete.clicked.connect(self.delete)
self.btnRestore.clicked.connect(self.restore)
self.btnRestore.setEnabled(False)
#self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# self.list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.updateTimer = QTimer()
self.updateTimer.setSingleShot(True)
self.updateTimer.setInterval(500)
self.updateTimer.timeout.connect(self.update)
self.updateTimer.stop()
self.menu = QMenu(self)
self.actGroup = QActionGroup(self)
self.actShowDiff = QAction(self.tr("Show modifications"), self.menu)
self.actShowDiff.setCheckable(True)
self.actShowDiff.setChecked(True)
self.actShowDiff.triggered.connect(self.showDiff)
self.menu.addAction(self.actShowDiff)
self.actGroup.addAction(self.actShowDiff)
self.actShowVersion = QAction(self.tr("Show ancient version"), self.menu)
self.actShowVersion.setCheckable(True)
self.actShowVersion.setChecked(False)
self.actShowVersion.triggered.connect(self.showDiff)
self.menu.addAction(self.actShowVersion)
self.actGroup.addAction(self.actShowVersion)
self.menu.addSeparator()
self.actShowSpaces = QAction(self.tr("Show spaces"), self.menu)
self.actShowSpaces.setCheckable(True)
self.actShowSpaces.setChecked(False)
self.actShowSpaces.triggered.connect(self.showDiff)
self.menu.addAction(self.actShowSpaces)
self.actDiffOnly = QAction(self.tr("Show modifications only"), self.menu)
self.actDiffOnly.setCheckable(True)
self.actDiffOnly.setChecked(True)
self.actDiffOnly.triggered.connect(self.showDiff)
self.menu.addAction(self.actDiffOnly)
self.btnOptions.setMenu(self.menu)
self._model = None
self._index = None
def setModel(self, model):
self._model = model
self._model.dataChanged.connect(self.updateMaybe)
def setCurrentModelIndex(self, index):
self._index = index
self.view.setText("")
self.update()
def updateMaybe(self, topLeft, bottomRight):
if self._index and \
topLeft.column() <= Outline.revisions.value <= bottomRight.column() and \
topLeft.row() <= self._index.row() <= bottomRight.row():
#self.update()
topLeft.column() <= Outline.revisions.value <= bottomRight.column() and \
topLeft.row() <= self._index.row() <= bottomRight.row():
# self.update()
self.updateTimer.start()
def update(self):
self.list.clear()
item = self._index.internalPointer()
rev = item.revisions()
# Sort revisions
rev = sorted(rev, key=lambda x:x[0], reverse=True)
rev = sorted(rev, key=lambda x: x[0], reverse=True)
for r in rev:
timestamp = datetime.datetime.fromtimestamp(r[0]).strftime('%Y-%m-%d %H:%M:%S')
readable = self.readableDelta(r[0])
i = QListWidgetItem(readable)
i.setData(Qt.UserRole, r[0])
i.setData(Qt.UserRole+1, timestamp)
i.setData(Qt.UserRole + 1, timestamp)
self.list.addItem(i)
def readableDelta(self, timestamp):
now = datetime.datetime.now()
delta = now - datetime.datetime.fromtimestamp(timestamp)
@ -118,47 +120,47 @@ class revisions(QWidget, Ui_revisions):
return self.tr("{} minutes ago").format(str(int(delta.seconds / 60)))
else:
return self.tr("{} seconds ago").format(str(delta.seconds))
def showDiff(self):
# UI stuff
self.actShowSpaces.setEnabled(self.actShowDiff.isChecked())
self.actDiffOnly.setEnabled(self.actShowDiff.isChecked())
#FIXME: Errors in line number
# FIXME: Errors in line number
i = self.list.currentItem()
if not i:
self.btnDelete.setEnabled(False)
self.btnRestore.setEnabled(False)
return
self.btnDelete.setEnabled(True)
self.btnRestore.setEnabled(True)
ts = i.data(Qt.UserRole)
item = self._index.internalPointer()
textNow = item.text()
textBefore = [r[1] for r in item.revisions() if r[0] == ts][0]
if self.actShowVersion.isChecked():
if item.type() == "t2t":
textBefore = Ref.basicT2TFormat(textBefore)
self.view.setText(textBefore)
return
textNow = textNow.splitlines()
textBefore = textBefore.splitlines()
d = difflib.Differ()
diff = list(d.compare(textBefore, textNow))
if self.actShowSpaces.isChecked():
_format = lambda x: x.replace(" ", "␣ ")
else:
_format = lambda x:x
extra = "" if item.type() == "html" else "<br>"
_format = lambda x: x
extra = "" if item.type() == "html" else "<br>"
diff = [d for d in diff if d and not d[:2] == "? "]
mydiff = ""
skip = False
@ -166,23 +168,23 @@ class revisions(QWidget, Ui_revisions):
l = diff[n]
op = l[:2]
txt = l[2:]
op2 = diff[n+1][:2] if n+1 < len(diff) else None
txt2 = diff[n+1][2:] if n+1 < len(diff) else None
op2 = diff[n + 1][:2] if n + 1 < len(diff) else None
txt2 = diff[n + 1][2:] if n + 1 < len(diff) else None
if skip:
skip = False
continue
# Same line
if op == " " and not self.actDiffOnly.isChecked():
if item.type() == "t2t":
txt = Ref.basicT2TFormat(txt)
mydiff += "{}{}".format(txt, extra)
elif op == "- " and op2 == "+ ":
if self.actDiffOnly.isChecked():
mydiff += "<br><span style='color: blue;'>{}</span><br>".format(
self.tr("Line {}:").format(str(n)))
self.tr("Line {}:").format(str(n)))
s = difflib.SequenceMatcher(None, txt, txt2, autojunk=True)
newline = ""
for tag, i1, i2, j1, j2 in s.get_opcodes():
@ -191,21 +193,25 @@ class revisions(QWidget, Ui_revisions):
elif tag == "delete":
newline += "<span style='color:red; background:yellow;'>{}</span>".format(_format(txt[i1:i2]))
elif tag == "insert":
newline += "<span style='color:green; background:yellow;'>{}</span>".format(_format(txt2[j1:j2]))
newline += "<span style='color:green; background:yellow;'>{}</span>".format(
_format(txt2[j1:j2]))
elif tag == "replace":
newline += "<span style='color:red; background:yellow;'>{}</span>".format(_format(txt[i1:i2]))
newline += "<span style='color:green; background:yellow;'>{}</span>".format(_format(txt2[j1:j2]))
newline += "<span style='color:green; background:yellow;'>{}</span>".format(
_format(txt2[j1:j2]))
# Few ugly tweaks for html diffs
newline = re.sub(r"(<span style='color.*?><span.*?>)</span>(.*)<span style='color:.*?>(</span></span>)",
"\\1\\2\\3", newline)
newline = re.sub(r"<p align=\"<span style='color:red; background:yellow;'>cen</span><span style='color:green; background:yellow;'>righ</span>t<span style='color:red; background:yellow;'>er</span>\" style=\" -qt-block-indent:0; -qt-user-state:0; \">(.*?)</p>",
"<p align=\"right\"><span style='color:green; background:yellow;'>\\1</span></p>", newline)
newline = re.sub(r"<p align=\"<span style='color:green; background:yellow;'>cente</span>r<span style='color:red; background:yellow;'>ight</span>\" style=\" -qt-block-indent:0; -qt-user-state:0; \">(.*)</p>",
"<p align=\"center\"><span style='color:green; background:yellow;'>\\1</span></p>", newline)
newline = re.sub(
r"<p align=\"<span style='color:red; background:yellow;'>cen</span><span style='color:green; background:yellow;'>righ</span>t<span style='color:red; background:yellow;'>er</span>\" style=\" -qt-block-indent:0; -qt-user-state:0; \">(.*?)</p>",
"<p align=\"right\"><span style='color:green; background:yellow;'>\\1</span></p>", newline)
newline = re.sub(
r"<p align=\"<span style='color:green; background:yellow;'>cente</span>r<span style='color:red; background:yellow;'>ight</span>\" style=\" -qt-block-indent:0; -qt-user-state:0; \">(.*)</p>",
"<p align=\"center\"><span style='color:green; background:yellow;'>\\1</span></p>", newline)
newline = re.sub(r"<p(<span.*?>)(.*?)(</span>)(.*?)>(.*?)</p>",
"<p\\2\\4>\\1\\5\\3</p>", newline)
mydiff += newline + extra
skip = True
elif op == "- ":
@ -216,9 +222,9 @@ class revisions(QWidget, Ui_revisions):
if self.actDiffOnly.isChecked():
mydiff += "<br>{}:<br>".format(str(n))
mydiff += "<span style='color:green;'>{}</span>{}".format(txt, extra)
self.view.setText(mydiff)
def restore(self):
i = self.list.currentItem()
if not i:
@ -228,26 +234,26 @@ class revisions(QWidget, Ui_revisions):
textBefore = [r[1] for r in item.revisions() if r[0] == ts][0]
index = self._index.sibling(self._index.row(), Outline.text.value)
self._index.model().setData(index, textBefore)
#item.setData(Outline.text.value, textBefore)
# item.setData(Outline.text.value, textBefore)
def delete(self):
i = self.list.currentItem()
if not i:
return
ts = i.data(Qt.UserRole)
self._index.internalPointer().deleteRevision(ts)
def clearAll(self):
self._index.internalPointer().clearAllRevisions()
def saveState(self):
return [
self.actShowDiff.isChecked(),
self.actShowVersion.isChecked(),
self.actShowSpaces.isChecked(),
self.actDiffOnly.isChecked(),
]
]
def popupMenu(self, pos):
i = self.list.itemAt(pos)
m = QMenu(self)
@ -257,9 +263,9 @@ class revisions(QWidget, Ui_revisions):
m.addSeparator()
if self.list.count():
m.addAction(self.tr("Clear all")).triggered.connect(self.clearAll)
m.popup(self.list.mapToGlobal(pos))
def restoreState(self, state):
self.actShowDiff.setChecked(state[0])
self.actShowVersion.setChecked(state[1])
@ -267,25 +273,25 @@ class revisions(QWidget, Ui_revisions):
self.actDiffOnly.setChecked(state[3])
self.actShowSpaces.setEnabled(self.actShowDiff.isChecked())
self.actDiffOnly.setEnabled(self.actShowDiff.isChecked())
class listCompleterDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole+1)
extra = index.data(Qt.UserRole + 1)
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Inactive, QPalette.Highlight))
title = index.data()
extra = " - {}".format(extra)
painter.drawText(option.rect, Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
w = fm.width(title)
r = QRect(option.rect)
@ -293,4 +299,4 @@ class listCompleterDelegate(QStyledItemDelegate):
painter.save()
painter.setPen(Qt.gray)
painter.drawText(r, Qt.AlignLeft, extra)
painter.restore()
painter.restore()

View file

@ -1,19 +1,20 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
import models.references as Ref
from ui.search_ui import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QPalette, QFontMetrics
from PyQt5.QtWidgets import QWidget, QMenu, QAction, qApp, QListWidgetItem, QStyledItemDelegate, QStyle
from manuskript.enums import Outline
from manuskript.functions import mainWindow
from manuskript.ui.search_ui import Ui_search
from manuskript.models import references as Ref
class search(QWidget, Ui_search):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.options = {
"All": True,
"Title": True,
@ -24,30 +25,30 @@ class search(QWidget, Ui_search):
"Status": False,
"Label": False,
"CS": True
}
}
self.text.returnPressed.connect(self.search)
self.generateOptionMenu()
self.delegate = listResultDelegate(self)
self.result.setItemDelegate(self.delegate)
self.result.itemActivated.connect(self.openItem)
def generateOptionMenu(self):
self.menu = QMenu(self)
a = QAction(self.tr("Search in:"), self.menu)
a.setEnabled(False)
self.menu.addAction(a)
for i, d in [
(self.tr("All"), "All"),
(self.tr("Title"), "Title"),
(self.tr("Text"), "Text"),
(self.tr("All"), "All"),
(self.tr("Title"), "Title"),
(self.tr("Text"), "Text"),
(self.tr("Summary"), "Summary"),
(self.tr("Notes"), "Notes"),
(self.tr("POV"), "POV"),
(self.tr("Status"), "Status"),
(self.tr("Label"), "Label"),
]:
(self.tr("Notes"), "Notes"),
(self.tr("POV"), "POV"),
(self.tr("Status"), "Status"),
(self.tr("Label"), "Label"),
]:
a = QAction(i, self.menu)
a.setCheckable(True)
a.setChecked(self.options[d])
@ -55,13 +56,13 @@ class search(QWidget, Ui_search):
a.triggered.connect(self.updateOptions)
self.menu.addAction(a)
self.menu.addSeparator()
a = QAction(self.tr("Options:"), self.menu)
a.setEnabled(False)
self.menu.addAction(a)
for i, d in [
(self.tr("Case sensitive"), "CS"),
]:
(self.tr("Case sensitive"), "CS"),
]:
a = QAction(i, self.menu)
a.setCheckable(True)
a.setChecked(self.options[d])
@ -69,36 +70,36 @@ class search(QWidget, Ui_search):
a.triggered.connect(self.updateOptions)
self.menu.addAction(a)
self.menu.addSeparator()
self.btnOptions.setMenu(self.menu)
def updateOptions(self):
a = self.sender()
self.options[a.data()] = a.isChecked()
def search(self):
text = self.text.text()
# Chosing the right columns
lstColumns = [
("Title", Outline.title.value),
("Text", Outline.text.value),
("Summary", Outline.summarySentance.value),
("Summary", Outline.summarySentance.value),
("Summary", Outline.summaryFull.value),
("Notes", Outline.notes.value),
("POV", Outline.POV.value),
("Status", Outline.status.value),
("Label", Outline.label.value),
]
]
columns = [c[1] for c in lstColumns if self.options[c[0]] or self.options["All"]]
# Setting override cursor
qApp.setOverrideCursor(Qt.WaitCursor)
# Searching
model = mainWindow().mdlOutline
results = model.findItemsContaining(text, columns, self.options["CS"])
# Showing results
self.result.clear()
for r in results:
@ -110,35 +111,35 @@ class search(QWidget, Ui_search):
i.setData(Qt.UserRole, r)
i.setData(Qt.UserRole + 1, item.path())
self.result.addItem(i)
# Removing override cursor
qApp.restoreOverrideCursor()
def openItem(self, item):
r = Ref.textReference(item.data(Qt.UserRole))
Ref.open(r)
#mw = mainWindow()
#index = mw.mdlOutline.getIndexByID(item.data(Qt.UserRole))
#mw.mainEditor.setCurrentModelIndex(index, newTab=True)
# mw = mainWindow()
# index = mw.mdlOutline.getIndexByID(item.data(Qt.UserRole))
# mw.mainEditor.setCurrentModelIndex(index, newTab=True)
class listResultDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole+1)
extra = index.data(Qt.UserRole + 1)
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Highlight))
title = index.data()
extra = " - {}".format(extra)
painter.drawText(option.rect.adjusted(2, 1, 0, 0), Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
w = fm.width(title)
r = QRect(option.rect)
@ -149,4 +150,4 @@ class listResultDelegate(QStyledItemDelegate):
else:
painter.setPen(Qt.gray)
painter.drawText(r.adjusted(2, 1, 0, 0), Qt.AlignLeft, extra)
painter.restore()
painter.restore()

View file

@ -1,79 +1,80 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from functions import *
from ui.sldImportance_ui import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import pyqtSignal, pyqtProperty
from PyQt5.QtWidgets import QWidget
from manuskript.functions import toInt
from manuskript.ui.sldImportance_ui import Ui_sldImportance
class sldImportance(QWidget, Ui_sldImportance):
importanceChanged = pyqtSignal(str)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self._column = 0
self._updating = False
self._index = None
self.lastValue = -1
self.sld.valueChanged.connect(self.changed)
self.setValue(0)
def getImportance(self):
return str(self.sld.value())
def changed(self, v):
val = [
self.tr("Minor"),
self.tr("Secondary"),
self.tr("Main"),
]
]
self.lbl.setText(val[v])
self.importanceChanged.emit(str(v))
if self._index and not self._updating:
if str(v) != self._model.data(self._index):
self._updating = True
self._model.setData(self._index, str(v))
self._updating = False
def setValue(self, v):
if v != self.lastValue:
if v != self.lastValue:
self.sld.setValue(int(v) if v else 0)
self.changed(int(v) if v else 0)
self.lastValue = v
def setProperty():
pass
# MODEL / VIEW
def setColumn(self, column):
self._column = column
def setModel(self, model):
self._model = model
self._model.dataChanged.connect(self.update)
def update(self, topLeft, bottomRight):
if self._updating:
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateValue()
def setCurrentModelIndex(self, index):
if index.isValid():
if index.column() != self._column:
index = index.sibling(index.row(), self._column)
self._index = index
self.updateValue()
def updateValue(self):
if self._index:
val = toInt(self._model.data(self._index))
@ -81,6 +82,5 @@ class sldImportance(QWidget, Ui_sldImportance):
self._updating = True
self.setValue(val)
self._updating = False
importance = pyqtProperty(str, fget=getImportance, fset=setValue, notify=importanceChanged)
importance = pyqtProperty(str, fget=getImportance, fset=setValue, notify=importanceChanged)

View file

@ -6,7 +6,7 @@
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtCore, QtWidgets
class Ui_sldImportance(object):
def setupUi(self, sldImportance):

View file

@ -1,45 +1,45 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.views.basicItemView_ui import *
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QWidget
from manuskript.enums import Outline
from manuskript.ui.views.basicItemView_ui import Ui_basicItemView
class basicItemView(QWidget, Ui_basicItemView):
def __init__(self, parent=None):
QWidget.__init__(self)
self.setupUi(self)
self.txtSummarySentance.setColumn(Outline.summarySentance.value)
self.txtSummaryFull.setColumn(Outline.summaryFull.value)
self.txtGoal.setColumn(Outline.setGoal.value)
def setModels(self, mdlOutline, mdlPersos, mdlLabels, mdlStatus):
self.cmbPOV.setModels(mdlPersos, mdlOutline)
self.txtSummarySentance.setModel(mdlOutline)
self.txtSummaryFull.setModel(mdlOutline)
self.txtGoal.setModel(mdlOutline)
def getIndexes(self, sourceView):
"Returns a list of indexes from list of QItemSelectionRange"
"""Returns a list of indexes from list of QItemSelectionRange"""
indexes = []
for i in sourceView.selectionModel().selection().indexes():
if i.column() != 0:
if i.column() != 0:
continue
if i not in indexes:
indexes.append(i)
return indexes
def selectionChanged(self, sourceView):
indexes = self.getIndexes(sourceView)
if len(indexes) == 0:
self.setEnabled(False)
elif len(indexes) == 1:
self.setEnabled(True)
idx = indexes[0]
@ -47,18 +47,16 @@ class basicItemView(QWidget, Ui_basicItemView):
self.txtSummaryFull.setCurrentModelIndex(idx)
self.cmbPOV.setCurrentModelIndex(idx)
self.txtGoal.setCurrentModelIndex(idx)
else:
self.setEnabled(True)
self.txtSummarySentance.setCurrentModelIndexes(indexes)
self.txtSummaryFull.setCurrentModelIndexes(indexes)
self.cmbPOV.setCurrentModelIndexes(indexes)
self.txtGoal.setCurrentModelIndexes(indexes)
def setDict(self, d):
self.txtSummaryFull.setDict(d)
def toggleSpellcheck(self, v):
self.txtSummaryFull.toggleSpellcheck(v)

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/views/basicItemView_ui.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
@ -66,6 +66,6 @@ class Ui_basicItemView(object):
self.txtSummarySentance.setPlaceholderText(_translate("basicItemView", "One line summary"))
self.label_9.setText(_translate("basicItemView", "Few sentences summary:"))
from ui.views.textEditView import textEditView
from ui.views.lineEditView import lineEditView
from ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser
from manuskript.ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser
from manuskript.ui.views.lineEditView import lineEditView
from manuskript.ui.views.textEditView import textEditView

View file

@ -109,17 +109,17 @@
<customwidget>
<class>textEditView</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditView.h</header>
<header>manuskript.ui.views.textEditView.h</header>
</customwidget>
<customwidget>
<class>cmbOutlinePersoChoser</class>
<extends>QComboBox</extends>
<header>ui.views.cmbOutlinePersoChoser.h</header>
<header>manuskript.ui.views.cmbOutlinePersoChoser.h</header>
</customwidget>
<customwidget>
<class>lineEditView</class>
<extends>QLineEdit</extends>
<header>ui.views.lineEditView.h</header>
<header>manuskript.ui.views.lineEditView.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -1,16 +1,16 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from qt import *
from enums import *
# Because I have trouble with QDataWidgetMapper and the checkbox, I don't know why.
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QCheckBox
from manuskript.enums import Outline
class chkOutlineCompile(QCheckBox):
def __init__(self, parent=None):
QCheckBox.__init__(self, parent)
self.stateChanged.connect(self.submit)
@ -19,11 +19,11 @@ class chkOutlineCompile(QCheckBox):
self._indexes = None
self._model = None
self._updating = False
def setModel(self, model):
self._model = model
self._model.dataChanged.connect(self.update)
def setCurrentModelIndex(self, index):
self._indexes = None
if index.column() != self._column:
@ -31,7 +31,7 @@ class chkOutlineCompile(QCheckBox):
self._index = index
self.setTristate(False)
self.updateCheckState()
def setCurrentModelIndexes(self, indexes):
self._index = None
self._indexes = []
@ -40,7 +40,7 @@ class chkOutlineCompile(QCheckBox):
i = i.sibling(i.row(), self._column)
self._indexes.append(i)
self.updateCheckState()
def getCheckedValue(self, index):
item = index.internalPointer()
c = item.data(Outline.compile)
@ -48,72 +48,71 @@ class chkOutlineCompile(QCheckBox):
c = int(c)
else:
c = Qt.Unchecked
return c
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateCheckState()
elif self._indexes:
update = False
for i in self._indexes:
if topLeft.row() <= i.row() <= bottomRight.row():
update = True
if update:
self.updateCheckState()
def updateCheckState(self):
if self._index:
self.setEnabled(True)
c = self.getCheckedValue(self._index)
self.setCheckState(c)
elif self._indexes:
self.setEnabled(True)
values = []
for i in self._indexes:
values.append(self.getCheckedValue(i))
same = True
for v in values[1:]:
if v != values[0]:
same = False
break
if same:
self.setCheckState(values[0])
else:
self._updating = True
self.setCheckState(Qt.PartiallyChecked)
self._updating = False
else:
self.setChecked(False)
self.setEnabled(False)
def submit(self, state):
if self._updating:
return
if self._index:
if self._model.data(self._index) != state:
self._model.setData(self._index, state)
elif self._indexes:
for i in self._indexes:
if self._model.data(i) != state:
self._model.setData(i, state)
self.setTristate(False)

View file

@ -1,11 +1,13 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush
from PyQt5.QtWidgets import QComboBox
from manuskript.enums import Outline
class cmbOutlineLabelChoser(QComboBox):
def __init__(self, parent=None):
QComboBox.__init__(self, parent)
self.activated[int].connect(self.submit)
@ -14,27 +16,27 @@ class cmbOutlineLabelChoser(QComboBox):
self._indexes = None
self._updating = False
self._various = False
def setModels(self, mdlLabels, mdlOutline):
self.mdlLabels = mdlLabels
self.mdlLabels.dataChanged.connect(self.updateItems)
self.mdlOutline = mdlOutline
self.mdlOutline.dataChanged.connect(self.update)
self.updateItems()
def updateItems(self):
self.clear()
for i in range(self.mdlLabels.rowCount()):
item = self.mdlLabels.item(i, 0)
if item:
self.addItem(item.icon(),
item.text())
item.text())
self._various = False
if self._index or self._indexes:
self.updateSelectedItem()
def setCurrentModelIndex(self, index):
self._indexes = None
if index.column() != self._column:
@ -42,30 +44,30 @@ class cmbOutlineLabelChoser(QComboBox):
self._index = index
self.updateItems()
self.updateSelectedItem()
def setCurrentModelIndexes(self, indexes):
self._indexes = []
self._index = None
for i in indexes:
if i.isValid():
if i.column() != self._column:
i = i.sibling(i.row(), self._column)
self._indexes.append(i)
self.updateItems()
self.updateSelectedItem()
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateSelectedItem()
elif self._indexes:
update = False
for i in self._indexes:
@ -73,39 +75,39 @@ class cmbOutlineLabelChoser(QComboBox):
update = True
if update:
self.updateSelectedItem()
def getLabel(self, index):
item = index.internalPointer()
label = item.data(self._column)
if not label:
if not label:
label = 0
return int(label)
def updateSelectedItem(self):
if self._updating:
return
if self._index:
label = self.getLabel(self._index)
self.setCurrentIndex(label)
elif self._indexes:
labels = []
same = True
for i in self._indexes:
labels.append(self.getLabel(i))
for lbl in labels[1:]:
if lbl != labels[0]:
same = False
break
if same:
self._various = False
self.setCurrentIndex(labels[0])
else:
if not self._various:
self.insertItem(0, self.tr("Various"))
@ -115,25 +117,24 @@ class cmbOutlineLabelChoser(QComboBox):
self.setItemData(0, QBrush(Qt.darkGray), Qt.ForegroundRole)
self._various = True
self.setCurrentIndex(0)
else:
self.setCurrentIndex(0)
def submit(self, idx):
if self._index:
self.mdlOutline.setData(self._index, self.currentIndex())
elif self._indexes:
value = self.currentIndex()
if self._various:
if value == 0:
return
value -= 1
self._updating = True
for i in self._indexes:
self.mdlOutline.setData(i, value)
self._updating = False

View file

@ -1,12 +1,14 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QBrush, QColor
from PyQt5.QtWidgets import QComboBox
from manuskript.enums import Outline
from manuskript.functions import toInt
class cmbOutlinePersoChoser(QComboBox):
def __init__(self, parent=None):
QComboBox.__init__(self, parent)
self.activated[int].connect(self.submit)
@ -15,71 +17,71 @@ class cmbOutlinePersoChoser(QComboBox):
self._indexes = None
self._updating = False
self._various = False
def setModels(self, mdlPersos, mdlOutline):
self.mdlPersos = mdlPersos
self.mdlPersos.dataChanged.connect(self.updateItems)
self.mdlOutline = mdlOutline
self.mdlOutline.dataChanged.connect(self.update)
self.updateItems()
def updateItems(self):
self.clear()
self.addItem(QIcon.fromTheme("dialog-no"), self.tr("None"))
l = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
for importance in range(3):
self.addItem(l[importance])
self.setItemData(self.count()-1, QBrush(QColor(Qt.darkBlue)), Qt.ForegroundRole)
self.setItemData(self.count()-1, QBrush(QColor(Qt.blue).lighter(190)), Qt.BackgroundRole)
item = self.model().item(self.count()-1)
self.setItemData(self.count() - 1, QBrush(QColor(Qt.darkBlue)), Qt.ForegroundRole)
self.setItemData(self.count() - 1, QBrush(QColor(Qt.blue).lighter(190)), Qt.BackgroundRole)
item = self.model().item(self.count() - 1)
item.setFlags(Qt.ItemIsEnabled)
for i in range(self.mdlPersos.rowCount()):
imp = toInt(self.mdlPersos.importance(i))
if not 2-imp == importance: continue
if not 2 - imp == importance:
continue
self.addItem(self.mdlPersos.icon(i), self.mdlPersos.name(i), self.mdlPersos.ID(i))
self.setItemData(self.count() - 1, self.mdlPersos.name(i), Qt.ToolTipRole)
self._various = False
if self._index or self._indexes:
self.updateSelectedItem()
def setCurrentModelIndex(self, index):
self._indexes = None
if index.column() != self._column:
index = index.sibling(index.row(), self._column)
self._index = index
self.updateItems()
def setCurrentModelIndexes(self, indexes):
self._index = None
idxes = []
for i in indexes:
if i.isValid():
if i.column() != self._column:
i = i.sibling(i.row(), self._column)
idxes.append(i)
if idxes != self._indexes:
self._indexes = idxes
self.updateItems()
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateSelectedItem()
elif self._indexes:
update = False
for i in self._indexes:
@ -87,44 +89,44 @@ class cmbOutlinePersoChoser(QComboBox):
update = True
if update:
self.updateSelectedItem()
def getPOV(self, index):
item = index.internalPointer()
POV = item.data(self._column)
return POV
def selectPOV(self, POV):
idx = self.findData(POV)
if idx != -1:
self.setCurrentIndex(idx)
else:
self.setCurrentIndex(0)
def updateSelectedItem(self, idx1=None, idx2=None):
if self._updating:
return
if self._index:
POV = self.getPOV(self._index)
self.selectPOV(POV)
elif self._indexes:
POVs = []
same = True
for i in self._indexes:
POVs.append(self.getPOV(i))
for POV in POVs[1:]:
if POV != POVs[0]:
same = False
break
if same:
self._various = False
self.selectPOV(POVs[0])
else:
if not self._various:
self.insertItem(0, self.tr("Various"))
@ -134,19 +136,19 @@ class cmbOutlinePersoChoser(QComboBox):
self.setItemData(0, QBrush(Qt.darkGray), Qt.ForegroundRole)
self._various = True
self.setCurrentIndex(0)
else:
self.setCurrentIndex(0)
def submit(self, idx):
if self._index:
self.mdlOutline.setData(self._index, self.currentData())
elif self._indexes:
if self._various and self.currentIndex() == 0:
return
self._updating = True
for i in self._indexes:
self.mdlOutline.setData(i, self.currentData())
self._updating = False
self._updating = False

View file

@ -1,12 +1,13 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush
from PyQt5.QtWidgets import QComboBox
from manuskript.enums import Outline
class cmbOutlineStatusChoser(QComboBox):
def __init__(self, parent=None):
QComboBox.__init__(self, parent)
self.activated[int].connect(self.submit)
@ -15,26 +16,26 @@ class cmbOutlineStatusChoser(QComboBox):
self._indexes = None
self._updating = False
self._various = False
def setModels(self, mdlStatus, mdlOutline):
self.mdlStatus = mdlStatus
self.mdlStatus.dataChanged.connect(self.updateItems)
self.mdlOutline = mdlOutline
self.mdlOutline.dataChanged.connect(self.update)
self.updateItems()
def updateItems(self):
self.clear()
for i in range(self.mdlStatus.rowCount()):
item = self.mdlStatus.item(i, 0)
if item:
self.addItem(item.text())
self._various = False
if self._index or self._indexes:
self.updateSelectedItem()
def setCurrentModelIndex(self, index):
self._indexes = None
if index.column() != self._column:
@ -42,30 +43,30 @@ class cmbOutlineStatusChoser(QComboBox):
self._index = index
self.updateItems()
self.updateSelectedItem()
def setCurrentModelIndexes(self, indexes):
self._indexes = []
self._index = None
for i in indexes:
if i.isValid():
if i.column() != self._column:
i = i.sibling(i.row(), self._column)
self._indexes.append(i)
self.updateItems()
self.updateSelectedItem()
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateSelectedItem()
elif self._indexes:
update = False
for i in self._indexes:
@ -73,39 +74,39 @@ class cmbOutlineStatusChoser(QComboBox):
update = True
if update:
self.updateSelectedItem()
def getStatus(self, index):
item = index.internalPointer()
status = item.data(self._column)
if not status:
if not status:
status = 0
return int(status)
def updateSelectedItem(self):
if self._updating:
return
if self._index:
status = self.getStatus(self._index)
self.setCurrentIndex(status)
elif self._indexes:
statuses = []
same = True
for i in self._indexes:
statuses.append(self.getStatus(i))
for s in statuses[1:]:
if s != statuses[0]:
same = False
break
if same:
self._various = False
self.setCurrentIndex(statuses[0])
else:
if not self._various:
self.insertItem(0, self.tr("Various"))
@ -115,24 +116,24 @@ class cmbOutlineStatusChoser(QComboBox):
self.setItemData(0, QBrush(Qt.darkGray), Qt.ForegroundRole)
self._various = True
self.setCurrentIndex(0)
else:
self.setCurrentIndex(0)
def submit(self, idx):
if self._index:
self.mdlOutline.setData(self._index, self.currentIndex())
elif self._indexes:
value = self.currentIndex()
if self._various:
if value == 0:
return
value -= 1
self._updating = True
for i in self._indexes:
self.mdlOutline.setData(i, value)
self._updating = False
self._updating = False

View file

@ -1,12 +1,13 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QBrush
from PyQt5.QtWidgets import QComboBox
from manuskript.enums import Outline
class cmbOutlineTypeChoser(QComboBox):
def __init__(self, parent=None):
QComboBox.__init__(self, parent)
self.activated[int].connect(self.submit)
@ -15,27 +16,27 @@ class cmbOutlineTypeChoser(QComboBox):
self._indexes = None
self._updating = False
self._various = False
def setModel(self, mdlOutline):
self.mdlOutline = mdlOutline
self.mdlOutline.dataChanged.connect(self.update)
self.updateItems()
def updateItems(self):
self.clear()
types = [
("t2t", self.tr("Txt2Tags"), "text-x-generic"),
("html", self.tr("Rich Text (html)"), "text-html"),
("txt", self.tr("Plain Text"), "text-x-generic"),
]
]
for t in types:
self.addItem(QIcon.fromTheme(t[2]), t[1], t[0])
self._various = False
if self._index or self._indexes:
self.updateSelectedItem()
def setCurrentModelIndex(self, index):
self._indexes = None
if index.column() != self._column:
@ -45,11 +46,11 @@ class cmbOutlineTypeChoser(QComboBox):
self.setEnabled(index.internalPointer().type() in ["t2t", "html", "txt"])
self.updateItems()
self.updateSelectedItem()
def setCurrentModelIndexes(self, indexes):
self._indexes = []
self._index = None
hasText = False
for i in indexes:
if i.isValid():
@ -58,22 +59,22 @@ class cmbOutlineTypeChoser(QComboBox):
self._indexes.append(i)
if i.internalPointer().type() in ["t2t", "html", "txt"]:
hasText = True
self.setEnabled(hasText)
self.updateItems()
self.updateSelectedItem()
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateSelectedItem()
elif self._indexes:
update = False
for i in self._indexes:
@ -81,40 +82,40 @@ class cmbOutlineTypeChoser(QComboBox):
update = True
if update:
self.updateSelectedItem()
def getType(self, index):
item = index.internalPointer()
return item.type()
def updateSelectedItem(self):
if self._updating:
return
if self._index:
_type = self.getType(self._index)
i = self.findData(_type)
if i != -1:
self.setCurrentIndex(i)
elif self._indexes:
types = []
same = True
for i in self._indexes:
types.append(self.getType(i))
for t in types[1:]:
if t != types[0]:
same = False
break
if same:
self._various = False
i = self.findData(types[0])
if i != -1:
self.setCurrentIndex(i)
else:
if not self._various:
self.insertItem(0, self.tr("Various"))
@ -124,21 +125,21 @@ class cmbOutlineTypeChoser(QComboBox):
self.setItemData(0, QBrush(Qt.darkGray), Qt.ForegroundRole)
self._various = True
self.setCurrentIndex(0)
else:
self.setCurrentIndex(0)
def submit(self, idx):
if self._index:
self.mdlOutline.setData(self._index, self.currentData())
elif self._indexes:
value = self.currentData()
if self._various and self.currentIndex() == 0:
return
self._updating = True
for i in self._indexes:
self.mdlOutline.setData(i, value)
self._updating = False
self._updating = False

View file

@ -1,14 +1,18 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from random import randint
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QSize, Qt, QRect, QPoint
from PyQt5.QtGui import QMouseEvent, QFont, QPalette, QRegion, QFontMetrics, QColor, QIcon
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)
self.factor = settings.corkSizeFactor / 100.
@ -16,22 +20,22 @@ class corkDelegate(QStyledItemDelegate):
self.lastPos = None
self.editing = None
self.margin = 5
def setCorkSizeFactor(self, v):
self.factor = v / 100.
def sizeHint(self, option, index):
return self.defaultSize * self.factor
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:
self.lastPos = event.pos() # - option.rect.topLeft()
self.lastPos = event.pos() # - option.rect.topLeft()
return QStyledItemDelegate.editorEvent(self, event, model, option, index)
def createEditor(self, parent, option, index):
self.updateRects(option, index)
if self.mainLineRect.contains(self.lastPos):
# One line summary
self.editing = Outline.summarySentance
@ -44,7 +48,7 @@ class corkDelegate(QStyledItemDelegate):
f.setItalic(True)
edt.setFont(f)
return edt
elif self.titleRect.contains(self.lastPos):
# Title
self.editing = Outline.title
@ -52,13 +56,13 @@ class corkDelegate(QStyledItemDelegate):
edt.setFocusPolicy(Qt.StrongFocus)
edt.setFrame(False)
f = QFont(option.font)
#f.setPointSize(f.pointSize() + 1)
# f.setPointSize(f.pointSize() + 1)
f.setBold(True)
edt.setFont(f)
edt.setAlignment(Qt.AlignCenter)
#edt.setGeometry(self.titleRect)
# edt.setGeometry(self.titleRect)
return edt
else: # self.mainTextRect.contains(self.lastPos):
# Summary
self.editing = Outline.summaryFull
@ -67,54 +71,53 @@ class corkDelegate(QStyledItemDelegate):
edt.setFrameShape(QFrame.NoFrame)
edt.setPlaceholderText(self.tr("Full summary"))
return edt
def updateEditorGeometry(self, editor, option, index):
if self.editing == Outline.summarySentance:
# One line summary
editor.setGeometry(self.mainLineRect)
elif self.editing == Outline.title:
# Title
editor.setGeometry(self.titleRect)
elif self.editing == Outline.summaryFull:
# Summary
editor.setGeometry(self.mainTextRect)
def setEditorData(self, editor, index):
item = index.internalPointer()
if self.editing == Outline.summarySentance:
# One line summary
editor.setText(item.data(Outline.summarySentance.value))
elif self.editing == Outline.title:
# Title
editor.setText(index.data())
elif self.editing == Outline.summaryFull:
# Summary
editor.setPlainText(item.data(Outline.summaryFull.value))
def setModelData(self, editor, model, index):
if self.editing == Outline.summarySentance:
# One line summary
model.setData(index.sibling(index.row(), Outline.summarySentance.value), editor.text())
elif self.editing == Outline.title:
# Title
model.setData(index, editor.text(), Outline.title.value)
elif self.editing == Outline.summaryFull:
# Summary
model.setData(index.sibling(index.row(), Outline.summaryFull.value), editor.toPlainText())
def updateRects(self, option, index):
margin = self.margin
iconSize = max(16*self.factor, 12)
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))
@ -122,7 +125,7 @@ class corkDelegate(QStyledItemDelegate):
self.itemRect.topRight() + QPoint(0, iconSize + 2 * margin))
self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
self.labelRect.bottomLeft() - QPoint(margin, margin))
self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin),
self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin),
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)
@ -130,50 +133,50 @@ class corkDelegate(QStyledItemDelegate):
self.mainRect.topRight() + QPoint(0, iconSize))
self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
self.mainRect.bottomRight())
if not item.data(Outline.summarySentance.value) :
if not item.data(Outline.summarySentance.value):
self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())
if item.data(Outline.label.value) in ["", "0"]:
self.titleRect.setBottomRight(self.labelRect.bottomRight() - QPoint(self.margin, self.margin))
def paint(self, p, option, index):
#QStyledItemDelegate.paint(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())
# 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
# 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()
# Stack
# Stack
if item.isFolder() and item.childCount() > 0:
p.save()
p.setBrush(Qt.white)
for i in reversed(range(3)):
p.drawRoundedRect(self.itemRect.adjusted(2*i, 2*i, -2*i, 2*i), 10, 10)
p.drawRoundedRect(self.itemRect.adjusted(2 * i, 2 * i, -2 * i, 2 * i), 10, 10)
p.restore()
# Background
# Background
itemRect = self.itemRect
p.save()
if settings.viewSettings["Cork"]["Background"] != "Nothing":
@ -187,8 +190,8 @@ class corkDelegate(QStyledItemDelegate):
p.setPen(pen)
p.drawRoundedRect(itemRect, 10, 10)
p.restore()
# Title bar
# Title bar
topRect = self.topRect
p.save()
if item.isFolder():
@ -199,10 +202,10 @@ class corkDelegate(QStyledItemDelegate):
p.setBrush(color)
p.setClipRegion(QRegion(topRect))
p.drawRoundedRect(itemRect, 10, 10)
#p.drawRect(topRect)
# p.drawRect(topRect)
p.restore()
# Label color
# Label color
if settings.viewSettings["Cork"]["Corner"] != "Nothing":
p.save()
color = colors[settings.viewSettings["Cork"]["Corner"]]
@ -210,23 +213,23 @@ class corkDelegate(QStyledItemDelegate):
p.setBrush(color)
p.setClipRegion(QRegion(self.labelRect))
p.drawRoundedRect(itemRect, 10, 10)
#p.drawRect(topRect)
# p.drawRect(topRect)
p.restore()
p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())
# One line summary background
# One line summary background
lineSummary = item.data(Outline.summarySentance.value)
fullSummary = item.data(Outline.summaryFull.value)
if lineSummary or not fullSummary:
m = self.margin
r = self.mainLineRect.adjusted(-m, -m, m, m/2)
r = self.mainLineRect.adjusted(-m, -m, m, m / 2)
p.save()
p.setPen(Qt.NoPen)
p.setBrush(QColor("#EEE"))
p.drawRect(r)
p.restore()
# Border
# Border
p.save()
p.setBrush(Qt.NoBrush)
pen = p.pen()
@ -239,8 +242,7 @@ class corkDelegate(QStyledItemDelegate):
p.setPen(pen)
p.drawRoundedRect(itemRect, 10, 10)
p.restore()
# Draw the icon
iconRect = self.iconRect
mode = QIcon.Normal
@ -248,13 +250,13 @@ class corkDelegate(QStyledItemDelegate):
mode = QIcon.Disabled
elif option.state & style.State_Selected:
mode = QIcon.Selected
#index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
# 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()
@ -266,23 +268,23 @@ class corkDelegate(QStyledItemDelegate):
col = Qt.black
p.setPen(col)
f = QFont(option.font)
#f.setPointSize(f.pointSize() + 1)
# 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()
# Draw the line
bottomRect = self.bottomRect
p.save()
#p.drawLine(itemRect.x(), iconRect.bottom() + margin,
#itemRect.right(), iconRect.bottom() + margin)
# p.drawLine(itemRect.x(), iconRect.bottom() + margin,
# itemRect.right(), iconRect.bottom() + margin)
p.drawLine(bottomRect.topLeft(), bottomRect.topRight())
p.restore()
# Lines
# Lines
if True:
p.save()
p.setPen(QColor("#EEE"))
@ -293,7 +295,7 @@ class corkDelegate(QStyledItemDelegate):
p.drawLine(l, QPoint(self.mainTextRect.right(), l.y()))
l.setY(l.y() + h)
p.restore()
# Draw status
mainRect = self.mainRect
status = item.data(Outline.status.value)
@ -310,9 +312,9 @@ class corkDelegate(QStyledItemDelegate):
_rotate(-35)
p.drawText(mainRect, Qt.AlignCenter, it.text())
p.restore()
# Draw Summary
# One line
# Draw Summary
# One line
if lineSummary:
p.save()
f = QFont(option.font)
@ -322,12 +324,12 @@ class corkDelegate(QStyledItemDelegate):
elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText)
p.restore()
# Full summary
# Full summary
if fullSummary:
p.setFont(option.font)
p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
#Debug
#for r in [self.itemRect, self.iconRect, self.titleRect, self.bottomRect, self.mainLineRect, self.mainTextRect]:
#p.drawRect(r)
# Debug
# for r in [self.itemRect, self.iconRect, self.titleRect, self.bottomRect, self.mainLineRect, self.mainTextRect]:
# p.drawRect(r)

View file

@ -1,21 +1,19 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from ui.views.corkDelegate import *
from ui.views.dndView import *
from ui.views.outlineBasics import *
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QListView
from manuskript import settings
from manuskript.ui.views.corkDelegate import corkDelegate
from manuskript.ui.views.dndView import dndView
from manuskript.ui.views.outlineBasics import outlineBasics
class corkView(QListView, dndView, outlineBasics):
def __init__(self, parent=None):
QListView.__init__(self, parent)
dndView.__init__(self, parent)
outlineBasics.__init__(self, parent)
self.setResizeMode(QListView.Adjust)
self.setWrapping(True)
self.setItemDelegate(corkDelegate())
@ -24,7 +22,7 @@ class corkView(QListView, dndView, outlineBasics):
self.setFlow(self.LeftToRight)
self.setSelectionBehavior(self.SelectRows)
self.updateBackground()
def updateBackground(self):
self.setStyleSheet("""QListView {{
background:{color};
@ -32,12 +30,12 @@ class corkView(QListView, dndView, outlineBasics):
}}""".format(
color=settings.corkBackground["color"],
url=settings.corkBackground["image"]
))
))
def dragMoveEvent(self, event):
dndView.dragMoveEvent(self, event)
QListView.dragMoveEvent(self, event)
def mouseReleaseEvent(self, event):
QListView.mouseReleaseEvent(self, event)
outlineBasics.mouseReleaseEvent(self, event)
outlineBasics.mouseReleaseEvent(self, event)

View file

@ -1,25 +1,20 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QAbstractItemView
from qt import *
from enums import *
from functions import *
class dndView(QAbstractItemView):
def __init__(self, parent=None):
#QAbstractItemView.__init__(self, parent)
# QAbstractItemView.__init__(self, parent)
self.setDragDropMode(self.DragDrop)
self.setDefaultDropAction(Qt.MoveAction)
self.setSelectionMode(self.ExtendedSelection)
def dragMoveEvent(self, event):
#return QAbstractItemView.dragMoveEvent(self, event)
#print(a)
# return QAbstractItemView.dragMoveEvent(self, event)
# print(a)
if event.keyboardModifiers() & Qt.ControlModifier:
event.setDropAction(Qt.CopyAction)
else:
event.setDropAction(Qt.MoveAction)
event.setDropAction(Qt.MoveAction)

View file

@ -1,12 +1,12 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QLineEdit
from manuskript.enums import Outline
from manuskript.functions import toString
class lineEditView(QLineEdit):
def __init__(self, parent=None):
QLineEdit.__init__(self, parent)
self._column = Outline.title.value
@ -14,14 +14,14 @@ class lineEditView(QLineEdit):
self._index = None
self._placeholderText = None
self._updating = False
def setModel(self, model):
self._model = model
self._model.dataChanged.connect(self.update)
def setColumn(self, col):
self._column = col
def setCurrentModelIndex(self, index):
self._indexes = None
if index.isValid():
@ -29,49 +29,49 @@ class lineEditView(QLineEdit):
index = index.sibling(index.row(), self._column)
self._index = index
self._model = index.model()
#self.item = index.internalPointer()
if self._placeholderText != None:
# self.item = index.internalPointer()
if self._placeholderText is not None:
self.setPlaceholderText(self._placeholderText)
self.textEdited.connect(self.submit)
self.updateText()
def setCurrentModelIndexes(self, indexes):
self._indexes = []
self._index = None
for i in indexes:
if i.isValid():
if i.column() != self._column:
i = i.sibling(i.row(), self._column)
self._indexes.append(i)
self.textEdited.connect(self.submit)
self.updateText()
def submit(self):
if self._index:
#item = self._index.internalPointer()
# item = self._index.internalPointer()
if self.text() != self._model.data(self._index):
self._model.setData(self._index, self.text())
elif self._indexes:
self._updating = True
for i in self._indexes:
#item = i.internalPointer()
# item = i.internalPointer()
if self.text() != self._model.data(i):
self._model.setData(i, self.text())
self._updating = False
def update(self, topLeft, bottomRight):
if self._updating:
# We are currently putting data in the model, so no updates
return
if self._index:
if topLeft.row() <= self._index.row() <= bottomRight.row():
self.updateText()
elif self._indexes:
update = False
for i in self._indexes:
@ -79,35 +79,34 @@ class lineEditView(QLineEdit):
update = True
if update:
self.updateText()
def updateText(self):
if self._index:
#item = self._index.internalPointer()
#txt = toString(item.data(self._column))
# item = self._index.internalPointer()
# txt = toString(item.data(self._column))
txt = toString(self._model.data(self._index))
if self.text() != txt:
self.setText(txt)
elif self._indexes:
t = []
same = True
for i in self._indexes:
#item = i.internalPointer()
#t.append(toString(item.data(self._column)))
# item = i.internalPointer()
# t.append(toString(item.data(self._column)))
t.append(toString(self._model.data(i)))
for t2 in t[1:]:
if t2 != t[0]:
same = False
break
if same:
self.setText(t[0])
else:
self.setText("")
if not self._placeholderText:
self._placeholderText = self.placeholderText()
self.setPlaceholderText(self.tr("Various"))

View file

@ -1,12 +1,12 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.views.metadataView_ui import *
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QWidget
from manuskript.enums import Outline
from manuskript.ui.views.metadataView_ui import Ui_metadataView
class metadataView(QWidget, Ui_metadataView):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
@ -15,37 +15,37 @@ class metadataView(QWidget, Ui_metadataView):
self.txtSummaryFull.setColumn(Outline.summaryFull.value)
self.txtNotes.setColumn(Outline.notes.value)
self.revisions.setEnabled(False)
def setModels(self, mdlOutline, mdlPersos, mdlLabels, mdlStatus):
self.properties.setModels(mdlOutline, mdlPersos, mdlLabels, mdlStatus)
self.txtSummarySentance.setModel(mdlOutline)
self.txtSummaryFull.setModel(mdlOutline)
self.txtNotes.setModel(mdlOutline)
self.revisions.setModel(mdlOutline)
def getIndexes(self, sourceView):
"Returns a list of indexes from list of QItemSelectionRange"
"""Returns a list of indexes from list of QItemSelectionRange"""
indexes = []
for i in sourceView.selectionModel().selection().indexes():
if i.column() != 0:
if i.column() != 0:
continue
if i not in indexes:
indexes.append(i)
return indexes
def selectionChanged(self, sourceView):
indexes = self.getIndexes(sourceView)
if self._lastIndexes == indexes:
return
if len(indexes) == 0:
self.setEnabled(False)
self.revisions.setEnabled(False)
elif len(indexes) == 1:
self.setEnabled(True)
idx = indexes[0]
@ -54,25 +54,25 @@ class metadataView(QWidget, Ui_metadataView):
self.txtNotes.setCurrentModelIndex(idx)
self.revisions.setEnabled(True)
self.revisions.setCurrentModelIndex(idx)
else:
self.setEnabled(True)
self.txtSummarySentance.setCurrentModelIndexes(indexes)
self.txtSummaryFull.setCurrentModelIndexes(indexes)
self.txtNotes.setCurrentModelIndexes(indexes)
self.revisions.setEnabled(False)
self.properties.selectionChanged(sourceView)
self._lastIndexes = indexes
def setDict(self, d):
self.txtNotes.setDict(d)
self.txtSummaryFull.setDict(d)
def toggleSpellcheck(self, v):
self.txtNotes.toggleSpellcheck(v)
self.txtSummaryFull.toggleSpellcheck(v)
def saveState(self):
return [
self.grpProperties.saveState(),
@ -80,10 +80,10 @@ class metadataView(QWidget, Ui_metadataView):
self.grpNotes.saveState(),
self.grpRevisions.saveState(),
self.revisions.saveState()
]
]
def restoreState(self, state):
self.grpProperties.restoreState(state[0])
self.grpSummary.restoreState(state[1])
self.grpNotes.restoreState(state[2])
self.grpRevisions.restoreState(state[3])
self.grpRevisions.restoreState(state[3])

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/views/metadataView_ui.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
@ -83,9 +83,9 @@ class Ui_metadataView(object):
self.grpNotes.setTitle(_translate("metadataView", "Notes / References"))
self.grpRevisions.setTitle(_translate("metadataView", "Revisions"))
from ui.collapsibleGroupBox2 import collapsibleGroupBox2
from ui.views.propertiesView import propertiesView
from ui.views.textEditView import textEditView
from ui.revisions import revisions
from ui.views.textEditCompleter import textEditCompleter
from ui.views.lineEditView import lineEditView
from manuskript.ui.collapsibleGroupBox2 import collapsibleGroupBox2
from manuskript.ui.revisions import revisions
from manuskript.ui.views.lineEditView import lineEditView
from manuskript.ui.views.propertiesView import propertiesView
from manuskript.ui.views.textEditCompleter import textEditCompleter
from manuskript.ui.views.textEditView import textEditView

View file

@ -137,34 +137,34 @@
<customwidget>
<class>textEditView</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditView.h</header>
<header>manuskript.ui.views.textEditView.h</header>
</customwidget>
<customwidget>
<class>lineEditView</class>
<extends>QLineEdit</extends>
<header>ui.views.lineEditView.h</header>
<header>manuskript.ui.views.lineEditView.h</header>
</customwidget>
<customwidget>
<class>collapsibleGroupBox2</class>
<extends>QGroupBox</extends>
<header>ui.collapsibleGroupBox2.h</header>
<header>manuskript.ui.collapsibleGroupBox2.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>propertiesView</class>
<extends>QWidget</extends>
<header>ui.views.propertiesView.h</header>
<header>manuskript.ui.views.propertiesView.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>textEditCompleter</class>
<extends>QTextEdit</extends>
<header>ui.views.textEditCompleter.h</header>
<header>manuskript.ui.views.textEditCompleter.h</header>
</customwidget>
<customwidget>
<class>revisions</class>
<extends>QWidget</extends>
<header>ui.revisions.h</header>
<header>manuskript.ui.revisions.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View file

@ -1,68 +1,73 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from models.outlineModel import *
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QSignalMapper
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QAbstractItemView, qApp, QMenu, QAction
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import mainWindow
from manuskript.functions import toInt
from manuskript.models.outlineModel import outlineItem
class outlineBasics(QAbstractItemView):
def __init__(self, parent=None):
pass
def getSelection(self):
sel = []
for i in self.selectedIndexes():
if i.column() != 0: continue
if not i in sel: sel.append(i)
if i.column() != 0:
continue
if not i in sel:
sel.append(i)
return sel
def mouseReleaseEvent(self, event):
if event.button() == Qt.RightButton:
self.menu = self.makePopupMenu()
self.menu.popup(event.globalPos())
else:
QAbstractItemView.mouseReleaseEvent(self, event)
def makePopupMenu(self):
index = self.currentIndex()
sel = self.getSelection()
clipboard = qApp.clipboard()
menu = QMenu(self)
# Add / remove items
self.actAddFolder = QAction(QIcon.fromTheme("folder-new"), qApp.translate("outlineBasics", "New Folder"), menu)
self.actAddFolder.triggered.connect(self.addFolder)
menu.addAction(self.actAddFolder)
self.actAddText = QAction(QIcon.fromTheme("document-new"), qApp.translate("outlineBasics", "New Text"), menu)
self.actAddText.triggered.connect(self.addText)
menu.addAction(self.actAddText)
self.actDelete = QAction(QIcon.fromTheme("edit-delete"), qApp.translate("outlineBasics", "Delete"), menu)
self.actDelete.triggered.connect(self.delete)
menu.addAction(self.actDelete)
menu.addSeparator()
# Copy, cut, paste
self.actCopy = QAction(QIcon.fromTheme("edit-copy"), qApp.translate("outlineBasics", "Copy"), menu)
self.actCopy.triggered.connect(self.copy)
menu.addAction(self.actCopy)
self.actCut = QAction(QIcon.fromTheme("edit-cut"), qApp.translate("outlineBasics", "Cut"), menu)
self.actCut.triggered.connect(self.cut)
menu.addAction(self.actCut)
self.actPaste = QAction(QIcon.fromTheme("edit-paste"), qApp.translate("outlineBasics", "Paste"), menu)
self.actPaste.triggered.connect(self.paste)
menu.addAction(self.actPaste)
menu.addSeparator()
# POV
self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
mw = mainWindow()
@ -70,33 +75,33 @@ class outlineBasics(QAbstractItemView):
a.triggered.connect(lambda: self.setPOV(""))
self.menuPOV.addAction(a)
self.menuPOV.addSeparator()
menus = []
for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
m = QMenu(i, self.menuPOV)
menus.append(m)
self.menuPOV.addMenu(m)
mpr = QSignalMapper(self.menuPOV)
for i in range(mw.mdlPersos.rowCount()):
a = QAction(mw.mdlPersos.icon(i), mw.mdlPersos.name(i), self.menuPOV)
a.triggered.connect(mpr.map)
mpr.setMapping(a, int(mw.mdlPersos.ID(i)))
imp = toInt(mw.mdlPersos.importance(i))
menus[2-imp].addAction(a)
menus[2 - imp].addAction(a)
mpr.mapped.connect(self.setPOV)
menu.addMenu(self.menuPOV)
# Status
self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu)
#a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
#a.triggered.connect(lambda: self.setStatus(""))
#self.menuStatus.addAction(a)
#self.menuStatus.addSeparator()
# a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
# a.triggered.connect(lambda: self.setStatus(""))
# self.menuStatus.addAction(a)
# self.menuStatus.addSeparator()
mpr = QSignalMapper(self.menuStatus)
for i in range(mw.mdlStatus.rowCount()):
a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
@ -105,29 +110,28 @@ class outlineBasics(QAbstractItemView):
self.menuStatus.addAction(a)
mpr.mapped.connect(self.setStatus)
menu.addMenu(self.menuStatus)
# Labels
self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu)
mpr = QSignalMapper(self.menuLabel)
for i in range(mw.mdlLabels.rowCount()):
a = QAction(mw.mdlLabels.item(i, 0).icon(),
mw.mdlLabels.item(i, 0).text(),
mw.mdlLabels.item(i, 0).text(),
self.menuLabel)
a.triggered.connect(mpr.map)
mpr.setMapping(a, i)
self.menuLabel.addAction(a)
mpr.mapped.connect(self.setLabel)
menu.addMenu(self.menuLabel)
if len(sel) > 0 and index.isValid() and not index.internalPointer().isFolder() \
or not clipboard.mimeData().hasFormat("application/xml"):
or not clipboard.mimeData().hasFormat("application/xml"):
self.actPaste.setEnabled(False)
if len(sel) > 0 and index.isValid() and not index.internalPointer().isFolder():
self.actAddFolder.setEnabled(False)
self.actAddText.setEnabled(False)
if len(sel) == 0:
self.actCopy.setEnabled(False)
self.actCut.setEnabled(False)
@ -135,53 +139,53 @@ class outlineBasics(QAbstractItemView):
self.menuPOV.setEnabled(False)
self.menuStatus.setEnabled(False)
self.menuLabel.setEnabled(False)
return menu
def addFolder(self):
self.addItem("folder")
def addText(self):
self.addItem("text")
def addItem(self, _type="folder"):
if len(self.selectedIndexes()) == 0:
parent = self.rootIndex()
else:
parent = self.currentIndex()
if _type == "text":
_type = settings.defaultTextType
item = outlineItem(title=qApp.translate("outlineBasics", "New"), _type=_type)
self.model().appendItem(item, parent)
def copy(self):
mimeData = self.model().mimeData(self.selectionModel().selectedIndexes())
qApp.clipboard().setMimeData(mimeData)
def paste(self):
index = self.currentIndex()
if len(self.getSelection()) == 0:
index = self.rootIndex()
data = qApp.clipboard().mimeData()
self.model().dropMimeData(data, Qt.CopyAction, -1, 0, index)
def cut(self):
self.copy()
self.delete()
def delete(self):
self.model().removeIndexes(self.getSelection())
def setPOV(self, POV):
for i in self.getSelection():
self.model().setData(i.sibling(i.row(), Outline.POV.value), str(POV))
def setStatus(self, status):
for i in self.getSelection():
self.model().setData(i.sibling(i.row(), Outline.status.value), str(status))
def setLabel(self, label):
for i in self.getSelection():
self.model().setData(i.sibling(i.row(), Outline.label.value), str(label))
self.model().setData(i.sibling(i.row(), Outline.label.value), str(label))

View file

@ -1,49 +1,53 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QSize, QModelIndex
from PyQt5.QtGui import QColor, QPalette, QIcon, QFont, QFontMetrics, QBrush
from PyQt5.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem, QStyle, QComboBox, QStyleOptionComboBox
from PyQt5.QtWidgets import qApp
from manuskript import settings
from manuskript.enums import Perso, Outline
from manuskript.functions import outlineItemColors, mixColors, colorifyPixmap, toInt, toFloat, drawProgress
from qt import *
from enums import *
from functions import *
import settings
class outlineTitleDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
self._view = None
def setView(self, view):
self._view = view
def paint(self, painter, option, index):
item = index.internalPointer()
colors = outlineItemColors(item)
style = qApp.style()
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, index)
iconRect = style.subElementRect(style.SE_ItemViewItemDecoration, opt)
textRect = style.subElementRect(style.SE_ItemViewItemText, opt)
# Background
style.drawPrimitive(style.PE_PanelItemViewItem, opt, painter)
if settings.viewSettings["Outline"]["Background"] != "Nothing" and not opt.state & QStyle.State_Selected:
col = colors[settings.viewSettings["Outline"]["Background"]]
if col != QColor(Qt.transparent):
col2 = QColor(Qt.white)
if opt.state & QStyle.State_Selected:
col2 = opt.palette.brush(QPalette.Normal, QPalette.Highlight).color()
col = mixColors(col, col2, .2)
painter.save()
painter.setBrush(col)
painter.setPen(Qt.NoPen)
rect = opt.rect
if self._view:
r2 = self._view.visualRect(index)
@ -51,10 +55,10 @@ class outlineTitleDelegate(QStyledItemDelegate):
rect.setLeft(r2.left())
rect.setTop(r2.top())
rect.setBottom(r2.bottom())
painter.drawRoundedRect(rect, 5, 5)
painter.restore()
# Icon
mode = QIcon.Normal
if not opt.state & QStyle.State_Enabled:
@ -68,7 +72,7 @@ class outlineTitleDelegate(QStyledItemDelegate):
colorifyPixmap(icon, color)
opt.icon = QIcon(icon)
opt.icon.paint(painter, iconRect, opt.decorationAlignment, mode, state)
# Text
if opt.text:
painter.save()
@ -82,49 +86,49 @@ class outlineTitleDelegate(QStyledItemDelegate):
fm = QFontMetrics(f)
elidedText = fm.elidedText(opt.text, Qt.ElideRight, textRect.width())
painter.drawText(textRect, Qt.AlignLeft, elidedText)
painter.restore()
#QStyledItemDelegate.paint(self, painter, option, index)
# QStyledItemDelegate.paint(self, painter, option, index)
class outlinePersoDelegate(QStyledItemDelegate):
def __init__(self, mdlPersos, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.mdlPersos = mdlPersos
def sizeHint(self, option, index):
#s = QStyledItemDelegate.sizeHint(self, option, index)
# s = QStyledItemDelegate.sizeHint(self, option, index)
item = QModelIndex()
for i in range(self.mdlPersos.rowCount()):
if self.mdlPersos.ID(i) == index.data():
item = self.mdlPersos.index(i, Perso.name.value)
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, item)
s = QStyledItemDelegate.sizeHint(self, opt, item)
if s.width() > 200:
s.setWidth(200)
elif s.width() < 100:
s.setWidth(100)
return s + QSize(18, 0)
def createEditor(self, parent, option, index):
item = index.internalPointer()
#if item.isFolder(): # No POV for folders
#return
# if item.isFolder(): # No POV for folders
# return
editor = QComboBox(parent)
editor.setAutoFillBackground(True)
editor.setFrame(False)
return editor
def setEditorData(self, editor, index):
#editor.addItem("")
# editor.addItem("")
editor.addItem(QIcon.fromTheme("dialog-no"), self.tr("None"))
l = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
for importance in range(3):
editor.addItem(l[importance])
@ -134,112 +138,110 @@ class outlinePersoDelegate(QStyledItemDelegate):
item.setFlags(Qt.ItemIsEnabled)
for i in range(self.mdlPersos.rowCount()):
imp = toInt(self.mdlPersos.importance(i))
if not 2-imp == importance: continue
#try:
if not 2 - imp == importance: continue
# try:
editor.addItem(self.mdlPersos.icon(i), self.mdlPersos.name(i), self.mdlPersos.ID(i))
editor.setItemData(editor.count() - 1, self.mdlPersos.name(i), Qt.ToolTipRole)
#except:
#pass
# except:
# pass
editor.setCurrentIndex(editor.findData(index.data()))
editor.showPopup()
def setModelData(self, editor, model, index):
val = editor.currentData()
model.setData(index, val)
def paint(self, painter, option, index):
##option.rect.setWidth(option.rect.width() - 18)
#QStyledItemDelegate.paint(self, painter, option, index)
# QStyledItemDelegate.paint(self, painter, option, index)
##option.rect.setWidth(option.rect.width() + 18)
item = QModelIndex()
for i in range(self.mdlPersos.rowCount()):
if self.mdlPersos.ID(i) == index.data():
item = self.mdlPersos.index(i, Perso.name.value)
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, item)
qApp.style().drawControl(QStyle.CE_ItemViewItem, opt, painter)
#if index.isValid() and index.internalPointer().data(Outline.POV.value) not in ["", None]:
# if index.isValid() and index.internalPointer().data(Outline.POV.value) not in ["", None]:
if index.isValid() and self.mdlPersos.data(index) not in ["", None]:
opt = QStyleOptionComboBox()
opt.rect = option.rect
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
option.rect = r
qApp.style().drawPrimitive(QStyle.PE_IndicatorArrowDown, option, painter)
class outlineCompileDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def displayText(self, value, locale):
return ""
class outlineGoalPercentageDelegate(QStyledItemDelegate):
def __init__(self, rootIndex=None, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.rootIndex = rootIndex
def sizeHint(self, option, index):
sh = QStyledItemDelegate.sizeHint(self, option, index)
#if sh.width() > 50:
# if sh.width() > 50:
sh.setWidth(100)
return sh
def paint(self, painter, option, index):
if not index.isValid():
return QStyledItemDelegate.paint(self, painter, option, index)
QStyledItemDelegate.paint(self, painter, option, index)
item = index.internalPointer()
if not item.data(Outline.goal.value):
return
p = toFloat(item.data(Outline.goalPercentage.value))
typ = item.data(Outline.type.value)
level = item.level()
if self.rootIndex and self.rootIndex.isValid():
level -= self.rootIndex.internalPointer().level() + 1
margin = 5
height = max(min(option.rect.height() - 2*margin, 12) - 2 * level, 6)
height = max(min(option.rect.height() - 2 * margin, 12) - 2 * level, 6)
painter.save()
rect = option.rect.adjusted(margin, margin, -margin, -margin)
# Move
rect.translate(level * rect.width() / 10, 0)
rect.setWidth(rect.width() - level * rect.width() / 10)
rect.setHeight(height)
rect.setTop(option.rect.top() + (option.rect.height() - height) / 2)
drawProgress(painter, rect, p) # from functions
drawProgress(painter, rect, p) # from functions
painter.restore()
def displayText(self, value, locale):
return ""
class outlineStatusDelegate(QStyledItemDelegate):
def __init__(self, mdlStatus, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.mdlStatus = mdlStatus
def sizeHint(self, option, index):
s = QStyledItemDelegate.sizeHint(self, option, index)
if s.width() > 150:
@ -247,52 +249,51 @@ class outlineStatusDelegate(QStyledItemDelegate):
elif s.width() < 50:
s.setWidth(50)
return s + QSize(18, 0)
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
editor.setAutoFillBackground(True)
editor.setFrame(False)
return editor
def setEditorData(self, editor, index):
for i in range(self.mdlStatus.rowCount()):
editor.addItem(self.mdlStatus.item(i, 0).text())
val = index.internalPointer().data(Outline.status.value)
if not val: val = 0
editor.setCurrentIndex(int(val))
editor.showPopup()
def setModelData(self, editor, model, index):
val = editor.currentIndex()
model.setData(index, val)
def displayText(self, value, locale):
try:
return self.mdlStatus.item(int(value), 0).text()
except:
return ""
def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, index)
if index.isValid() and index.internalPointer().data(Outline.status.value) not in ["", None, "0"]:
opt = QStyleOptionComboBox()
opt.rect = option.rect
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
option.rect = r
qApp.style().drawPrimitive(QStyle.PE_IndicatorArrowDown, option, painter)
class outlineLabelDelegate(QStyledItemDelegate):
def __init__(self, mdlLabels, parent=None):
QStyledItemDelegate.__init__(self, parent)
self.mdlLabels = mdlLabels
def sizeHint(self, option, index):
d = index.internalPointer().data(index.column(), Qt.DisplayRole)
if not d:
if not d:
d = 0
item = self.mdlLabels.item(int(d), 0)
idx = self.mdlLabels.indexFromItem(item)
@ -304,44 +305,44 @@ class outlineLabelDelegate(QStyledItemDelegate):
elif s.width() < 50:
s.setWidth(50)
return s + QSize(18, 0)
def createEditor(self, parent, option, index):
item = index.internalPointer()
editor = QComboBox(parent)
#editor.setAutoFillBackground(True)
# editor.setAutoFillBackground(True)
editor.setFrame(False)
return editor
def setEditorData(self, editor, index):
for i in range(self.mdlLabels.rowCount()):
editor.addItem(self.mdlLabels.item(i, 0).icon(),
self.mdlLabels.item(i, 0).text())
val = index.internalPointer().data(Outline.label.value)
if not val: val = 0
editor.setCurrentIndex(int(val))
editor.showPopup()
def setModelData(self, editor, model, index):
val = editor.currentIndex()
model.setData(index, val)
def paint(self, painter, option, index):
if not index.isValid():
return QStyledItemDelegate.paint(self, painter, option, index)
else:
item = index.internalPointer()
d = item.data(index.column(), Qt.DisplayRole)
if not d:
if not d:
d = 0
lbl = self.mdlLabels.item(int(d), 0)
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, self.mdlLabels.indexFromItem(lbl))
qApp.style().drawControl(QStyle.CE_ItemViewItem, opt, painter)
# Drop down indicator
if index.isValid() and index.internalPointer().data(Outline.label.value) not in ["", None, "0"]:
opt = QStyleOptionComboBox()
@ -349,4 +350,3 @@ class outlineLabelDelegate(QStyledItemDelegate):
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
option.rect = r
qApp.style().drawPrimitive(QStyle.PE_IndicatorArrowDown, option, painter)

View file

@ -1,47 +1,45 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QTreeView, QHeaderView
from manuskript import settings
from manuskript.enums import Outline
from manuskript.ui.views.dndView import dndView
from manuskript.ui.views.outlineBasics import outlineBasics
from manuskript.ui.views.outlineDelegates import outlineTitleDelegate, outlinePersoDelegate, outlineCompileDelegate, \
outlineStatusDelegate, outlineGoalPercentageDelegate, outlineLabelDelegate
from qt import *
from enums import *
from functions import *
from ui.views.outlineDelegates import *
from ui.views.dndView import *
from ui.views.outlineBasics import *
class outlineView(QTreeView, dndView, outlineBasics):
def __init__(self, parent=None, modelPersos=None, modelLabels=None, modelStatus=None):
QTreeView.__init__(self, parent)
dndView.__init__(self)
outlineBasics.__init__(self, parent)
self.modelPersos = modelPersos
self.modelLabels = modelLabels
self.modelStatus = modelStatus
self.header().setStretchLastSection(False)
def setModelPersos(self, model):
# This is used by outlinePersoDelegate to select character
self.modelPersos = model
def setModelLabels(self, model):
# This is used by outlineLabelDelegate to display labels
self.modelLabels = model
def setModelStatus(self, model):
# This is used by outlineStatusDelegate to display statuses
self.modelStatus = model
def setModel(self, model):
QTreeView.setModel(self, model)
# Setting delegates
self.outlineTitleDelegate = outlineTitleDelegate(self)
#self.outlineTitleDelegate.setView(self)
# self.outlineTitleDelegate.setView(self)
self.setItemDelegateForColumn(Outline.title.value, self.outlineTitleDelegate)
self.outlinePersoDelegate = outlinePersoDelegate(self.modelPersos)
self.setItemDelegateForColumn(Outline.POV.value, self.outlinePersoDelegate)
@ -53,10 +51,10 @@ class outlineView(QTreeView, dndView, outlineBasics):
self.setItemDelegateForColumn(Outline.goalPercentage.value, self.outlineGoalPercentageDelegate)
self.outlineLabelDelegate = outlineLabelDelegate(self.modelLabels)
self.setItemDelegateForColumn(Outline.label.value, self.outlineLabelDelegate)
# Hiding columns
self.hideColumns()
self.header().setSectionResizeMode(Outline.title.value, QHeaderView.Stretch)
self.header().setSectionResizeMode(Outline.POV.value, QHeaderView.ResizeToContents)
self.header().setSectionResizeMode(Outline.status.value, QHeaderView.ResizeToContents)
@ -65,23 +63,22 @@ class outlineView(QTreeView, dndView, outlineBasics):
self.header().setSectionResizeMode(Outline.wordCount.value, QHeaderView.ResizeToContents)
self.header().setSectionResizeMode(Outline.goal.value, QHeaderView.ResizeToContents)
self.header().setSectionResizeMode(Outline.goalPercentage.value, QHeaderView.ResizeToContents)
def hideColumns(self):
for c in range(self.model().columnCount()):
self.hideColumn(c)
for c in settings.outlineViewColumns:
self.showColumn(c)
def setRootIndex(self, index):
QTreeView.setRootIndex(self, index)
self.outlineGoalPercentageDelegate = outlineGoalPercentageDelegate(index)
self.setItemDelegateForColumn(Outline.goalPercentage.value, self.outlineGoalPercentageDelegate)
def dragMoveEvent(self, event):
dndView.dragMoveEvent(self, event)
QTreeView.dragMoveEvent(self, event)
def mouseReleaseEvent(self, event):
QTreeView.mouseReleaseEvent(self, event)
outlineBasics.mouseReleaseEvent(self, event)

View file

@ -1,13 +1,13 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtCore import QSize, QModelIndex, Qt
from PyQt5.QtGui import QPixmap, QColor, QIcon, QBrush
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
from manuskript.enums import Perso
class persoTreeView(QTreeWidget):
def __init__(self, parent=None):
QTreeWidget.__init__(self, parent)
self._model = None
@ -19,43 +19,43 @@ class persoTreeView(QTreeWidget):
self.setIndentation(10)
self.setHeaderHidden(True)
self.setIconSize(QSize(24, 24))
self.setColumnCount(1)
self._rootItem = QTreeWidgetItem()
self.insertTopLevelItem(0, self._rootItem)
def setPersosModel(self, model):
self._model = model
self._model.dataChanged.connect(self.updateMaybe)
self._model.rowsInserted.connect(self.updateMaybe2)
self._model.rowsRemoved.connect(self.updateMaybe2)
self.updateItems()
def setFilter(self, text):
self._filter = text
self.updateItems()
def updateMaybe(self, topLeft, bottomRight):
if topLeft.parent() != QModelIndex():
return
if topLeft.column() <= Perso.name.value <= bottomRight.column():
# Update name
self.updateNames()
elif topLeft.column() <= Perso.importance.value <= bottomRight.column():
# Importance changed
self.updateItems()
def updateMaybe2(self, parent, first, last):
#Rows inserted or removed, we update only if they are topLevel rows.
# Rows inserted or removed, we update only if they are topLevel rows.
if parent == QModelIndex():
self.updateItems()
def updateNames(self):
for i in range(self.topLevelItemCount()):
item = self.topLevelItem(i)
for c in range(item.childCount()):
sub = item.child(c)
ID = sub.data(0, Qt.UserRole)
@ -68,18 +68,18 @@ class persoTreeView(QTreeWidget):
color = QColor(self._model.getPersoColorByID(ID))
px.fill(color)
sub.setIcon(0, QIcon(px))
def updateItems(self):
if not self._model:
return
if self.currentItem():
self._lastID = self.currentItem().data(0, Qt.UserRole)
self._updating = True
self.clear()
persos = self._model.getPersosByImportance()
h = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
for i in range(3):
cat = QTreeWidgetItem(self, [h[i]])
@ -90,11 +90,11 @@ class persoTreeView(QTreeWidget):
f.setBold(True)
cat.setFont(0, f)
self.addTopLevelItem(cat)
#cat.setChildIndicatorPolicy(cat.DontShowIndicator)
# cat.setChildIndicatorPolicy(cat.DontShowIndicator)
for ID in persos[i]:
name = self._model.getPersoNameByID(ID)
if not self._filter.lower() in name.lower():
if not self._filter.lower() in name.lower():
continue
item = QTreeWidgetItem(cat, [name])
item.setData(0, Qt.UserRole, ID)
@ -102,30 +102,29 @@ class persoTreeView(QTreeWidget):
color = QColor(self._model.getPersoColorByID(ID))
px.fill(color)
item.setIcon(0, QIcon(px))
if ID == self._lastID:
self.setCurrentItem(item)
self.expandAll()
self._updating = False
def getItemByID(self, ID):
for t in range(self.topLevelItemCount()):
for i in range(self.topLevelItem(t).childCount()):
item = self.topLevelItem(t).child(i)
if item.data(0, Qt.UserRole) == ID:
return item
def currentPersoIndex(self):
ID = None
if self.currentItem():
ID = self.currentItem().data(0, Qt.UserRole)
return self._model.getIndexFromID(ID)
def mouseDoubleClickEvent(self, event):
item = self.currentItem()
# Catching double clicks to forbid collapsing of toplevel items
if item.parent():
QTreeWidget.mouseDoubleClickEvent(self, event)

View file

@ -1,52 +1,53 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import settings
import collections
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QStyledItemDelegate, QLineEdit, QMenu, QAction
class plotDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def sizeHint(self, option, index):
s = QStyledItemDelegate.sizeHint(self, option, index)
if s.width() < 200:
s.setWidth(200)
return s
def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
editor.setFrame(False)
editor.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
return editor
def setEditorData(self, editor, index):
editor.setText(index.model().data(index))
self.txt = editor
self.menu = QMenu(editor)
plotsTypes = collections.OrderedDict({
self.tr("General"): [
self.tr("Promise"),
self.tr("Problem"),
self.tr("Progress"),
self.tr("Resolution")
],
],
self.tr("Try / Fail"): [
self.tr("No and"),
self.tr("Yes but"),
],
],
self.tr("Freytag's pyramid"): [
self.tr("Exposition"),
self.tr("Rising action"),
self.tr("Climax"),
self.tr("Falling action"),
self.tr("Resolution"),
],
],
self.tr("Three acts"): [
self.tr("1. Setup"),
self.tr("1. Inciting event"),
@ -59,8 +60,8 @@ class plotDelegate(QStyledItemDelegate):
self.tr("3. Stand up"),
self.tr("3. Climax"),
self.tr("3. Ending"),
],
],
self.tr("Hero's journey"): [
self.tr("Ordinary world"),
self.tr("Call to adventure"),
@ -74,12 +75,12 @@ class plotDelegate(QStyledItemDelegate):
self.tr("Transformation"),
self.tr("Atonement"),
self.tr("Return"),
],
})
],
})
for name in plotsTypes:
m = QMenu(name, self.menu)
for sub in plotsTypes[name]:
if sub == "---":
m.addSeparator()
@ -87,19 +88,19 @@ class plotDelegate(QStyledItemDelegate):
a = QAction(sub, m)
a.triggered.connect(self.submit)
m.addAction(a)
self.menu.addMenu(m)
editor.addAction(QIcon.fromTheme("list-add"), QLineEdit.LeadingPosition).triggered.connect(self.popupMenu)
def setModelData(self, editor, model, index):
val = editor.text()
model.setData(index, val)
def popupMenu(self):
act = self.sender()
self.menu.popup(self.txt.parent().mapToGlobal(self.txt.geometry().bottomLeft()))
def submit(self):
act = self.sender()
self.txt.setText(act.text())
self.txt.setText(act.text())

View file

@ -1,15 +1,16 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
import settings
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QModelIndex, QMimeData
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
from lxml import etree as ET
import models.references as Ref
from manuskript import settings
from manuskript.enums import Plot, Outline
from manuskript.models import references as Ref
class plotTreeView(QTreeWidget):
def __init__(self, parent=None):
QTreeWidget.__init__(self, parent)
self._model = None
@ -20,37 +21,38 @@ class plotTreeView(QTreeWidget):
self._showSubPlot = False
self.setRootIsDecorated(False)
self.setIndentation(10)
self.setColumnCount(1)
self._rootItem = QTreeWidgetItem()
self.insertTopLevelItem(0, self._rootItem)
#self.currentItemChanged.connect(self._currentItemChanged)
# self.currentItemChanged.connect(self._currentItemChanged)
###############################################################################
# SETTERS
###############################################################################
###############################################################################
# SETTERS
###############################################################################
def setShowSubPlot(self, v):
self._showSubPlot = v
self.updateItems()
def setPlotModel(self, model):
self._model = model
self._model.dataChanged.connect(self.updateMaybe)
self._model.rowsInserted.connect(self.updateMaybe2)
self._model.rowsRemoved.connect(self.updateMaybe2)
self.updateItems()
def setFilter(self, text):
self._filter = text
self.updateItems()
###############################################################################
# GETTERS
###############################################################################
###############################################################################
# GETTERS
###############################################################################
def getItemByID(self, ID):
"Recursively search items to find one whose data is ``ID``."
def find(item, ID):
if item.data(0, Qt.UserRole) == ID:
return item
@ -58,63 +60,63 @@ class plotTreeView(QTreeWidget):
r = find(item.child(i), ID)
if r:
return r
return find(self.invisibleRootItem(), ID)
def currentPlotIndex(self):
"Returns index of the current item in plot model."
ID = None
if self.currentItem():
ID = self.currentItem().data(0, Qt.UserRole)
return self._model.getIndexFromID(ID)
###############################################################################
# UPDATES
###############################################################################
###############################################################################
# UPDATES
###############################################################################
def updateMaybe(self, topLeft, bottomRight):
if topLeft.parent() != QModelIndex():
return
if topLeft.column() <= Plot.name.value <= bottomRight.column():
# Update name
self.updateNames()
elif topLeft.column() <= Plot.importance.value <= bottomRight.column():
# Importance changed
self.updateItems()
def updateMaybe2(self, parent, first, last):
"Rows inserted or removed"
if parent == QModelIndex():
self.updateItems()
elif self._showSubPlot:
self.updateItems()
def updateNames(self):
for i in range(self.topLevelItemCount()):
item = self.topLevelItem(i)
for c in range(item.childCount()):
sub = item.child(c)
ID = sub.data(0, Qt.UserRole)
if ID:
name = self._model.getPlotNameByID(ID)
sub.setText(0, name)
def updateItems(self):
if not self._model:
return
if self.currentItem():
self._lastID = self.currentItem().data(0, Qt.UserRole)
self._updating = True
self.clear()
plots = self._model.getPlotsByImportance()
h = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
for i in range(3):
cat = QTreeWidgetItem(self, [h[i]])
@ -126,71 +128,71 @@ class plotTreeView(QTreeWidget):
cat.setFont(0, f)
cat.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
self.addTopLevelItem(cat)
#cat.setChildIndicatorPolicy(cat.DontShowIndicator)
# cat.setChildIndicatorPolicy(cat.DontShowIndicator)
for ID in plots[i]:
name = self._model.getPlotNameByID(ID)
if not self._filter.lower() in name.lower():
if not self._filter.lower() in name.lower():
continue
item = QTreeWidgetItem(cat, [name])
item.setData(0, Qt.UserRole, ID)
item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
if self._showSubPlot:
f = item.font(0)
f.setBold(True)
item.setFont(0, f)
for subID, name, summary in self._model.getSubPlotsByID(ID):
sub = QTreeWidgetItem(item, [name])
#sub.setData(0, Qt.UserRole, "{}:{}".format(ID, subID))
# sub.setData(0, Qt.UserRole, "{}:{}".format(ID, subID))
sub.setData(0, Qt.UserRole, ID)
if ID == self._lastID:
self.setCurrentItem(item)
self.expandAll()
self._updating = False
###############################################################################
# DRAG N DROP
###############################################################################
###############################################################################
# DRAG N DROP
###############################################################################
def mimeTypes(self):
return ["application/xml"]
def mimeData(self, items):
mimeData = QMimeData()
encodedData = ""
root = ET.Element("outlineItems")
for item in items:
plotID = item.data(0, Qt.UserRole)
subplotRaw = item.parent().indexOfChild(item)
_id, name, summary = self._model.getSubPlotsByID(plotID)[subplotRaw]
sub = ET.Element("outlineItem")
sub = ET.Element("outlineItem")
sub.set(Outline.title.name, name)
sub.set(Outline.type.name, settings.defaultTextType)
sub.set(Outline.summaryFull.name, summary)
sub.set(Outline.notes.name, self.tr("**Plot:** {}").format(
Ref.plotReference(plotID)))
root.append(sub)
encodedData = ET.tostring(root)
mimeData.setData("application/xml", encodedData)
return mimeData
Ref.plotReference(plotID)))
###############################################################################
# EVENTS
###############################################################################
root.append(sub)
encodedData = ET.tostring(root)
mimeData.setData("application/xml", encodedData)
return mimeData
###############################################################################
# EVENTS
###############################################################################
def mouseDoubleClickEvent(self, event):
item = self.currentItem()
# Catching double clicks to forbid collapsing of toplevel items
if item.parent():
QTreeWidget.mouseDoubleClickEvent(self, event)
QTreeWidget.mouseDoubleClickEvent(self, event)

View file

@ -1,17 +1,17 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.views.propertiesView_ui import *
# --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QWidget
from manuskript.enums import Outline
from manuskript.ui.views.propertiesView_ui import Ui_propertiesView
class propertiesView(QWidget, Ui_propertiesView):
def __init__(self, parent=None):
QWidget.__init__(self)
self.setupUi(self)
self.txtGoal.setColumn(Outline.setGoal.value)
def setModels(self, mdlOutline, mdlPersos, mdlLabels, mdlStatus):
self.cmbPOV.setModels(mdlPersos, mdlOutline)
self.cmbLabel.setModels(mdlLabels, mdlOutline)
@ -20,27 +20,27 @@ class propertiesView(QWidget, Ui_propertiesView):
self.chkCompile.setModel(mdlOutline)
self.txtTitle.setModel(mdlOutline)
self.txtGoal.setModel(mdlOutline)
def getIndexes(self, sourceView):
"Returns a list of indexes from list of QItemSelectionRange"
"""Returns a list of indexes from list of QItemSelectionRange"""
indexes = []
for i in sourceView.selectionModel().selection().indexes():
if i.column() != 0:
if i.column() != 0:
continue
if i not in indexes:
indexes.append(i)
return indexes
def selectionChanged(self, sourceView):
indexes = self.getIndexes(sourceView)
#print(indexes)
# print(indexes)
if len(indexes) == 0:
self.setEnabled(False)
elif len(indexes) == 1:
self.setEnabled(True)
self.setLabelsItalic(False)
@ -51,9 +51,9 @@ class propertiesView(QWidget, Ui_propertiesView):
self.chkCompile.setCurrentModelIndex(idx)
self.txtTitle.setCurrentModelIndex(idx)
self.txtGoal.setCurrentModelIndex(idx)
self.cmbType.setCurrentModelIndex(idx)
else:
self.setEnabled(True)
self.setLabelsItalic(True)
@ -63,9 +63,9 @@ class propertiesView(QWidget, Ui_propertiesView):
self.cmbPOV.setCurrentModelIndexes(indexes)
self.cmbLabel.setCurrentModelIndexes(indexes)
self.cmbStatus.setCurrentModelIndexes(indexes)
self.cmbType.setCurrentModelIndexes(indexes)
def setLabelsItalic(self, value):
f = self.lblPOV.font()
f.setItalic(value)
@ -75,5 +75,5 @@ class propertiesView(QWidget, Ui_propertiesView):
self.lblLabel,
self.lblCompile,
self.lblGoal
]:
lbl.setFont(f)
]:
lbl.setFont(f)

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/views/propertiesView_ui.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
# Created by: PyQt5 UI code generator 5.4.2
#
# WARNING! All changes made in this file will be lost!
@ -107,8 +107,8 @@ class Ui_propertiesView(object):
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.page_2)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.formLayout_2 = QtWidgets.QFormLayout()
self.formLayout_2.setObjectName("formLayout_2")
@ -194,9 +194,9 @@ class Ui_propertiesView(object):
self.label_36.setText(_translate("propertiesView", "Goal"))
self.txtGoalMulti.setPlaceholderText(_translate("propertiesView", "Word count"))
from ui.views.lineEditView import lineEditView
from ui.views.chkOutlineCompile import chkOutlineCompile
from ui.views.cmbOutlineTypeChoser import cmbOutlineTypeChoser
from ui.views.cmbOutlineLabelChoser import cmbOutlineLabelChoser
from ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser
from ui.views.cmbOutlineStatusChoser import cmbOutlineStatusChoser
from manuskript.ui.views.chkOutlineCompile import chkOutlineCompile
from manuskript.ui.views.cmbOutlineLabelChoser import cmbOutlineLabelChoser
from manuskript.ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser
from manuskript.ui.views.cmbOutlineStatusChoser import cmbOutlineStatusChoser
from manuskript.ui.views.cmbOutlineTypeChoser import cmbOutlineTypeChoser
from manuskript.ui.views.lineEditView import lineEditView

View file

@ -297,32 +297,32 @@
<customwidget>
<class>lineEditView</class>
<extends>QLineEdit</extends>
<header>ui.views.lineEditView.h</header>
<header>manuskript.ui.views.lineEditView.h</header>
</customwidget>
<customwidget>
<class>cmbOutlinePersoChoser</class>
<extends>QComboBox</extends>
<header>ui.views.cmbOutlinePersoChoser.h</header>
<header>manuskript.ui.views.cmbOutlinePersoChoser.h</header>
</customwidget>
<customwidget>
<class>cmbOutlineStatusChoser</class>
<extends>QComboBox</extends>
<header>ui.views.cmbOutlineStatusChoser.h</header>
<header>manuskript.ui.views.cmbOutlineStatusChoser.h</header>
</customwidget>
<customwidget>
<class>chkOutlineCompile</class>
<extends>QCheckBox</extends>
<header>ui.views.chkOutlineCompile.h</header>
<header>manuskript.ui.views.chkOutlineCompile.h</header>
</customwidget>
<customwidget>
<class>cmbOutlineLabelChoser</class>
<extends>QComboBox</extends>
<header>ui.views.cmbOutlineLabelChoser.h</header>
<header>manuskript.ui.views.cmbOutlineLabelChoser.h</header>
</customwidget>
<customwidget>
<class>cmbOutlineTypeChoser</class>
<extends>QComboBox</extends>
<header>ui.views.cmbOutlineTypeChoser.h</header>
<header>manuskript.ui.views.cmbOutlineTypeChoser.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -1,53 +1,55 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from functions import *
from ui.views.textEditView import *
from ui.editors.completer import *
import models.references as Ref
import settings
# --!-- coding: utf8 --!--
import re
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor, QFont, QFontMetrics
from PyQt5.QtWidgets import QAction, qApp, QToolTip, QTextEdit
from manuskript.ui.editors.completer import completer
from manuskript.ui.views.textEditView import textEditView
from manuskript.models import references as Ref
try:
import enchant
except ImportError:
enchant = None
class textEditCompleter(textEditView):
def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="", autoResize=False):
textEditView.__init__(self, parent=parent, index=index, html=html, spellcheck=spellcheck, highlighting=True, dict=dict, autoResize=autoResize)
def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="",
autoResize=False):
textEditView.__init__(self, parent=parent, index=index, html=html, spellcheck=spellcheck, highlighting=True,
dict=dict, autoResize=autoResize)
self.completer = None
self.setMouseTracking(True)
self.refRects = []
self.textChanged.connect(self.getRefRects)
self.document().documentLayoutChanged.connect(self.getRefRects)
def setCurrentModelIndex(self, index):
textEditView.setCurrentModelIndex(self, index)
if self._index and not self.completer:
self.setCompleter(completer())
def setCompleter(self, completer):
self.completer = completer
self.completer.activated.connect(self.insertCompletion)
def insertCompletion(self, txt):
tc = self.textCursor()
tc.insertText(txt)
self.setTextCursor(tc)
def textUnderCursor(self, select=False):
tc = self.textCursor()
tc.select(QTextCursor.WordUnderCursor)
if select:
self.setTextCursor(tc)
return tc.selectedText()
def refUnderCursor(self, cursor):
pos = cursor.position()
cursor.select(QTextCursor.BlockUnderCursor)
@ -57,27 +59,27 @@ class textEditCompleter(textEditView):
for m in match:
if text.find(m) <= pos <= text.find(m) + len(m):
return m
#def event(self, event):
#if event.type() == QEvent.ToolTip:
#cursor = self.cursorForPosition(event.pos())
#ref = self.refUnderCursor(cursor)
#if ref:
#QToolTip.showText(self.mapToGlobal(event.pos()), infoForRef(ref))
#else:
#QToolTip.hideText()
#return True
#return textEditView.event(self, event)
# def event(self, event):
# if event.type() == QEvent.ToolTip:
# cursor = self.cursorForPosition(event.pos())
# ref = self.refUnderCursor(cursor)
# if ref:
# QToolTip.showText(self.mapToGlobal(event.pos()), infoForRef(ref))
# else:
# QToolTip.hideText()
# return True
# return textEditView.event(self, event)
def createStandardContextMenu(self):
menu = textEditView.createStandardContextMenu(self)
a = QAction(self.tr("Insert reference"), menu)
a.triggered.connect(self.popupCompleter)
menu.insertSeparator(menu.actions()[0])
menu.insertAction(menu.actions()[0], a)
return menu
def keyPressEvent(self, event):
if self.completer.isVisible():
if event.key() in (
@ -88,17 +90,17 @@ class textEditCompleter(textEditView):
Qt.Key_Backtab):
event.ignore()
return
isShortcut = (event.modifiers() == Qt.ControlModifier and\
isShortcut = (event.modifiers() == Qt.ControlModifier and \
event.key() == Qt.Key_Space)
if not self.completer or not isShortcut:
self.completer.setVisible(False)
textEditView.keyPressEvent(self, event)
return
self.popupCompleter()
def popupCompleter(self):
if self.completer:
cr = self.cursorRect()
@ -106,24 +108,24 @@ class textEditCompleter(textEditView):
cr.setWidth(self.completer.sizeHint().width())
self.completer.setGeometry(cr)
self.completer.popup(self.textUnderCursor(select=True))
def mouseMoveEvent(self, event):
textEditView.mouseMoveEvent(self, event)
onRef = [r for r in self.refRects if r.contains(event.pos())]
if not onRef:
qApp.restoreOverrideCursor()
QToolTip.hideText()
return
cursor = self.cursorForPosition(event.pos())
ref = self.refUnderCursor(cursor)
if ref:
if not qApp.overrideCursor():
qApp.setOverrideCursor(Qt.PointingHandCursor)
QToolTip.showText(self.mapToGlobal(event.pos()), Ref.tooltip(ref))
def mouseReleaseEvent(self, event):
textEditView.mouseReleaseEvent(self, event)
onRef = [r for r in self.refRects if r.contains(event.pos())]
@ -133,11 +135,11 @@ class textEditCompleter(textEditView):
if ref:
Ref.open(ref)
qApp.restoreOverrideCursor()
def resizeEvent(self, event):
textEditView.resizeEvent(self, event)
self.getRefRects()
def getRefRects(self):
cursor = self.textCursor()
f = self.font()
@ -151,12 +153,12 @@ class textEditCompleter(textEditView):
r.setWidth(fm.width(txt.group(0)))
refs.append(r)
self.refRects = refs
def paintEvent(self, event):
QTextEdit.paintEvent(self, event)
# Debug: paint rects
#painter = QPainter(self.viewport())
#painter.setPen(Qt.gray)
#for r in self.refRects:
#painter.drawRect(r)
# painter = QPainter(self.viewport())
# painter.setPen(Qt.gray)
# for r in self.refRects:
# painter.drawRect(r)

View file

@ -1,25 +1,31 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from ui.editors.t2tHighlighter import *
from ui.editors.t2tFunctions import *
from ui.editors.basicHighlighter import *
from ui.editors.textFormat import *
from models.outlineModel import *
from functions import *
import settings
# --!-- coding: utf8 --!--
import re
from PyQt5.QtCore import QTimer, QModelIndex, Qt, QEvent, pyqtSignal, QRegExp
from PyQt5.QtGui import QTextBlockFormat, QTextCharFormat, QFont, QColor, QMouseEvent, QTextCursor
from PyQt5.QtWidgets import QTextEdit, qApp, QAction, QMenu
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import AUC
from manuskript.functions import toString
from manuskript.models.outlineModel import outlineModel
from manuskript.ui.editors.basicHighlighter import basicHighlighter
from manuskript.ui.editors.t2tFunctions import t2tClearFormat
from manuskript.ui.editors.t2tFunctions import t2tFormatSelection
from manuskript.ui.editors.t2tHighlighter import t2tHighlighter
from manuskript.ui.editors.textFormat import textFormat
try:
import enchant
except ImportError:
enchant = None
class textEditView(QTextEdit):
def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="", autoResize=False):
def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="",
autoResize=False):
QTextEdit.__init__(self, parent)
self._column = Outline.text.value
self._index = None
@ -32,8 +38,8 @@ class textEditView(QTextEdit):
self._textFormat = "text"
self.setAcceptRichText(False)
# When setting up a theme, this becomes true.
self._fromTheme = False
self._fromTheme = False
self.spellcheck = spellcheck
self.currentDict = dict if dict else settings.dict
self.highlighter = None
@ -44,41 +50,40 @@ class textEditView(QTextEdit):
self.highligtCS = False
self.defaultFontPointSize = qApp.font().pointSize()
self._dict = None
#self.document().contentsChanged.connect(self.submit, AUC)
# self.document().contentsChanged.connect(self.submit, AUC)
# Submit text changed only after 500ms without modifications
self.updateTimer = QTimer()
self.updateTimer.setInterval(500)
self.updateTimer.setSingleShot(True)
self.updateTimer.timeout.connect(self.submit)
#self.updateTimer.timeout.connect(lambda: print("Timeout"))
# self.updateTimer.timeout.connect(lambda: print("Timeout"))
self.updateTimer.stop()
self.document().contentsChanged.connect(self.updateTimer.start, AUC)
#self.document().contentsChanged.connect(lambda: print("Document changed"))
#self.document().contentsChanged.connect(lambda: print(self.objectName(), "Contents changed"))
# self.document().contentsChanged.connect(lambda: print("Document changed"))
# self.document().contentsChanged.connect(lambda: print(self.objectName(), "Contents changed"))
self.setEnabled(False)
if index:
self.setCurrentModelIndex(index)
elif html:
self.document().setHtml(html)
self.setReadOnly(True)
# Spellchecking
if enchant and self.spellcheck:
self._dict = enchant.Dict(self.currentDict if self.currentDict else enchant.get_default_language())
else:
self.spellcheck = False
if self._highlighting and not self.highlighter:
self.highlighter = basicHighlighter(self)
self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat)
def setModel(self, model):
self._model = model
try:
@ -89,18 +94,18 @@ class textEditView(QTextEdit):
self._model.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved, AUC)
except TypeError:
pass
def setColumn(self, col):
self._column = col
def setHighlighting(self, val):
self._highlighting = val
def setDefaultBlockFormat(self, bf):
self._defaultBlockFormat = bf
if self.highlighter:
self.highlighter.setDefaultBlockFormat(bf)
def setCurrentModelIndex(self, index):
self._indexes = None
if index.isValid():
@ -108,9 +113,9 @@ class textEditView(QTextEdit):
if index.column() != self._column:
index = index.sibling(index.row(), self._column)
self._index = index
self.setPlaceholderText(self._placeholderText)
if not self._model:
self.setModel(index.model())
@ -123,32 +128,32 @@ class textEditView(QTextEdit):
self.setPlainText("")
self.setEnabled(False)
def setCurrentModelIndexes(self, indexes):
self._index = None
self._indexes = []
for i in indexes:
if i.isValid():
self.setEnabled(True)
if i.column() != self._column:
i = i.sibling(i.row(), self._column)
self._indexes.append(i)
if not self._model:
self.setModel(i.model())
self.updateText()
def setupEditorForIndex(self, index):
# what type of text are we editing?
if type(index.model()) != outlineModel:
self._textFormat = "text"
return
if self._column not in [Outline.text.value, Outline.notes.value]:
self._textFormat = "text"
else:
item = index.internalPointer()
if item.isHTML():
@ -157,13 +162,13 @@ class textEditView(QTextEdit):
self._textFormat = "t2t"
else:
self._textFormat = "text"
# Accept richtext maybe
if self._textFormat == "html":
self.setAcceptRichText(True)
else:
self.setAcceptRichText(False)
# Setting highlighter
if self._highlighting:
item = index.internalPointer()
@ -171,20 +176,20 @@ class textEditView(QTextEdit):
self.highlighter = basicHighlighter(self)
else:
self.highlighter = t2tHighlighter(self)
self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat)
def loadFontSettings(self):
if self._fromTheme or \
not self._index or \
type(self._index.model()) != outlineModel or \
self._column != Outline.text.value:
not self._index or \
type(self._index.model()) != outlineModel or \
self._column != Outline.text.value:
return
opt = settings.textEditor
f = QFont()
f.fromString(opt["font"])
#self.setFont(f)
# self.setFont(f)
self.setStyleSheet("""
background: {bg};
color: {foreground};
@ -195,52 +200,52 @@ class textEditView(QTextEdit):
foreground=opt["fontColor"],
ff=f.family(),
fs="{}pt".format(str(f.pointSize()))))
cf = QTextCharFormat()
#cf.setFont(f)
#cf.setForeground(QColor(opt["fontColor"]))
# cf.setFont(f)
# cf.setForeground(QColor(opt["fontColor"]))
bf = QTextBlockFormat()
bf.setLineHeight(opt["lineSpacing"], bf.ProportionalHeight)
bf.setTextIndent(opt["tabWidth"] * 1 if opt["indent"] else 0)
bf.setTopMargin(opt["spacingAbove"])
bf.setBottomMargin(opt["spacingBelow"])
self._defaultCharFormat = cf
self._defaultBlockFormat = bf
if self.highlighter:
self.highlighter.setMisspelledColor(QColor(opt["misspelled"]))
self.highlighter.setDefaultCharFormat(self._defaultCharFormat)
self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat)
def update(self, topLeft, bottomRight):
if self._updating:
return
elif self._index:
if topLeft.parent() != self._index.parent():
return
#print("Model changed: ({}:{}), ({}:{}/{}), ({}:{}) for {} of {}".format(
#topLeft.row(), topLeft.column(),
#self._index.row(), self._index.row(), self._column,
#bottomRight.row(), bottomRight.column(),
#self.objectName(), self.parent().objectName()))
# print("Model changed: ({}:{}), ({}:{}/{}), ({}:{}) for {} of {}".format(
# topLeft.row(), topLeft.column(),
# self._index.row(), self._index.row(), self._column,
# bottomRight.row(), bottomRight.column(),
# self.objectName(), self.parent().objectName()))
if topLeft.row() <= self._index.row() <= bottomRight.row():
if self._column == Outline.text.value and \
topLeft.column() <= Outline.type.value <= bottomRight.column():
topLeft.column() <= Outline.type.value <= bottomRight.column():
# If item type change, and we display the main text,
# we reset the index to set the proper
# highlighter and other defaults
self.setupEditorForIndex(self._index)
self.updateText()
elif topLeft.column() <= self._column <= bottomRight.column():
self.updateText()
elif self._indexes:
update = False
for i in self._indexes:
@ -248,43 +253,43 @@ class textEditView(QTextEdit):
update = True
if update:
self.updateText()
def rowsAboutToBeRemoved(self, parent, first, last):
if self._index:
if self._index.parent() == parent and \
first <= self._index.row() <= last:
first <= self._index.row() <= last:
self._index = None
self.setEnabled(False)
#FIXME: self._indexes
# FIXME: self._indexes
def disconnectDocument(self):
try:
self.document().contentsChanged.disconnect(self.updateTimer.start)
except:
pass
def reconnectDocument(self):
self.document().contentsChanged.connect(self.updateTimer.start, AUC)
def updateText(self):
if self._updating:
return
#print("Updating", self.objectName())
# print("Updating", self.objectName())
self._updating = True
if self._index:
self.disconnectDocument()
if self._textFormat == "html":
if self.toHtml() != toString(self._model.data(self._index)):
#print(" Updating html")
# print(" Updating html")
html = self._model.data(self._index)
self.document().setHtml(toString(html))
else:
if self.toPlainText() != toString(self._model.data(self._index)):
#print(" Updating plaintext")
# print(" Updating plaintext")
self.document().setPlainText(toString(self._model.data(self._index)))
self.reconnectDocument()
elif self._indexes:
self.disconnectDocument()
t = []
@ -292,35 +297,35 @@ class textEditView(QTextEdit):
for i in self._indexes:
item = i.internalPointer()
t.append(toString(item.data(self._column)))
for t2 in t[1:]:
if t2 != t[0]:
same = False
break
if same:
# Assuming that we don't use HTML with multiple items
self.document().setPlainText(t[0])
else:
self.document().setPlainText("")
if not self._placeholderText:
self._placeholderText = self.placeholderText()
self.setPlaceholderText(self.tr("Various"))
self.reconnectDocument()
self._updating = False
def submit(self):
self.updateTimer.stop()
if self._updating:
return
#print("Submitting", self.objectName())
# print("Submitting", self.objectName())
if self._index:
#item = self._index.internalPointer()
# item = self._index.internalPointer()
if self._textFormat == "html":
if self.toHtml() != self._model.data(self._index):
#print(" Submitting html")
# print(" Submitting html")
self._updating = True
html = self.toHtml()
# We don't store paragraph and font settings
@ -329,16 +334,16 @@ class textEditView(QTextEdit):
html = re.sub(r"margin-.*?;\s*", "", html)
html = re.sub(r"text-indent:.*?;\s*", "", html)
html = re.sub(r"line-height:.*?;\s*", "", html)
#print("Submitting:", html)
# print("Submitting:", html)
self._model.setData(self._index, html)
self._updating = False
else:
if self.toPlainText() != self._model.data(self._index):
#print(" Submitting plain text")
# print(" Submitting plain text")
self._updating = True
self._model.setData(self._index, self.toPlainText())
self._updating = False
elif self._indexes:
self._updating = True
for i in self._indexes:
@ -347,15 +352,15 @@ class textEditView(QTextEdit):
print("Submitting many indexes")
self._model.setData(i, self.toPlainText())
self._updating = False
def keyPressEvent(self, event):
QTextEdit.keyPressEvent(self, event)
if event.key() == Qt.Key_Space:
self.submit()
# -----------------------------------------------------------------------------------------------------
# Resize stuff
def resizeEvent(self, e):
QTextEdit.resizeEvent(self, e)
if self._autoResize:
@ -365,7 +370,7 @@ class textEditView(QTextEdit):
docHeight = self.document().size().height()
if self.heightMin <= docHeight <= self.heightMax:
self.setMinimumHeight(docHeight)
def setAutoResize(self, val):
self._autoResize = val
if self._autoResize:
@ -373,18 +378,18 @@ class textEditView(QTextEdit):
self.heightMin = 0
self.heightMax = 65000
self.sizeChange()
###############################################################################
# SPELLCHECKING
###############################################################################
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
###############################################################################
# SPELLCHECKING
###############################################################################
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
def setDict(self, d):
self.currentDict = d
self._dict = enchant.Dict(d)
if self.highlighter:
self.highlighter.rehighlight()
def toggleSpellcheck(self, v):
self.spellcheck = v
if enchant and self.spellcheck and not self._dict:
@ -399,34 +404,34 @@ class textEditView(QTextEdit):
# Rewrite the mouse event to a left button event so the cursor is
# moved to the location of the pointer.
event = QMouseEvent(QEvent.MouseButtonPress, event.pos(),
Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
QTextEdit.mousePressEvent(self, event)
class SpellAction(QAction):
"A special QAction that returns the text in a signal. Used for spellckech."
"""A special QAction that returns the text in a signal. Used for spellckech."""
correct = pyqtSignal(str)
def __init__(self, *args):
QAction.__init__(self, *args)
self.triggered.connect(lambda x: self.correct.emit(
str(self.text())))
str(self.text())))
def contextMenuEvent(self, event):
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
popup_menu = self.createStandardContextMenu()
popup_menu.exec_(event.globalPos())
def createStandardContextMenu(self):
popup_menu = QTextEdit.createStandardContextMenu(self)
if not self.spellcheck:
return popup_menu
# Select the word under the cursor.
cursor = self.textCursor()
#cursor = self.cursorForPosition(pos)
# cursor = self.cursorForPosition(pos)
cursor.select(QTextCursor.WordUnderCursor)
self.setTextCursor(cursor)
# Check if the selected word is misspelled and offer spelling
@ -446,97 +451,97 @@ class textEditView(QTextEdit):
popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
return popup_menu
def correctWord(self, word):
'''
"""
Replaces the selected text with word.
'''
"""
cursor = self.textCursor()
cursor.beginEditBlock()
cursor.removeSelectedText()
cursor.insertText(word)
cursor.endEditBlock()
###############################################################################
# FORMATTING
###############################################################################
###############################################################################
# FORMATTING
###############################################################################
def focusOutEvent(self, event):
"Submit changes just before focusing out."
"""Submit changes just before focusing out."""
QTextEdit.focusOutEvent(self, event)
self.submit()
def focusInEvent(self, event):
"Finds textFormatter and attach them to that view."
"""Finds textFormatter and attach them to that view."""
QTextEdit.focusInEvent(self, event)
p = self.parent()
while p.parent():
p = p.parent()
if self._index:
for tF in p.findChildren(textFormat, QRegExp(".*"), Qt.FindChildrenRecursively):
tF.updateFromIndex(self._index)
tF.setTextEdit(self)
def applyFormat(self, _format):
if self._textFormat == "html":
if _format == "Clear":
cursor = self.textCursor()
if _format == "Clear":
fmt = self._defaultCharFormat
cursor.setCharFormat(fmt)
bf = self._defaultBlockFormat
cursor.setBlockFormat(bf)
elif _format in ["Bold", "Italic", "Underline"]:
cursor = self.textCursor()
# If no selection, selects the word in which the cursor is now
if not cursor.hasSelection():
cursor.movePosition(QTextCursor.StartOfWord,
QTextCursor.MoveAnchor)
cursor.movePosition(QTextCursor.EndOfWord,
QTextCursor.KeepAnchor)
fmt = cursor.charFormat()
if _format == "Bold":
fmt.setFontWeight(QFont.Bold if fmt.fontWeight() != QFont.Bold else QFont.Normal)
elif _format == "Italic":
fmt.setFontItalic(not fmt.fontItalic())
elif _format == "Underline":
fmt.setFontUnderline(not fmt.fontUnderline())
fmt2 = self._defaultCharFormat
fmt2.setFontWeight(fmt.fontWeight())
fmt2.setFontItalic(fmt.fontItalic())
fmt2.setFontUnderline(fmt.fontUnderline())
cursor.mergeCharFormat(fmt2)
elif _format in ["Left", "Center", "Right", "Justify"]:
cursor = self.textCursor()
#bf = cursor.blockFormat()
# bf = cursor.blockFormat()
bf = QTextBlockFormat()
bf.setAlignment(
Qt.AlignLeft if _format == "Left" else
Qt.AlignHCenter if _format == "Center" else
Qt.AlignRight if _format == "Right" else
Qt.AlignJustify)
Qt.AlignLeft if _format == "Left" else
Qt.AlignHCenter if _format == "Center" else
Qt.AlignRight if _format == "Right" else
Qt.AlignJustify)
cursor.setBlockFormat(bf)
self.setTextCursor(cursor)
elif self._textFormat == "t2t":
if _format == "Bold":
t2tFormatSelection(self, 0)
@ -546,6 +551,3 @@ class textEditView(QTextEdit):
t2tFormatSelection(self, 2)
elif _format == "Clear":
t2tClearFormat(self)

View file

@ -1,52 +1,58 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QColor, QPalette, QIcon, QFont, QFontMetrics
from PyQt5.QtWidgets import QStyledItemDelegate, qApp, QStyleOptionViewItem, QStyle
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import mixColors, colorifyPixmap
from manuskript.functions import outlineItemColors
from manuskript.functions import toFloat
from qt import *
from enums import *
from functions import *
import settings
class treeTitleDelegate(QStyledItemDelegate):
"""The main purpose of ``treeTitleDelegate`` is to paint outline items
in the treeview with propers colors according to settings.
"""
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
self._view = None
def setView(self, view):
self._view = view
def paint(self, painter, option, index):
item = index.internalPointer()
colors = outlineItemColors(item)
style = qApp.style()
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, index)
iconRect = style.subElementRect(style.SE_ItemViewItemDecoration, opt)
textRect = style.subElementRect(style.SE_ItemViewItemText, opt)
# Background
style.drawPrimitive(style.PE_PanelItemViewItem, opt, painter)
if settings.viewSettings["Tree"]["Background"] != "Nothing" and not opt.state & QStyle.State_Selected:
col = colors[settings.viewSettings["Tree"]["Background"]]
if col != QColor(Qt.transparent):
col2 = QColor(Qt.white)
if opt.state & QStyle.State_Selected:
col2 = opt.palette.brush(QPalette.Normal, QPalette.Highlight).color()
col = mixColors(col, col2, .2)
painter.save()
painter.setBrush(col)
painter.setPen(Qt.NoPen)
rect = opt.rect
if self._view:
r2 = self._view.visualRect(index)
@ -54,10 +60,10 @@ class treeTitleDelegate(QStyledItemDelegate):
rect.setLeft(r2.left())
rect.setTop(r2.top())
rect.setBottom(r2.bottom())
painter.drawRoundedRect(rect, 5, 5)
painter.restore()
# Icon
mode = QIcon.Normal
if not opt.state & QStyle.State_Enabled:
@ -71,7 +77,7 @@ class treeTitleDelegate(QStyledItemDelegate):
colorifyPixmap(icon, color)
opt.icon = QIcon(icon)
opt.icon.paint(painter, iconRect, opt.decorationAlignment, mode, state)
# Text
if opt.text:
painter.save()
@ -85,7 +91,7 @@ class treeTitleDelegate(QStyledItemDelegate):
fm = QFontMetrics(f)
elidedText = fm.elidedText(opt.text, Qt.ElideRight, textRect.width())
painter.drawText(textRect, Qt.AlignLeft, elidedText)
extraText = ""
if item.isFolder() and settings.viewSettings["Tree"]["InfoFolder"] != "Nothing":
if settings.viewSettings["Tree"]["InfoFolder"] == "Count":
@ -98,7 +104,7 @@ class treeTitleDelegate(QStyledItemDelegate):
extraText = int(toFloat(item.data(Outline.goalPercentage.value)) * 100)
if extraText:
extraText = " ({}%)".format(extraText)
if item.isText() and settings.viewSettings["Tree"]["InfoText"] != "Nothing":
if settings.viewSettings["Tree"]["InfoText"] == "WC":
extraText = item.data(Outline.wordCount.value)
@ -106,19 +112,17 @@ class treeTitleDelegate(QStyledItemDelegate):
elif settings.viewSettings["Tree"]["InfoText"] == "Progress":
extraText = int(toFloat(item.data(Outline.goalPercentage.value)) * 100)
if extraText:
extraText = " ({}%)".format(extraText)
extraText = " ({}%)".format(extraText)
if extraText:
r = QRect(textRect)
r.setLeft(r.left() + fm.width(opt.text + " "))
painter.save()
painter.setPen(Qt.darkGray)
painter.drawText(r, Qt.AlignLeft | Qt.AlignBottom, extraText)
painter.restore()
painter.restore()
#QStyledItemDelegate.paint(self, painter, option, index)
# QStyledItemDelegate.paint(self, painter, option, index)

View file

@ -1,117 +1,116 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QTreeView, QAction
from manuskript.enums import Outline
from manuskript.functions import mainWindow
from manuskript.ui.views.dndView import dndView
from manuskript.ui.views.outlineBasics import outlineBasics
from manuskript.ui.views.treeDelegates import treeTitleDelegate
from qt import *
from enums import *
from functions import *
from ui.views.dndView import *
from ui.views.outlineBasics import *
from ui.views.treeDelegates import *
class treeView(QTreeView, dndView, outlineBasics):
def __init__(self, parent=None):
QTreeView.__init__(self, parent)
dndView.__init__(self, parent)
outlineBasics.__init__(self, parent)
self._indexesToOpen = None
def setModel(self, model):
QTreeView.setModel(self, model)
# Hiding columns
for c in range(1, self.model().columnCount()):
self.hideColumn(c)
# Setting delegate
self.titleDelegate = treeTitleDelegate()
self.setItemDelegateForColumn(Outline.title.value, self.titleDelegate)
def makePopupMenu(self):
menu = outlineBasics.makePopupMenu(self)
first = menu.actions()[0]
# Open item in new tab
sel = self.selectedIndexes()
pos = self.viewport().mapFromGlobal(QCursor.pos())
mouseIndex = self.indexAt(pos)
if mouseIndex.isValid():
mouseTitle = mouseIndex.internalPointer().title()
else:
mouseTitle = self.tr("Root")
if mouseIndex in sel and len(sel) > 1:
actionTitle = self.tr("Open {} items in new tabs").format(len(sel))
self._indexesToOpen = sel
else:
actionTitle = self.tr("Open {} in a new tab").format(mouseTitle)
self._indexesToOpen = [mouseIndex]
self.actNewTab = QAction(actionTitle, menu)
self.actNewTab.triggered.connect(self.openNewTab)
menu.insertAction(first, self.actNewTab)
menu.insertSeparator(first)
# Expand /collapse item
if mouseIndex.isValid():
#index = self.currentIndex()
# index = self.currentIndex()
item = mouseIndex.internalPointer()
self.actExpand = QAction(self.tr("Expand {}").format(item.title()), menu)
self.actExpand.triggered.connect(self.expandCurrentIndex)
menu.insertAction(first, self.actExpand)
self.actCollapse = QAction(self.tr("Collapse {}").format(item.title()), menu)
self.actCollapse.triggered.connect(self.collapseCurrentIndex)
menu.insertAction(first, self.actCollapse)
menu.insertSeparator(first)
# Expand /collapse all
self.actExpandAll = QAction(self.tr("Expand All"), menu)
self.actExpandAll.triggered.connect(self.expandAll)
menu.insertAction(first, self.actExpandAll)
self.actCollapseAll = QAction(self.tr("Collapse All"), menu)
self.actCollapseAll.triggered.connect(self.collapseAll)
menu.insertAction(first, self.actCollapseAll)
menu.insertSeparator(first)
return menu
def openNewTab(self):
mainWindow().mainEditor.openIndexes(self._indexesToOpen, newTab=True)
def expandCurrentIndex(self, index=None):
if index is None or type(index) == bool:
index = self._indexesToOpen[0] #self.currentIndex()
index = self._indexesToOpen[0] # self.currentIndex()
self.expand(index)
for i in range(self.model().rowCount(index)):
idx = self.model().index(i, 0, index)
self.expandCurrentIndex(index=idx)
self.expandCurrentIndex(index=idx)
def collapseCurrentIndex(self, index=None):
if index is None or type(index) == bool:
index = self._indexesToOpen[0] #self.currentIndex()
index = self._indexesToOpen[0] # self.currentIndex()
self.collapse(index)
for i in range(self.model().rowCount(index)):
idx = self.model().index(i, 0, index)
self.collapseCurrentIndex(index=idx)
def dragMoveEvent(self, event):
dndView.dragMoveEvent(self, event)
QTreeView.dragMoveEvent(self, event)
def mousePressEvent(self, event):
if event.button() == Qt.RightButton:
# Capture mouse press so that selection doesn't change
# on right click
pass
else:
QTreeView.mousePressEvent(self, event)
QTreeView.mousePressEvent(self, event)

View file

@ -1,16 +1,22 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from functions import *
from ui.welcome_ui import *
from models.outlineModel import *
from models.persosModel import *
from models.plotModel import *
#from models.persosProxyModel import *
import settings
# --!-- coding: utf8 --!--
import locale
import imp
import os
from PyQt5.QtCore import QSettings, QRegExp, Qt
from PyQt5.QtGui import QIcon, QBrush, QColor, QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QWidget, QAction, QFileDialog, QSpinBox, QLineEdit, QLabel, QPushButton, QTreeWidgetItem
from manuskript import settings
from manuskript.enums import Outline
from manuskript.functions import mainWindow, iconFromColor
from manuskript.models.outlineModel import outlineItem
from manuskript.models.outlineModel import outlineModel
from manuskript.models.persosModel import persosModel
from manuskript.models.plotModel import plotModel
from manuskript.ui.welcome_ui import Ui_welcome
locale.setlocale(locale.LC_ALL, '')
@ -19,9 +25,9 @@ class welcome(QWidget, Ui_welcome):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.template = []
self.mw = mainWindow()
self.btnOpen.clicked.connect(self.openFile)
self.btnCreate.clicked.connect(self.createFile)
@ -29,31 +35,31 @@ class welcome(QWidget, Ui_welcome):
self.tree.itemActivated.connect(self.changeTemplate)
self.btnAddLevel.clicked.connect(self.templateAddLevel)
self.btnAddWC.clicked.connect(self.templateAddWordCount)
self.populateTemplates()
def updateValues(self):
# Auto load
autoLoad, last = self.getAutoLoadValues()
self.chkLoadLastProject.setChecked(autoLoad)
# Recent Files
self.loadRecents()
###############################################################################
# AUTOLOAD
###############################################################################
###############################################################################
# AUTOLOAD
###############################################################################
def showEvent(self, event):
"""Waiting for things to be fully loaded to start opening projects."""
QWidget.showEvent(self, event)
# Auto load last project
autoLoad, last = self.getAutoLoadValues()
if autoLoad and last:
self.mw.loadProject(last)
def getAutoLoadValues(self):
sttgns = QSettings()
if sttgns.contains("autoLoad"):
@ -64,16 +70,16 @@ class welcome(QWidget, Ui_welcome):
last = sttgns.value("lastProject")
else:
last = ""
return autoLoad, last
def setAutoLoad(self, v):
QSettings().setValue("autoLoad", v)
###############################################################################
# RECENTS
###############################################################################
###############################################################################
# RECENTS
###############################################################################
def loadRecents(self):
sttgns = QSettings()
self.mw.menuRecents.setIcon(QIcon.fromTheme("folder-recent"))
@ -87,16 +93,16 @@ class welcome(QWidget, Ui_welcome):
a.setStatusTip(f)
a.triggered.connect(self.loadRecentFile)
self.mw.menuRecents.addAction(a)
self.btnRecent.setMenu(self.mw.menuRecents)
def appendToRecentFiles(self, project):
sttgns = QSettings()
if sttgns.contains("recentFiles"):
recentFiles = sttgns.value("recentFiles")
else:
recentFiles = []
while project in recentFiles:
recentFiles.remove(project)
recentFiles.insert(0, project)
@ -108,92 +114,92 @@ class welcome(QWidget, Ui_welcome):
self.appendToRecentFiles(act.data())
self.mw.loadProject(act.data())
###############################################################################
# DIALOGS
###############################################################################
###############################################################################
# DIALOGS
###############################################################################
def openFile(self):
"""File dialog that request an existing file. For opening project."""
filename = QFileDialog.getOpenFileName(self,
self.tr("Open project"),
".",
self.tr("Manuskript project (*.msk)"))[0]
filename = QFileDialog.getOpenFileName(self,
self.tr("Open project"),
".",
self.tr("Manuskript project (*.msk)"))[0]
if filename:
self.appendToRecentFiles(filename)
self.mw.loadProject(filename)
def saveAsFile(self):
"""File dialog that request a file, existing or not.
Save datas to that file, which then becomes the current project."""
filename = QFileDialog.getSaveFileName(self,
self.tr("Save project as..."),
".",
self.tr("Manuskript project (*.msk)"))[0]
filename = QFileDialog.getSaveFileName(self,
self.tr("Save project as..."),
".",
self.tr("Manuskript project (*.msk)"))[0]
if filename:
self.appendToRecentFiles(filename)
self.mw.saveDatas(filename)
def createFile(self):
"""When starting a new project, ask for a place to save it.
Datas are not loaded from file, so they must be populated another way."""
filename = QFileDialog.getSaveFileName(self,
self.tr("Create New Project"),
".",
self.tr("Manuskript project (*.msk)"))[0]
filename = QFileDialog.getSaveFileName(self,
self.tr("Create New Project"),
".",
self.tr("Manuskript project (*.msk)"))[0]
if filename:
self.appendToRecentFiles(filename)
self.loadDefaultDatas()
self.mw.loadProject(filename, loadFromFile=False)
###############################################################################
# TEMPLATES
###############################################################################
###############################################################################
# TEMPLATES
###############################################################################
def templates(self):
return [
(self.tr("Empty"), []),
(self.tr("Novel"), [
( 20, self.tr("Chapter")),
( 5, self.tr("Scene")),
( 500, None) # A line with None is word count
]),
(20, self.tr("Chapter")),
(5, self.tr("Scene")),
(500, None) # A line with None is word count
]),
(self.tr("Novella"), [
( 10, self.tr("Chapter")),
( 5, self.tr("Scene")),
( 500, None)
]),
(10, self.tr("Chapter")),
(5, self.tr("Scene")),
(500, None)
]),
(self.tr("Short Story"), [
( 10, self.tr("Scene")),
(10, self.tr("Scene")),
(1000, None)
]),
]),
(self.tr("Trilogy"), [
( 3, self.tr("Book")),
( 3, self.tr("Section")),
( 10, self.tr("Chapter")),
( 5, self.tr("Scene")),
( 500, None)
]),
(3, self.tr("Book")),
(3, self.tr("Section")),
(10, self.tr("Chapter")),
(5, self.tr("Scene")),
(500, None)
]),
(self.tr("Research paper"), [
( 3, self.tr("Section")),
(3, self.tr("Section")),
(1000, None)
])
]
])
]
def defaultTextType(self):
return [
("t2t", self.tr("Txt2Tags"), "text-x-generic"),
("html", self.tr("Rich Text (html)"), "text-html"),
("txt", self.tr("Plain Text"), "text-x-generic"),
]
]
def changeTemplate(self, item, column):
template = [i for i in self.templates() if i[0] == item.text(0)]
if len(template):
self.template = template[0][1]
self.updateTemplate()
def updateTemplate(self):
# Clear layout
def clearLayout(l):
@ -203,13 +209,13 @@ class welcome(QWidget, Ui_welcome):
i.widget().deleteLater()
if i.layout():
clearLayout(i.layout())
clearLayout(self.lytTemplate)
#self.templateLayout.addStretch()
#l = QGridLayout()
#self.templateLayout.addLayout(l)
# self.templateLayout.addStretch()
# l = QGridLayout()
# self.templateLayout.addLayout(l)
k = 0
hasWC = False
for d in self.template:
@ -217,70 +223,69 @@ class welcome(QWidget, Ui_welcome):
spin.setRange(0, 999999)
spin.setValue(d[0])
spin.valueChanged.connect(self.updateWordCount)
if d[1] != None:
txt = QLineEdit(self)
txt.setText(d[1])
else:
hasWC = True
txt = QLabel(self.tr("words each."), self)
if k != 0:
of = QLabel(self.tr("of"), self)
self.lytTemplate.addWidget(of, k, 0)
btn = QPushButton("", self)
btn.setIcon(QIcon.fromTheme("edit-delete"))
btn.setProperty("deleteRow", k)
btn.clicked.connect(self.deleteTemplateRow)
self.lytTemplate.addWidget(btn, k, 3)
self.lytTemplate.addWidget(spin, k, 1)
self.lytTemplate.addWidget(txt, k, 2)
k += 1
self.btnAddWC.setEnabled(not hasWC and len(self.template) > 0)
self.btnAddLevel.setEnabled(True)
self.lblTotal.setVisible(hasWC)
self.updateWordCount()
def templateAddLevel(self):
if len(self.template) > 0 and \
self.template[len(self.template) - 1][1] == None:
self.template[len(self.template) - 1][1] == None:
# has word cound, so insert before
self.template.insert(len(self.template) - 1, (10, self.tr("Text")))
else:
# No word count, so insert at end
self.template.append((10, self.tr("Something")))
self.updateTemplate()
def templateAddWordCount(self):
self.template.append((500, None))
self.updateTemplate()
def deleteTemplateRow(self):
btn = self.sender()
row = btn.property("deleteRow")
self.template.pop(row)
self.updateTemplate()
def updateWordCount(self):
total = 1
for s in self.findChildren(QSpinBox, QRegExp(".*"),
Qt.FindChildrenRecursively):
total = total * s.value()
if total == 1:
if total == 1:
total = 0
self.lblTotal.setText(self.tr("<b>Total:</b> {} words (~ {} pages)").format(
locale.format("%d", total, grouping=True),
locale.format("%d", total / 250, grouping=True)
locale.format("%d", total, grouping=True),
locale.format("%d", total / 250, grouping=True)
))
def addTopLevelItem(self, name):
item = QTreeWidgetItem(self.tree, [name])
item.setBackground(0, QBrush(QColor(Qt.blue).lighter(190)))
@ -291,45 +296,45 @@ class welcome(QWidget, Ui_welcome):
f.setBold(True)
item.setFont(0, f)
return item
def populateTemplates(self):
self.tree.clear()
self.tree.setIndentation(0)
# Add templates
item = self.addTopLevelItem(self.tr("Templates"))
templates = self.templates()
for t in templates:
sub = QTreeWidgetItem(item, [t[0]])
# Add Demo project
item = self.addTopLevelItem(self.tr("Demo projects"))
# FIXME: none yet
# Populates default text type
self.cmbDefaultType.clear()
for t in self.defaultTextType():
self.cmbDefaultType.addItem(QIcon.fromTheme(t[2]), t[1], t[0])
self.tree.expandAll()
def loadDefaultDatas(self):
# Empty settings
imp.reload(settings)
# Données
self.mw.mdlFlatData = QStandardItemModel(2, 8, self.mw)
# Persos
#self.mw.mdlPersos = QStandardItemModel(0, 0, self.mw)
# self.mw.mdlPersos = QStandardItemModel(0, 0, self.mw)
self.mw.mdlPersos = persosModel(self.mw)
#self.mdlPersosProxy = None # persosProxyModel() # None
#self.mw.mdlPersosProxy = persosProxyModel(self.mw)
# self.mdlPersosProxy = None # persosProxyModel() # None
# self.mw.mdlPersosProxy = persosProxyModel(self.mw)
#self.mw.mdlPersosInfos = QStandardItemModel(1, 0, self.mw)
#self.mw.mdlPersosInfos.insertColumn(0, [QStandardItem("ID")])
#self.mw.mdlPersosInfos.setHorizontalHeaderLabels(["Description"])
# self.mw.mdlPersosInfos = QStandardItemModel(1, 0, self.mw)
# self.mw.mdlPersosInfos.insertColumn(0, [QStandardItem("ID")])
# self.mw.mdlPersosInfos.setHorizontalHeaderLabels(["Description"])
# Labels
self.mw.mdlLabels = QStandardItemModel(self.mw)
@ -340,18 +345,18 @@ class welcome(QWidget, Ui_welcome):
(Qt.blue, self.tr("Chapter")),
(Qt.red, self.tr("Scene")),
(Qt.cyan, self.tr("Research"))
]:
]:
self.mw.mdlLabels.appendRow(QStandardItem(iconFromColor(color), text))
# Status
self.mw.mdlStatus = QStandardItemModel(self.mw)
for text in [
"",
self.tr("TODO"),
self.tr("First draft"),
self.tr("Second draft"),
self.tr("Final")
]:
"",
self.tr("TODO"),
self.tr("First draft"),
self.tr("Second draft"),
self.tr("Final")
]:
self.mw.mdlStatus.appendRow(QStandardItem(text))
# Plot
@ -359,38 +364,37 @@ class welcome(QWidget, Ui_welcome):
# Outline
self.mw.mdlOutline = outlineModel(self.mw)
root = self.mw.mdlOutline.rootItem
_type = self.cmbDefaultType.currentData()
settings.defaultTextType = _type
def addElement(parent, datas):
if len(datas) == 2 and datas[1][1] == None or \
len(datas) == 1:
len(datas) == 1:
# Next item is word count
n = 0
for i in range(datas[0][0]):
for i in range(datas[0][0]):
n += 1
item = outlineItem(title="{} {}".format(
datas[0][1],
str(n)),
_type=_type,
parent=parent)
datas[0][1],
str(n)),
_type=_type,
parent=parent)
if len(datas) == 2:
item.setData(Outline.setGoal.value, datas[1][0])
#parent.appendChild(item)
# parent.appendChild(item)
else:
n = 0
for i in range(datas[0][0]):
n += 1
item = outlineItem(title="{} {}".format(
datas[0][1],
str(n)),
_type="folder",
parent=parent)
#parent.appendChild(item)
datas[0][1],
str(n)),
_type="folder",
parent=parent)
# parent.appendChild(item)
addElement(item, datas[1:])
if self.template:
addElement(root, self.template)