mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-21 05:12:27 +12:00
Releasing manuskript 0.3.0
This commit is contained in:
commit
d67f743ba0
|
@ -23,3 +23,4 @@ ratings:
|
|||
- "**.rb"
|
||||
exclude_paths:
|
||||
- libs/**/*
|
||||
- **/*_ui.py
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,4 +10,5 @@ ExportTest
|
|||
icons/Numix
|
||||
.idea
|
||||
dist
|
||||
build
|
||||
build
|
||||
test-projects
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
[Manuskript](http://www.theologeek.ch/manuskript) is an open-source tool for writers.
|
||||
|
||||
![Main view](http://www.theologeek.ch/manuskript/wp-content/uploads/2016/02/index-cards-1.jpg)
|
||||
![Main view](http://www.theologeek.ch/manuskript/wp-content/uploads/2016/03/manuskript-0.3.0.jpg)
|
||||
|
||||
|
||||
## [Download](http://www.theologeek.ch/manuskript/download)
|
||||
|
||||
## Running from sources
|
||||
|
||||
To run the application without installing just:
|
||||
|
@ -23,4 +25,4 @@ Be sure to have all **dependencies** installed !
|
|||
|
||||
Optional:
|
||||
- pyenchant
|
||||
- zlib
|
||||
- zlib
|
||||
|
|
|
@ -1,58 +1,64 @@
|
|||
FORMS += ../manuskript/ui/mainWindow.ui
|
||||
FORMS += ../manuskript/ui/settings_ui.ui
|
||||
FORMS += ../manuskript/ui/welcome_ui.ui
|
||||
FORMS += ../manuskript/ui/sldImportance_ui.ui
|
||||
FORMS += ../manuskript/ui/cheatSheet_ui.ui
|
||||
FORMS += ../manuskript/ui/compileDialog_ui.ui
|
||||
FORMS += ../manuskript/ui/revisions_ui.ui
|
||||
FORMS += ../manuskript/ui/mainWindow.ui
|
||||
FORMS += ../manuskript/ui/compileDialog_ui.ui
|
||||
FORMS += ../manuskript/ui/search_ui.ui
|
||||
FORMS += ../manuskript/ui/tools/frequency_ui.ui
|
||||
FORMS += ../manuskript/ui/welcome_ui.ui
|
||||
FORMS += ../manuskript/ui/cheatSheet_ui.ui
|
||||
FORMS += ../manuskript/ui/settings_ui.ui
|
||||
|
||||
FORMS += ../manuskript/ui/editors/editorWidget_ui.ui
|
||||
FORMS += ../manuskript/ui/editors/textFormat_ui.ui
|
||||
FORMS += ../manuskript/ui/editors/locker_ui.ui
|
||||
FORMS += ../manuskript/ui/editors/completer_ui.ui
|
||||
FORMS += ../manuskript/ui/editors/mainEditor_ui.ui
|
||||
|
||||
FORMS += ../manuskript/ui/views/propertiesView_ui.ui
|
||||
FORMS += ../manuskript/ui/views/basicItemView_ui.ui
|
||||
FORMS += ../manuskript/ui/views/metadataView_ui.ui
|
||||
FORMS += ../manuskript/ui/views/basicItemView_ui.ui
|
||||
FORMS += ../manuskript/ui/views/sldImportance_ui.ui
|
||||
FORMS += ../manuskript/ui/views/storylineView_ui.ui
|
||||
|
||||
|
||||
SOURCES += ../manuskript/exporter/__init__.py
|
||||
SOURCES += ../manuskript/load_save/version_0.py
|
||||
SOURCES += ../manuskript/main.py
|
||||
SOURCES += ../manuskript/loadSave.py
|
||||
SOURCES += ../manuskript/mainWindow.py
|
||||
SOURCES += ../manuskript/settingsWindow.py
|
||||
|
||||
SOURCES += ../manuskript/models/characterModel.py
|
||||
SOURCES += ../manuskript/models/outlineModel.py
|
||||
SOURCES += ../manuskript/models/persosProxyModel.py
|
||||
SOURCES += ../manuskript/models/plotModel.py
|
||||
SOURCES += ../manuskript/models/worldModel.py
|
||||
SOURCES += ../manuskript/models/persosModel.py
|
||||
SOURCES += ../manuskript/models/plotsProxyModel.py
|
||||
SOURCES += ../manuskript/models/references.py
|
||||
|
||||
SOURCES += ../manuskript/exporter/__init__.py
|
||||
|
||||
SOURCES += ../manuskript/ui/helpLabel.py
|
||||
SOURCES += ../manuskript/ui/sldImportance.py
|
||||
SOURCES += ../manuskript/ui/welcome.py
|
||||
SOURCES += ../manuskript/models/worldModel.py
|
||||
SOURCES += ../manuskript/settingsWindow.py
|
||||
SOURCES += ../manuskript/ui/cheatSheet.py
|
||||
SOURCES += ../manuskript/ui/compileDialog.py
|
||||
SOURCES += ../manuskript/ui/revisions.py
|
||||
SOURCES += ../manuskript/ui/collapsibleDockWidgets.py
|
||||
|
||||
SOURCES += ../manuskript/ui/editors/editorWidget.py
|
||||
SOURCES += ../manuskript/ui/compileDialog.py
|
||||
SOURCES += ../manuskript/ui/editors/fullScreenEditor.py
|
||||
SOURCES += ../manuskript/ui/editors/locker.py
|
||||
SOURCES += ../manuskript/ui/editors/textFormat.py
|
||||
SOURCES += ../manuskript/ui/editors/completer.py
|
||||
SOURCES += ../manuskript/ui/editors/mainEditor.py
|
||||
|
||||
SOURCES += ../manuskript/ui/views/corkDelegate.py
|
||||
SOURCES += ../manuskript/ui/views/outlineDelegates.py
|
||||
SOURCES += ../manuskript/ui/views/outlineBasics.py
|
||||
SOURCES += ../manuskript/ui/editors/textFormat.py
|
||||
SOURCES += ../manuskript/ui/helpLabel.py
|
||||
SOURCES += ../manuskript/ui/revisions.py
|
||||
SOURCES += ../manuskript/ui/search.py
|
||||
SOURCES += ../manuskript/ui/tools/frequencyAnalyzer.py
|
||||
SOURCES += ../manuskript/ui/views/characterTreeView.py
|
||||
SOURCES += ../manuskript/ui/views/cmbOutlineCharacterChoser.py
|
||||
SOURCES += ../manuskript/ui/views/cmbOutlineLabelChoser.py
|
||||
SOURCES += ../manuskript/ui/views/cmbOutlinePersoChoser.py
|
||||
SOURCES += ../manuskript/ui/views/cmbOutlineStatusChoser.py
|
||||
SOURCES += ../manuskript/ui/views/treeView.py
|
||||
SOURCES += ../manuskript/ui/views/corkDelegate.py
|
||||
SOURCES += ../manuskript/ui/views/lineEditView.py
|
||||
SOURCES += ../manuskript/ui/views/textEditView.py
|
||||
SOURCES += ../manuskript/ui/views/plotTreeView.py
|
||||
SOURCES += ../manuskript/ui/views/outlineBasics.py
|
||||
SOURCES += ../manuskript/ui/views/outlineDelegates.py
|
||||
SOURCES += ../manuskript/ui/views/plotDelegate.py
|
||||
SOURCES += ../manuskript/ui/views/plotTreeView.py
|
||||
SOURCES += ../manuskript/ui/views/sldImportance.py
|
||||
SOURCES += ../manuskript/ui/views/storylineView.py
|
||||
SOURCES += ../manuskript/ui/views/textEditCompleter.py
|
||||
SOURCES += ../manuskript/ui/views/textEditView.py
|
||||
SOURCES += ../manuskript/ui/views/treeView.py
|
||||
SOURCES += ../manuskript/ui/welcome.py
|
||||
|
||||
TRANSLATIONS += manuskript_fr.ts
|
||||
|
||||
TRANSLATIONS += manuskript_es.ts
|
||||
|
|
BIN
i18n/manuskript_es.qm
Normal file
BIN
i18n/manuskript_es.qm
Normal file
Binary file not shown.
3110
i18n/manuskript_es.ts
Normal file
3110
i18n/manuskript_es.ts
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
17
i18n/tool.txt
Normal file
17
i18n/tool.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
List all forms:
|
||||
|
||||
find .. -iname *.ui
|
||||
|
||||
List all files containing ".tr":
|
||||
|
||||
grep -rin "\.tr(" ../manuskript > list.txt
|
||||
|
||||
List all files containing ".translate":
|
||||
|
||||
grep -rin "\.translate(" ../manuskript >> list.txt
|
||||
|
||||
Then clean list.txt, and copy it in LibreOffice Calc, then:
|
||||
- Data, Filter, Advanced
|
||||
- From: whole column
|
||||
- No duplication
|
||||
- → filter
|
4
makefile
4
makefile
|
@ -10,13 +10,13 @@ run: $(UIs)
|
|||
bin/manuskript
|
||||
|
||||
debug: $(UIs)
|
||||
gdb --args python3 manuskript/main.py
|
||||
gdb --args python3 bin/manuskript
|
||||
|
||||
lineprof:
|
||||
kernprof -l -v manuskript/main.py
|
||||
|
||||
profile:
|
||||
python3 -m cProfile -s 'cumtime' manuskript/main.py | more
|
||||
python3 -m cProfile -s 'cumtime' bin/manuskript | more
|
||||
|
||||
compile:
|
||||
cd manuskript && python3 setup.py build_ext --inplace
|
||||
|
|
|
@ -4,7 +4,7 @@ block_cipher = None
|
|||
|
||||
|
||||
a = Analysis(['bin/manuskript'],
|
||||
pathex=['/home/olivier/Dropbox/Documents/Travail/Geekeries/Python/PyCharmProjects/manuskript_pyinstaller tests'],
|
||||
pathex=['.'],
|
||||
binaries=None,
|
||||
datas=[
|
||||
("icons", "icons"),
|
||||
|
@ -12,7 +12,7 @@ a = Analysis(['bin/manuskript'],
|
|||
("resources", "resources"),
|
||||
("sample-projects", "sample-projects"),
|
||||
],
|
||||
hiddenimports=[],
|
||||
hiddenimports=["xml.dom"],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
|
|
|
@ -9,7 +9,7 @@ from enum import Enum
|
|||
#def enum(**enums):
|
||||
#return type(str('Enum'), (), enums)
|
||||
|
||||
class Perso(Enum):
|
||||
class Character(Enum):
|
||||
name = 0
|
||||
ID = 1
|
||||
importance = 2
|
||||
|
@ -17,24 +17,22 @@ class Perso(Enum):
|
|||
goal = 4
|
||||
conflict = 5
|
||||
epiphany = 6
|
||||
summarySentance = 7
|
||||
summarySentence = 7
|
||||
summaryPara = 8
|
||||
summaryFull = 9
|
||||
notes = 10
|
||||
infoName = 11
|
||||
infoData = 12
|
||||
|
||||
class Plot(Enum):
|
||||
name = 0
|
||||
ID = 1
|
||||
importance = 2
|
||||
persos = 3
|
||||
characters = 3
|
||||
description = 4
|
||||
result = 5
|
||||
subplots = 6
|
||||
steps = 6
|
||||
summary = 7
|
||||
|
||||
class Subplot(Enum):
|
||||
class PlotStep(Enum):
|
||||
name = 0
|
||||
ID = 1
|
||||
meta = 2
|
||||
|
@ -51,7 +49,7 @@ class Outline(Enum):
|
|||
title = 0
|
||||
ID = 1
|
||||
type = 2
|
||||
summarySentance = 3
|
||||
summarySentence = 3
|
||||
summaryFull = 4
|
||||
POV = 5
|
||||
notes = 6
|
||||
|
@ -66,4 +64,3 @@ class Outline(Enum):
|
|||
# (sum of all sub-items' goals)
|
||||
textFormat = 15
|
||||
revisions = 16
|
||||
|
||||
|
|
|
@ -29,9 +29,7 @@ class arboExporter():
|
|||
writeItem(c, path2)
|
||||
|
||||
else:
|
||||
ext = ".t2t" if item.isT2T() else \
|
||||
".html" if item.isHTML() else \
|
||||
".txt"
|
||||
ext = ".md"
|
||||
path2 = os.path.join(path, item.title() + ext)
|
||||
f = open(path2, "w")
|
||||
text = self.formatText(item.text(), item.type())
|
||||
|
|
|
@ -2,43 +2,49 @@
|
|||
#--!-- coding: utf8 --!--
|
||||
|
||||
import os
|
||||
import re
|
||||
from random import *
|
||||
|
||||
from PyQt5.QtCore import Qt, QRect, QStandardPaths, QObject
|
||||
from PyQt5.QtCore import Qt, QRect, QStandardPaths, QObject, QRegExp
|
||||
|
||||
# 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 PyQt5.QtWidgets import qApp, QTextEdit
|
||||
|
||||
from manuskript.enums import Outline
|
||||
|
||||
AUC = Qt.AutoConnection | Qt.UniqueConnection
|
||||
MW = None
|
||||
|
||||
|
||||
def wordCount(text):
|
||||
return len(text.strip().replace(" ", "\n").split("\n")) if text else 0
|
||||
|
||||
|
||||
def toInt(text):
|
||||
if text:
|
||||
return int(text)
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
def toFloat(text):
|
||||
if text:
|
||||
return float(text)
|
||||
else:
|
||||
return 0.
|
||||
|
||||
|
||||
|
||||
def toString(text):
|
||||
if text in [None, "None"]:
|
||||
return ""
|
||||
else:
|
||||
return str(text)
|
||||
|
||||
|
||||
|
||||
def drawProgress(painter, rect, progress, radius=0):
|
||||
painter.setPen(Qt.NoPen)
|
||||
painter.setBrush(QColor("#dddddd"))
|
||||
|
@ -49,7 +55,8 @@ def drawProgress(painter, rect, progress, radius=0):
|
|||
r2 = QRect(rect)
|
||||
r2.setWidth(r2.width() * min(progress, 1))
|
||||
painter.drawRoundedRect(r2, radius, radius)
|
||||
|
||||
|
||||
|
||||
def colorFromProgress(progress):
|
||||
progress = toFloat(progress)
|
||||
c1 = QColor(Qt.red)
|
||||
|
@ -65,7 +72,8 @@ def colorFromProgress(progress):
|
|||
return c4
|
||||
else:
|
||||
return c3
|
||||
|
||||
|
||||
|
||||
def mainWindow():
|
||||
global MW
|
||||
if not MW:
|
||||
|
@ -77,6 +85,7 @@ def mainWindow():
|
|||
else:
|
||||
return MW
|
||||
|
||||
|
||||
def iconColor(icon):
|
||||
"""Returns a QRgb from a QIcon, assuming its all the same color"""
|
||||
px = icon.pixmap(5, 5)
|
||||
|
@ -85,14 +94,17 @@ def iconColor(icon):
|
|||
else:
|
||||
return QColor(Qt.transparent)
|
||||
|
||||
|
||||
def iconFromColor(color):
|
||||
px = QPixmap(32, 32)
|
||||
px.fill(color)
|
||||
return QIcon(px)
|
||||
|
||||
|
||||
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."""
|
||||
r = randint(0, 255)
|
||||
|
@ -106,6 +118,7 @@ def randomColor(mix=None):
|
|||
|
||||
return QColor(r, g, b)
|
||||
|
||||
|
||||
def mixColors(col1, col2, f=.5):
|
||||
f2 = 1-f
|
||||
r = col1.red() * f + col2.red() * f2
|
||||
|
@ -113,6 +126,7 @@ def mixColors(col1, col2, f=.5):
|
|||
b = col1.blue() * f + col2.blue() * f2
|
||||
return QColor(r, g, b)
|
||||
|
||||
|
||||
def outlineItemColors(item):
|
||||
"""Takes an OutlineItem and returns a dict of colors."""
|
||||
colors = {}
|
||||
|
@ -121,9 +135,9 @@ def outlineItemColors(item):
|
|||
# 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))
|
||||
for i in range(mw.mdlCharacter.rowCount()):
|
||||
if mw.mdlCharacter.ID(i) == POV:
|
||||
colors["POV"] = iconColor(mw.mdlCharacter.icon(i))
|
||||
|
||||
# Label
|
||||
lbl = item.data(Outline.label.value)
|
||||
|
@ -144,7 +158,8 @@ def outlineItemColors(item):
|
|||
colors["Compile"] = QColor(Qt.black)
|
||||
|
||||
return colors
|
||||
|
||||
|
||||
|
||||
def colorifyPixmap(pixmap, color):
|
||||
# FIXME: ugly
|
||||
p = QPainter(pixmap)
|
||||
|
@ -152,12 +167,14 @@ def colorifyPixmap(pixmap, color):
|
|||
p.fillRect(pixmap.rect(), color)
|
||||
return pixmap
|
||||
|
||||
|
||||
def appPath(suffix=None):
|
||||
p = os.path.realpath(os.path.join(os.path.split(__file__)[0], ".."))
|
||||
if suffix:
|
||||
p = os.path.join(p, suffix)
|
||||
return p
|
||||
|
||||
|
||||
def writablePath(suffix=None):
|
||||
if hasattr(QStandardPaths, "AppLocalDataLocation"):
|
||||
p = QStandardPaths.writableLocation(QStandardPaths.AppLocalDataLocation)
|
||||
|
@ -170,6 +187,7 @@ def writablePath(suffix=None):
|
|||
os.makedirs(p)
|
||||
return p
|
||||
|
||||
|
||||
def allPaths(suffix=None):
|
||||
paths = []
|
||||
# src directory
|
||||
|
@ -178,11 +196,54 @@ def allPaths(suffix=None):
|
|||
paths.append(writablePath(suffix))
|
||||
return paths
|
||||
|
||||
|
||||
def lightBlue():
|
||||
"""
|
||||
A light blue used in several places in manuskript.
|
||||
@return: QColor
|
||||
"""
|
||||
return QColor(Qt.blue).lighter(190)
|
||||
|
||||
|
||||
def totalObjects():
|
||||
return len(mainWindow().findChildren(QObject))
|
||||
|
||||
|
||||
def printObjects():
|
||||
print("Objects:", str(totalObjects()))
|
||||
print("Objects:", str(totalObjects()))
|
||||
|
||||
|
||||
def findWidgetsOfClass(cls):
|
||||
"""
|
||||
Returns all widgets, children of MainWindow, whose class is cls.
|
||||
@param cls: a class
|
||||
@return: list of QWidgets
|
||||
"""
|
||||
return mainWindow().findChildren(cls, QRegExp())
|
||||
|
||||
|
||||
def findBackground(filename):
|
||||
"""
|
||||
Returns the full path to a background file of name filename within ressource folders.
|
||||
"""
|
||||
return findFirstFile(re.escape(filename), "resources/backgrounds")
|
||||
|
||||
|
||||
def findFirstFile(regex, path="resources"):
|
||||
paths = allPaths(path)
|
||||
for p in paths:
|
||||
lst = os.listdir(p)
|
||||
for l in lst:
|
||||
if re.match(regex, l):
|
||||
return os.path.join(p, l)
|
||||
|
||||
|
||||
def HTML2PlainText(html):
|
||||
"""
|
||||
Ressource-inefficient way to convert HTML to plain text.
|
||||
@param html:
|
||||
@return:
|
||||
"""
|
||||
e = QTextEdit()
|
||||
e.setHtml(html)
|
||||
return e.toPlainText()
|
|
@ -1,149 +1,66 @@
|
|||
#!/usr/bin/env python
|
||||
#--!-- coding: utf8 --!--
|
||||
# --!-- coding: utf8 --!--
|
||||
|
||||
# The loadSave file calls the propper functions to load and save file
|
||||
# trying to detect the proper file format if it comes from an older version
|
||||
import os
|
||||
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
|
||||
import manuskript.load_save.version_0 as v0
|
||||
import manuskript.load_save.version_1 as v1
|
||||
|
||||
from manuskript.functions import iconColor, iconFromColorString
|
||||
|
||||
try:
|
||||
import zlib # Used with zipfile for compression
|
||||
compression = zipfile.ZIP_DEFLATED
|
||||
except:
|
||||
compression = zipfile.ZIP_STORED
|
||||
def saveProject(version=None):
|
||||
|
||||
def saveFilesToZip(files, zipname):
|
||||
"""Saves given files to zipname.
|
||||
files is actually a list of (content, filename)."""
|
||||
|
||||
zf = zipfile.ZipFile(zipname, mode="w")
|
||||
|
||||
for content, filename in files:
|
||||
zf.writestr(filename, content, compress_type=compression)
|
||||
|
||||
zf.close()
|
||||
|
||||
def loadFilesFromZip(zipname):
|
||||
"""Returns the content of zipfile as a dict of filename:content."""
|
||||
print(zipname)
|
||||
zf = zipfile.ZipFile(zipname)
|
||||
files = {}
|
||||
for f in zf.namelist():
|
||||
files[f] = zf.read(f)
|
||||
return files
|
||||
|
||||
def saveStandardItemModelXML(mdl, xml=None):
|
||||
"""Saves the given QStandardItemModel to XML.
|
||||
If xml (filename) is given, saves to xml. Otherwise returns as string."""
|
||||
|
||||
root = ET.Element("model")
|
||||
root.attrib["version"] = qApp.applicationVersion()
|
||||
|
||||
# Header
|
||||
header = ET.SubElement(root, "header")
|
||||
vHeader = ET.SubElement(header, "vertical")
|
||||
for x in range(mdl.rowCount()):
|
||||
vH = ET.SubElement(vHeader, "label")
|
||||
vH.attrib["row"] = str(x)
|
||||
vH.attrib["text"] = str(mdl.headerData(x, Qt.Vertical))
|
||||
|
||||
hHeader = ET.SubElement(header, "horizontal")
|
||||
for y in range(mdl.columnCount()):
|
||||
hH = ET.SubElement(hHeader, "label")
|
||||
hH.attrib["row"] = str(y)
|
||||
hH.attrib["text"] = str(mdl.headerData(y, Qt.Horizontal))
|
||||
|
||||
# Data
|
||||
data = ET.SubElement(root, "data")
|
||||
saveItem(data, mdl)
|
||||
|
||||
#print(qApp.tr("Saving to {}.").format(xml))
|
||||
if xml:
|
||||
ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
|
||||
# While debugging, we don't save the project
|
||||
# return
|
||||
|
||||
if version == 0:
|
||||
v0.saveProject()
|
||||
else:
|
||||
return ET.tostring(root, encoding="UTF-8", xml_declaration=True, pretty_print=True)
|
||||
|
||||
def saveItem(root, mdl, parent=QModelIndex()):
|
||||
for x in range(mdl.rowCount(parent)):
|
||||
row = ET.SubElement(root, "row")
|
||||
row.attrib["row"] = str(x)
|
||||
|
||||
for y in range(mdl.columnCount(parent)):
|
||||
col = ET.SubElement(row, "col")
|
||||
col.attrib["col"] = str(y)
|
||||
if mdl.data(mdl.index(x, y, parent), Qt.DecorationRole) != None:
|
||||
color = iconColor(mdl.data(mdl.index(x, y, parent), Qt.DecorationRole)).name(QColor.HexArgb)
|
||||
col.attrib["color"] = color if color != "#ff000000" else "#00000000"
|
||||
if mdl.data(mdl.index(x, y, parent)) != "":
|
||||
col.text = mdl.data(mdl.index(x, y, parent))
|
||||
if mdl.hasChildren(mdl.index(x, y, parent)):
|
||||
saveItem(col, mdl, mdl.index(x, y, parent))
|
||||
|
||||
def loadStandardItemModelXML(mdl, xml, fromString=False):
|
||||
"""Load data to a QStandardItemModel mdl from xml.
|
||||
By default xml is a filename. If fromString=True, xml is a string containg the data."""
|
||||
|
||||
#print(qApp.tr("Loading {}... ").format(xml), end="")
|
||||
|
||||
if not fromString:
|
||||
try:
|
||||
tree = ET.parse(xml)
|
||||
except:
|
||||
print("Failed.")
|
||||
return
|
||||
v1.saveProject()
|
||||
|
||||
|
||||
def clearSaveCache():
|
||||
v1.cache = {}
|
||||
|
||||
|
||||
def loadProject(project):
|
||||
|
||||
# Detect version
|
||||
isZip = False
|
||||
version = 0
|
||||
|
||||
# Is it a zip?
|
||||
try:
|
||||
zf = zipfile.ZipFile(project)
|
||||
isZip = True
|
||||
except zipfile.BadZipFile:
|
||||
isZip = False
|
||||
|
||||
# Does it have a VERSION in zip root?
|
||||
# Was used in transition between 0.2.0 and 0.3.0
|
||||
# So VERSION part can be deleted for manuskript 0.4.0
|
||||
if isZip and "VERSION" in zf.namelist():
|
||||
version = int(zf.read("VERSION"))
|
||||
|
||||
# Does it have a MANUSKRIPT in zip root?
|
||||
elif isZip and "MANUSKRIPT" in zf.namelist():
|
||||
version = int(zf.read("MANUSKRIPT"))
|
||||
|
||||
# Zip but no VERSION/MANUSKRIPT: oldest file format
|
||||
elif isZip:
|
||||
version = 0
|
||||
|
||||
# Not a zip
|
||||
else:
|
||||
root = ET.fromstring(xml)
|
||||
|
||||
#root = tree.getroot()
|
||||
|
||||
#Header
|
||||
hLabels = []
|
||||
vLabels = []
|
||||
for l in root.find("header").find("horizontal").findall("label"):
|
||||
hLabels.append(l.attrib["text"])
|
||||
for l in root.find("header").find("vertical").findall("label"):
|
||||
vLabels.append(l.attrib["text"])
|
||||
|
||||
#print(root.find("header").find("vertical").text)
|
||||
|
||||
#mdl.setVerticalHeaderLabels(vLabels)
|
||||
#mdl.setHorizontalHeaderLabels(hLabels)
|
||||
|
||||
# Populates with empty items
|
||||
for i in enumerate(vLabels):
|
||||
row = []
|
||||
for r in enumerate(hLabels):
|
||||
row.append(QStandardItem())
|
||||
mdl.appendRow(row)
|
||||
|
||||
#Data
|
||||
data = root.find("data")
|
||||
loadItem(data, mdl)
|
||||
|
||||
return True
|
||||
|
||||
def loadItem(root, mdl, parent=QModelIndex()):
|
||||
for row in root:
|
||||
r = int(row.attrib["row"])
|
||||
for col in row:
|
||||
c = int(col.attrib["col"])
|
||||
item = mdl.itemFromIndex(mdl.index(r, c, parent))
|
||||
if not item:
|
||||
item = QStandardItem()
|
||||
mdl.itemFromIndex(parent).setChild(r, c, item)
|
||||
|
||||
if col.text:
|
||||
#mdl.setData(mdl.index(r, c, parent), col.text)
|
||||
item.setText(col.text)
|
||||
|
||||
if "color" in col.attrib:
|
||||
#mdl.itemFromIndex(mdl.index(r, c, parent)).setIcon(iconFromColorString(col.attrib["color"]))
|
||||
item.setIcon(iconFromColorString(col.attrib["color"]))
|
||||
|
||||
if len(col) != 0:
|
||||
#loadItem(col, mdl, mdl.index(r, c, parent))
|
||||
loadItem(col, mdl, mdl.indexFromItem(item))
|
||||
with open(project, "r") as f:
|
||||
version = int(f.read())
|
||||
|
||||
print("Loading:", project)
|
||||
print("Detected file format version: {}. Zip: {}.".format(version, isZip))
|
||||
|
||||
if version == 0:
|
||||
v0.loadProject(project)
|
||||
else:
|
||||
v1.loadProject(project, zip=isZip)
|
||||
|
|
0
manuskript/load_save/__init__.py
Normal file
0
manuskript/load_save/__init__.py
Normal file
289
manuskript/load_save/version_0.py
Normal file
289
manuskript/load_save/version_0.py
Normal file
|
@ -0,0 +1,289 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
|
||||
# Version 0 of file saving format.
|
||||
# Was used at the begining and up util version XXX when
|
||||
# it was superseded by Version 1, which is more open and flexible
|
||||
|
||||
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 import settings
|
||||
from manuskript.functions import iconColor, iconFromColorString, mainWindow
|
||||
from manuskript.models.characterModel import Character, CharacterInfo
|
||||
|
||||
try:
|
||||
import zlib # Used with zipfile for compression
|
||||
|
||||
compression = zipfile.ZIP_DEFLATED
|
||||
except:
|
||||
compression = zipfile.ZIP_STORED
|
||||
|
||||
###########################################################################################
|
||||
# SAVE
|
||||
###########################################################################################
|
||||
|
||||
def saveProject():
|
||||
"""
|
||||
Saves the whole project. Call this function to save the project in Version 0 format.
|
||||
"""
|
||||
|
||||
files = []
|
||||
mw = mainWindow()
|
||||
|
||||
files.append((saveStandardItemModelXML(mw.mdlFlatData),
|
||||
"flatModel.xml"))
|
||||
print("ERROR: file format 0 does not save characters !")
|
||||
# files.append((saveStandardItemModelXML(mw.mdlCharacter),
|
||||
# "perso.xml"))
|
||||
files.append((saveStandardItemModelXML(mw.mdlWorld),
|
||||
"world.xml"))
|
||||
files.append((saveStandardItemModelXML(mw.mdlLabels),
|
||||
"labels.xml"))
|
||||
files.append((saveStandardItemModelXML(mw.mdlStatus),
|
||||
"status.xml"))
|
||||
files.append((saveStandardItemModelXML(mw.mdlPlots),
|
||||
"plots.xml"))
|
||||
files.append((mw.mdlOutline.saveToXML(),
|
||||
"outline.xml"))
|
||||
files.append((settings.save(),
|
||||
"settings.pickle"))
|
||||
|
||||
saveFilesToZip(files, mw.currentProject)
|
||||
|
||||
def saveFilesToZip(files, zipname):
|
||||
"""Saves given files to zipname.
|
||||
files is actually a list of (content, filename)."""
|
||||
|
||||
zf = zipfile.ZipFile(zipname, mode="w")
|
||||
|
||||
for content, filename in files:
|
||||
zf.writestr(filename, content, compress_type=compression)
|
||||
|
||||
zf.close()
|
||||
|
||||
def saveStandardItemModelXML(mdl, xml=None):
|
||||
"""Saves the given QStandardItemModel to XML.
|
||||
If xml (filename) is given, saves to xml. Otherwise returns as string."""
|
||||
|
||||
root = ET.Element("model")
|
||||
root.attrib["version"] = qApp.applicationVersion()
|
||||
|
||||
# Header
|
||||
header = ET.SubElement(root, "header")
|
||||
vHeader = ET.SubElement(header, "vertical")
|
||||
for x in range(mdl.rowCount()):
|
||||
vH = ET.SubElement(vHeader, "label")
|
||||
vH.attrib["row"] = str(x)
|
||||
vH.attrib["text"] = str(mdl.headerData(x, Qt.Vertical))
|
||||
|
||||
hHeader = ET.SubElement(header, "horizontal")
|
||||
for y in range(mdl.columnCount()):
|
||||
hH = ET.SubElement(hHeader, "label")
|
||||
hH.attrib["row"] = str(y)
|
||||
hH.attrib["text"] = str(mdl.headerData(y, Qt.Horizontal))
|
||||
|
||||
# Data
|
||||
data = ET.SubElement(root, "data")
|
||||
saveItem(data, mdl)
|
||||
|
||||
# print(qApp.tr("Saving to {}.").format(xml))
|
||||
if xml:
|
||||
ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
|
||||
else:
|
||||
return ET.tostring(root, encoding="UTF-8", xml_declaration=True, pretty_print=True)
|
||||
|
||||
|
||||
def saveItem(root, mdl, parent=QModelIndex()):
|
||||
for x in range(mdl.rowCount(parent)):
|
||||
row = ET.SubElement(root, "row")
|
||||
row.attrib["row"] = str(x)
|
||||
|
||||
for y in range(mdl.columnCount(parent)):
|
||||
col = ET.SubElement(row, "col")
|
||||
col.attrib["col"] = str(y)
|
||||
if mdl.data(mdl.index(x, y, parent), Qt.DecorationRole) != None:
|
||||
color = iconColor(mdl.data(mdl.index(x, y, parent), Qt.DecorationRole)).name(QColor.HexArgb)
|
||||
col.attrib["color"] = color if color != "#ff000000" else "#00000000"
|
||||
if mdl.data(mdl.index(x, y, parent)) != "":
|
||||
col.text = mdl.data(mdl.index(x, y, parent))
|
||||
if mdl.hasChildren(mdl.index(x, y, parent)):
|
||||
saveItem(col, mdl, mdl.index(x, y, parent))
|
||||
|
||||
###########################################################################################
|
||||
# LOAD
|
||||
###########################################################################################
|
||||
|
||||
def loadProject(project):
|
||||
|
||||
files = loadFilesFromZip(project)
|
||||
mw = mainWindow()
|
||||
|
||||
errors = []
|
||||
|
||||
if "flatModel.xml" in files:
|
||||
loadStandardItemModelXML(mw.mdlFlatData,
|
||||
files["flatModel.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("flatModel.xml")
|
||||
|
||||
if "perso.xml" in files:
|
||||
loadStandardItemModelXMLForCharacters(mw.mdlCharacter, files["perso.xml"])
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "world.xml" in files:
|
||||
loadStandardItemModelXML(mw.mdlWorld,
|
||||
files["world.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("world.xml")
|
||||
|
||||
if "labels.xml" in files:
|
||||
loadStandardItemModelXML(mw.mdlLabels,
|
||||
files["labels.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("labels.xml")
|
||||
|
||||
if "status.xml" in files:
|
||||
loadStandardItemModelXML(mw.mdlStatus,
|
||||
files["status.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("status.xml")
|
||||
|
||||
if "plots.xml" in files:
|
||||
loadStandardItemModelXML(mw.mdlPlots,
|
||||
files["plots.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("plots.xml")
|
||||
|
||||
if "outline.xml" in files:
|
||||
mw.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("outline.xml")
|
||||
|
||||
if "settings.pickle" in files:
|
||||
settings.load(files["settings.pickle"], fromString=True)
|
||||
else:
|
||||
errors.append("settings.pickle")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def loadFilesFromZip(zipname):
|
||||
"""Returns the content of zipfile as a dict of filename:content."""
|
||||
zf = zipfile.ZipFile(zipname)
|
||||
files = {}
|
||||
for f in zf.namelist():
|
||||
files[f] = zf.read(f)
|
||||
return files
|
||||
|
||||
|
||||
def loadStandardItemModelXML(mdl, xml, fromString=False):
|
||||
"""Load data to a QStandardItemModel mdl from xml.
|
||||
By default xml is a filename. If fromString=True, xml is a string containg the data."""
|
||||
|
||||
# print(qApp.tr("Loading {}... ").format(xml), end="")
|
||||
|
||||
if not fromString:
|
||||
try:
|
||||
tree = ET.parse(xml)
|
||||
except:
|
||||
print("Failed.")
|
||||
return
|
||||
else:
|
||||
root = ET.fromstring(xml)
|
||||
|
||||
# root = tree.getroot()
|
||||
|
||||
# Header
|
||||
hLabels = []
|
||||
vLabels = []
|
||||
for l in root.find("header").find("horizontal").findall("label"):
|
||||
hLabels.append(l.attrib["text"])
|
||||
for l in root.find("header").find("vertical").findall("label"):
|
||||
vLabels.append(l.attrib["text"])
|
||||
|
||||
# print(root.find("header").find("vertical").text)
|
||||
|
||||
# mdl.setVerticalHeaderLabels(vLabels)
|
||||
# mdl.setHorizontalHeaderLabels(hLabels)
|
||||
|
||||
# Populates with empty items
|
||||
for i in enumerate(vLabels):
|
||||
row = []
|
||||
for r in enumerate(hLabels):
|
||||
row.append(QStandardItem())
|
||||
mdl.appendRow(row)
|
||||
|
||||
# Data
|
||||
data = root.find("data")
|
||||
loadItem(data, mdl)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def loadItem(root, mdl, parent=QModelIndex()):
|
||||
for row in root:
|
||||
r = int(row.attrib["row"])
|
||||
for col in row:
|
||||
c = int(col.attrib["col"])
|
||||
item = mdl.itemFromIndex(mdl.index(r, c, parent))
|
||||
if not item:
|
||||
item = QStandardItem()
|
||||
mdl.itemFromIndex(parent).setChild(r, c, item)
|
||||
|
||||
if col.text:
|
||||
# mdl.setData(mdl.index(r, c, parent), col.text)
|
||||
item.setText(col.text)
|
||||
|
||||
if "color" in col.attrib:
|
||||
# mdl.itemFromIndex(mdl.index(r, c, parent)).setIcon(iconFromColorString(col.attrib["color"]))
|
||||
item.setIcon(iconFromColorString(col.attrib["color"]))
|
||||
|
||||
if len(col) != 0:
|
||||
# loadItem(col, mdl, mdl.index(r, c, parent))
|
||||
loadItem(col, mdl, mdl.indexFromItem(item))
|
||||
|
||||
|
||||
def loadStandardItemModelXMLForCharacters(mdl, xml):
|
||||
"""
|
||||
Loads a standardItemModel saved to XML by version 0, but for the new characterModel.
|
||||
@param mdl: characterModel
|
||||
@param xml: the content of the xml
|
||||
@return: nothing
|
||||
"""
|
||||
mdl = mainWindow().mdlCharacter
|
||||
root = ET.fromstring(xml)
|
||||
data = root.find("data")
|
||||
|
||||
for row in data:
|
||||
char = Character(mdl)
|
||||
|
||||
for col in row:
|
||||
c = int(col.attrib["col"])
|
||||
|
||||
# Value
|
||||
if col.text:
|
||||
char._data[c] = col.text
|
||||
|
||||
# Color
|
||||
if "color" in col.attrib:
|
||||
char.setColor(QColor(col.attrib["color"]))
|
||||
|
||||
# Infos
|
||||
if len(col) != 0:
|
||||
for rrow in col:
|
||||
info = CharacterInfo(char)
|
||||
for ccol in rrow:
|
||||
cc = int(ccol.attrib["col"])
|
||||
if cc == 11 and ccol.text:
|
||||
info.description = ccol.text
|
||||
if cc == 12 and ccol.text:
|
||||
info.value = ccol.text
|
||||
char.infos.append(info)
|
||||
|
||||
mdl.characters.append(char)
|
1042
manuskript/load_save/version_1.py
Normal file
1042
manuskript/load_save/version_1.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,15 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import faulthandler
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QLocale, QTranslator, QSettings
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QApplication, qApp
|
||||
|
||||
from manuskript.functions import appPath
|
||||
from manuskript.functions import appPath, writablePath
|
||||
|
||||
_version = "0.2.0"
|
||||
_version = "0.3.0"
|
||||
|
||||
faulthandler.enable()
|
||||
|
||||
|
@ -28,27 +29,33 @@ def run():
|
|||
|
||||
app.setStyle("Fusion")
|
||||
|
||||
# Translation process
|
||||
locale = QLocale.system().name()
|
||||
# locale = "fr_CH"
|
||||
|
||||
appTranslator = QTranslator()
|
||||
if appTranslator.load(appPath("i18n/manuskript_{}.qm").format(locale)):
|
||||
app.installTranslator(appTranslator)
|
||||
print(app.tr("Loaded transation: {}.").format(locale))
|
||||
else:
|
||||
print(app.tr("Failed to load translator for {}...").format(locale))
|
||||
|
||||
# Load style from QSettings
|
||||
settings = QSettings(app.organizationName(), app.applicationName())
|
||||
if settings.contains("applicationStyle"):
|
||||
style = settings.value("applicationStyle")
|
||||
app.setStyle(style)
|
||||
|
||||
# Translation process
|
||||
locale = QLocale.system().name()
|
||||
|
||||
appTranslator = QTranslator()
|
||||
# By default: locale
|
||||
translation = appPath(os.path.join("i18n", "manuskript_{}.qm".format(locale)))
|
||||
|
||||
# Load translation from settings
|
||||
if settings.contains("applicationTranslation"):
|
||||
translation = appPath(os.path.join("i18n", settings.value("applicationTranslation")))
|
||||
print("Found translation in settings:", translation)
|
||||
|
||||
if appTranslator.load(translation):
|
||||
app.installTranslator(appTranslator)
|
||||
print(app.tr("Loaded translation: {}.").format(translation))
|
||||
|
||||
else:
|
||||
print(app.tr("Warning: failed to load translator for locale {}...").format(locale))
|
||||
|
||||
QIcon.setThemeSearchPaths(QIcon.themeSearchPaths() + [appPath("icons")])
|
||||
QIcon.setThemeName("NumixMsk")
|
||||
print(QIcon.hasThemeIcon("dialog-no"))
|
||||
print(QIcon.themeSearchPaths())
|
||||
# qApp.setWindowIcon(QIcon.fromTheme("im-aim"))
|
||||
|
||||
# Seperating launch to avoid segfault, so it seem.
|
||||
|
|
|
@ -9,13 +9,11 @@ from PyQt5.QtWidgets import QMainWindow, QHeaderView, qApp, QMenu, QActionGroup,
|
|||
QLabel
|
||||
|
||||
from manuskript import settings
|
||||
from manuskript.enums import Perso, Subplot, Plot, World
|
||||
from manuskript.functions import AUC, wordCount, appPath
|
||||
from manuskript.loadSave import loadStandardItemModelXML, loadFilesFromZip
|
||||
from manuskript.loadSave import saveFilesToZip
|
||||
from manuskript.loadSave import saveStandardItemModelXML
|
||||
from manuskript.enums import Character, PlotStep, Plot, World, Outline
|
||||
from manuskript.functions import AUC, wordCount, appPath, findWidgetsOfClass
|
||||
from manuskript import loadSave
|
||||
from manuskript.models.characterModel import characterModel
|
||||
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
|
||||
|
@ -24,7 +22,7 @@ from manuskript.ui.compileDialog import compileDialog
|
|||
from manuskript.ui.helpLabel import helpLabel
|
||||
from manuskript.ui.mainWindow import Ui_MainWindow
|
||||
from manuskript.ui.tools.frequencyAnalyzer import frequencyAnalyzer
|
||||
from manuskript.ui.views.outlineDelegates import outlinePersoDelegate
|
||||
from manuskript.ui.views.outlineDelegates import outlineCharacterDelegate
|
||||
from manuskript.ui.views.plotDelegate import plotDelegate
|
||||
|
||||
# Spellcheck support
|
||||
|
@ -60,13 +58,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
# Welcome
|
||||
self.welcome.updateValues()
|
||||
# self.welcome.btnCreate.clicked.connect
|
||||
self.stack.setCurrentIndex(0)
|
||||
|
||||
# Word count
|
||||
self.mprWordCount = QSignalMapper(self)
|
||||
for t, i in [
|
||||
(self.txtSummarySentance, 0),
|
||||
(self.txtSummarySentence, 0),
|
||||
(self.txtSummaryPara, 1),
|
||||
(self.txtSummaryPage, 2),
|
||||
(self.txtSummaryFull, 3)
|
||||
|
@ -96,8 +93,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
# Main Menu
|
||||
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
||||
self.menuEdit, self.menuMode, self.menuView, self.menuTools,
|
||||
self.menuHelp]:
|
||||
self.menuEdit, self.menuView, self.menuTools, self.menuHelp]:
|
||||
i.setEnabled(False)
|
||||
|
||||
self.actOpen.triggered.connect(self.welcome.openFile)
|
||||
|
@ -112,6 +108,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.actToolFrequency.triggered.connect(self.frequencyAnalyzer)
|
||||
self.generateViewMenu()
|
||||
|
||||
self.actModeGroup = QActionGroup(self)
|
||||
self.actModeSimple.setActionGroup(self.actModeGroup)
|
||||
self.actModeFiction.setActionGroup(self.actModeGroup)
|
||||
self.actModeSnowflake.setActionGroup(self.actModeGroup)
|
||||
self.actModeSimple.triggered.connect(self.setViewModeSimple)
|
||||
self.actModeFiction.triggered.connect(self.setViewModeFiction)
|
||||
self.actModeSnowflake.setEnabled(False)
|
||||
|
||||
self.makeUIConnections()
|
||||
|
||||
# self.loadProject(os.path.join(appPath(), "test_project.zip"))
|
||||
|
@ -141,18 +145,21 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.treeOutlineOutline.delete()
|
||||
|
||||
###############################################################################
|
||||
# PERSOS
|
||||
# CHARACTERS
|
||||
###############################################################################
|
||||
|
||||
def changeCurrentPerso(self, trash=None):
|
||||
def changeCurrentCharacter(self, trash=None):
|
||||
"""
|
||||
|
||||
index = self.lstPersos.currentPersoIndex()
|
||||
|
||||
if not index.isValid():
|
||||
@return:
|
||||
"""
|
||||
c = self.lstCharacters.currentCharacter()
|
||||
if not c:
|
||||
self.tabPlot.setEnabled(False)
|
||||
return
|
||||
|
||||
self.tabPersos.setEnabled(True)
|
||||
index = c.index()
|
||||
|
||||
for w in [
|
||||
self.txtPersoName,
|
||||
|
@ -161,7 +168,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.txtPersoGoal,
|
||||
self.txtPersoConflict,
|
||||
self.txtPersoEpiphany,
|
||||
self.txtPersoSummarySentance,
|
||||
self.txtPersoSummarySentence,
|
||||
self.txtPersoSummaryPara,
|
||||
self.txtPersoSummaryFull,
|
||||
self.txtPersoNotes,
|
||||
|
@ -169,27 +176,24 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
w.setCurrentModelIndex(index)
|
||||
|
||||
# Button color
|
||||
self.mdlPersos.updatePersoColor(index)
|
||||
self.updateCharacterColor(c.ID())
|
||||
|
||||
# Perso Infos
|
||||
# Character Infos
|
||||
self.tblPersoInfos.setRootIndex(index)
|
||||
|
||||
if self.mdlPersos.rowCount(index):
|
||||
if self.mdlCharacter.rowCount(index):
|
||||
self.updatePersoInfoView()
|
||||
|
||||
def updatePersoInfoView(self):
|
||||
# Hide columns
|
||||
for i in range(self.mdlPersos.columnCount()):
|
||||
self.tblPersoInfos.hideColumn(i)
|
||||
self.tblPersoInfos.showColumn(Perso.infoName.value)
|
||||
self.tblPersoInfos.showColumn(Perso.infoData.value)
|
||||
|
||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
|
||||
Perso.infoName.value, QHeaderView.ResizeToContents)
|
||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
|
||||
Perso.infoData.value, QHeaderView.Stretch)
|
||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
|
||||
self.tblPersoInfos.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
|
||||
self.tblPersoInfos.verticalHeader().hide()
|
||||
|
||||
def updateCharacterColor(self, ID):
|
||||
c = self.mdlCharacter.getCharacterByID(ID)
|
||||
color = c.color().name()
|
||||
self.btnPersoColor.setStyleSheet("background:{};".format(color))
|
||||
|
||||
###############################################################################
|
||||
# PLOTS
|
||||
###############################################################################
|
||||
|
@ -207,8 +211,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.txtPlotResult.setCurrentModelIndex(index)
|
||||
self.sldPlotImportance.setCurrentModelIndex(index)
|
||||
self.lstPlotPerso.setRootIndex(index.sibling(index.row(),
|
||||
Plot.persos.value))
|
||||
subplotindex = index.sibling(index.row(), Plot.subplots.value)
|
||||
Plot.characters.value))
|
||||
subplotindex = index.sibling(index.row(), Plot.steps.value)
|
||||
self.lstSubPlots.setRootIndex(subplotindex)
|
||||
if self.mdlPlots.rowCount(subplotindex):
|
||||
self.updateSubPlotView()
|
||||
|
@ -224,18 +228,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
# Hide columns
|
||||
for i in range(self.mdlPlots.columnCount()):
|
||||
self.lstSubPlots.hideColumn(i)
|
||||
self.lstSubPlots.showColumn(Subplot.name.value)
|
||||
self.lstSubPlots.showColumn(Subplot.meta.value)
|
||||
self.lstSubPlots.showColumn(PlotStep.name.value)
|
||||
self.lstSubPlots.showColumn(PlotStep.meta.value)
|
||||
|
||||
self.lstSubPlots.horizontalHeader().setSectionResizeMode(
|
||||
Subplot.name.value, QHeaderView.Stretch)
|
||||
PlotStep.name.value, QHeaderView.Stretch)
|
||||
self.lstSubPlots.horizontalHeader().setSectionResizeMode(
|
||||
Subplot.meta.value, QHeaderView.ResizeToContents)
|
||||
PlotStep.meta.value, QHeaderView.ResizeToContents)
|
||||
self.lstSubPlots.verticalHeader().hide()
|
||||
|
||||
def changeCurrentSubPlot(self, index):
|
||||
# Got segfaults when using textEditView model system, so ad hoc stuff.
|
||||
index = index.sibling(index.row(), Subplot.summary.value)
|
||||
index = index.sibling(index.row(), PlotStep.summary.value)
|
||||
item = self.mdlPlots.itemFromIndex(index)
|
||||
if not item:
|
||||
self.txtSubPlotSummary.setEnabled(False)
|
||||
|
@ -253,7 +257,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
index = self.lstSubPlots.currentIndex()
|
||||
if not index.isValid():
|
||||
return
|
||||
index = index.sibling(index.row(), Subplot.summary.value)
|
||||
index = index.sibling(index.row(), PlotStep.summary.value)
|
||||
item = self.mdlPlots.itemFromIndex(index)
|
||||
|
||||
self._updatingSubPlot = True
|
||||
|
@ -280,11 +284,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.txtWorldName.setCurrentModelIndex(index)
|
||||
self.txtWorldDescription.setCurrentModelIndex(index)
|
||||
self.txtWorldPassion.setCurrentModelIndex(index)
|
||||
self.txtWorldConflict.setCurrentModelIndex(index)
|
||||
|
||||
###############################################################################
|
||||
# LOAD AND SAVE
|
||||
###############################################################################
|
||||
# self.txtWorldConflict.setCurrentModelIndex(index)
|
||||
#
|
||||
# ###############################################################################
|
||||
# # LOAD AND SAVE
|
||||
# ###############################################################################
|
||||
|
||||
def loadProject(self, project, loadFromFile=True):
|
||||
"""Loads the project ``project``.
|
||||
|
@ -310,7 +314,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
# Load settings
|
||||
for i in settings.openIndexes:
|
||||
idx = self.mdlOutline.indexFromPath(i)
|
||||
idx = self.mdlOutline.getIndexByID(i)
|
||||
self.mainEditor.setCurrentModelIndex(idx, newTab=True)
|
||||
self.generateViewMenu()
|
||||
self.mainEditor.sldCorkSizeFactor.setValue(settings.corkSizeFactor)
|
||||
|
@ -325,6 +329,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
# We force to emit even if it opens on the current tab
|
||||
self.tabMain.currentChanged.emit(settings.lastTab)
|
||||
self.mainEditor.updateCorkBackground()
|
||||
if settings.viewMode == "simple":
|
||||
self.setViewModeSimple()
|
||||
else:
|
||||
self.setViewModeFiction()
|
||||
|
||||
# Set autosave
|
||||
self.saveTimer = QTimer()
|
||||
|
@ -340,7 +348,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.saveTimerNoChanges.setSingleShot(True)
|
||||
self.mdlFlatData.dataChanged.connect(self.startTimerNoChanges)
|
||||
self.mdlOutline.dataChanged.connect(self.startTimerNoChanges)
|
||||
self.mdlPersos.dataChanged.connect(self.startTimerNoChanges)
|
||||
self.mdlCharacter.dataChanged.connect(self.startTimerNoChanges)
|
||||
self.mdlPlots.dataChanged.connect(self.startTimerNoChanges)
|
||||
self.mdlWorld.dataChanged.connect(self.startTimerNoChanges)
|
||||
# self.mdlPersosInfos.dataChanged.connect(self.startTimerNoChanges)
|
||||
|
@ -352,8 +360,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
# UI
|
||||
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
||||
self.menuEdit, self.menuMode, self.menuView, self.menuTools,
|
||||
self.menuHelp]:
|
||||
self.menuEdit, self.menuView, self.menuTools, self.menuHelp]:
|
||||
i.setEnabled(True)
|
||||
# FIXME: set Window's name: project name
|
||||
|
||||
|
@ -367,23 +374,27 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.stack.setCurrentIndex(1)
|
||||
|
||||
def closeProject(self):
|
||||
|
||||
if not self.currentProject:
|
||||
return
|
||||
|
||||
# Close open tabs in editor
|
||||
self.mainEditor.closeAllTabs()
|
||||
|
||||
# Save datas
|
||||
self.saveDatas()
|
||||
|
||||
self.currentProject = None
|
||||
QSettings().setValue("lastProject", "")
|
||||
|
||||
# FIXME: close all opened tabs in mainEditor
|
||||
|
||||
# Clear datas
|
||||
self.loadEmptyDatas()
|
||||
|
||||
self.saveTimer.stop()
|
||||
loadSave.clearSaveCache()
|
||||
|
||||
# UI
|
||||
for i in [self.actSave, self.actSaveAs, self.actCloseProject,
|
||||
self.menuEdit, self.menuMode, self.menuView, self.menuTools,
|
||||
self.menuHelp]:
|
||||
self.menuEdit, self.menuView, self.menuTools, self.menuHelp]:
|
||||
i.setEnabled(False)
|
||||
|
||||
# Reload recent files
|
||||
|
@ -434,10 +445,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
settings.lastTab = self.tabMain.currentIndex()
|
||||
|
||||
if self.currentProject:
|
||||
# Remembering the current items
|
||||
# Remembering the current items (stores outlineItem's ID)
|
||||
sel = []
|
||||
for i in range(self.mainEditor.tab.count()):
|
||||
sel.append(self.mdlOutline.pathToIndex(self.mainEditor.tab.widget(i).currentIndex))
|
||||
sel.append(self.mdlOutline.ID(self.mainEditor.tab.widget(i).currentIndex))
|
||||
settings.openIndexes = sel
|
||||
|
||||
# Save data from models
|
||||
|
@ -462,27 +473,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.currentProject = projectName
|
||||
QSettings().setValue("lastProject", projectName)
|
||||
|
||||
# Saving
|
||||
files = []
|
||||
|
||||
files.append((saveStandardItemModelXML(self.mdlFlatData),
|
||||
"flatModel.xml"))
|
||||
files.append((saveStandardItemModelXML(self.mdlPersos),
|
||||
"perso.xml"))
|
||||
files.append((saveStandardItemModelXML(self.mdlWorld),
|
||||
"world.xml"))
|
||||
files.append((saveStandardItemModelXML(self.mdlLabels),
|
||||
"labels.xml"))
|
||||
files.append((saveStandardItemModelXML(self.mdlStatus),
|
||||
"status.xml"))
|
||||
files.append((saveStandardItemModelXML(self.mdlPlots),
|
||||
"plots.xml"))
|
||||
files.append((self.mdlOutline.saveToXML(),
|
||||
"outline.xml"))
|
||||
files.append((settings.save(),
|
||||
"settings.pickle"))
|
||||
|
||||
saveFilesToZip(files, self.currentProject)
|
||||
loadSave.saveProject() # version=0
|
||||
self.saveTimerNoChanges.stop()
|
||||
|
||||
# Giving some feedback
|
||||
print(self.tr("Project {} saved.").format(self.currentProject))
|
||||
|
@ -491,7 +483,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
def loadEmptyDatas(self):
|
||||
self.mdlFlatData = QStandardItemModel(self)
|
||||
self.mdlPersos = persosModel(self)
|
||||
self.mdlCharacter = characterModel(self)
|
||||
# self.mdlPersosProxy = persosProxyModel(self)
|
||||
# self.mdlPersosInfos = QStandardItemModel(self)
|
||||
self.mdlLabels = QStandardItemModel(self)
|
||||
|
@ -501,56 +493,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.mdlWorld = worldModel(self)
|
||||
|
||||
def loadDatas(self, project):
|
||||
# Loading
|
||||
files = loadFilesFromZip(project)
|
||||
|
||||
errors = []
|
||||
|
||||
if "flatModel.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlFlatData,
|
||||
files["flatModel.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("flatModel.xml")
|
||||
|
||||
if "perso.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlPersos,
|
||||
files["perso.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "world.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlWorld,
|
||||
files["world.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("world.xml")
|
||||
|
||||
if "labels.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlLabels,
|
||||
files["labels.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "status.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlStatus,
|
||||
files["status.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "plots.xml" in files:
|
||||
loadStandardItemModelXML(self.mdlPlots,
|
||||
files["plots.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "outline.xml" in files:
|
||||
self.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
|
||||
if "settings.pickle" in files:
|
||||
settings.load(files["settings.pickle"], fromString=True)
|
||||
else:
|
||||
errors.append("perso.xml")
|
||||
errors = loadSave.loadProject(project)
|
||||
|
||||
# Giving some feedback
|
||||
if not errors:
|
||||
|
@ -569,8 +513,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
###############################################################################
|
||||
|
||||
def makeUIConnections(self):
|
||||
"Connections that have to be made once only, event when new project is loaded."
|
||||
self.lstPersos.currentItemChanged.connect(self.changeCurrentPerso, AUC)
|
||||
"Connections that have to be made once only, even when a new project is loaded."
|
||||
self.lstCharacters.currentItemChanged.connect(self.changeCurrentCharacter, AUC)
|
||||
|
||||
self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, AUC)
|
||||
self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, AUC)
|
||||
|
@ -592,8 +536,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
# Flat datas (Summary and general infos)
|
||||
for widget, col in [
|
||||
(self.txtSummarySituation, 0),
|
||||
(self.txtSummarySentance, 1),
|
||||
(self.txtSummarySentance_2, 1),
|
||||
(self.txtSummarySentence, 1),
|
||||
(self.txtSummarySentence_2, 1),
|
||||
(self.txtSummaryPara, 2),
|
||||
(self.txtSummaryPara_2, 2),
|
||||
(self.txtPlotSummaryPara, 2),
|
||||
|
@ -621,30 +565,33 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
widget.setColumn(col)
|
||||
widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))
|
||||
|
||||
# Persos
|
||||
self.lstPersos.setPersosModel(self.mdlPersos)
|
||||
self.tblPersoInfos.setModel(self.mdlPersos)
|
||||
# Characters
|
||||
self.lstCharacters.setCharactersModel(self.mdlCharacter)
|
||||
self.tblPersoInfos.setModel(self.mdlCharacter)
|
||||
|
||||
self.btnAddPerso.clicked.connect(self.mdlPersos.addPerso, AUC)
|
||||
self.btnRmPerso.clicked.connect(self.mdlPersos.removePerso, AUC)
|
||||
self.btnPersoColor.clicked.connect(self.mdlPersos.chosePersoColor, AUC)
|
||||
|
||||
self.btnPersoAddInfo.clicked.connect(self.mdlPersos.addPersoInfo, AUC)
|
||||
self.btnPersoRmInfo.clicked.connect(self.mdlPersos.removePersoInfo, AUC)
|
||||
self.btnAddPerso.clicked.connect(self.mdlCharacter.addCharacter, AUC)
|
||||
try:
|
||||
self.btnRmPerso.clicked.connect(self.lstCharacters.removeCharacter, AUC)
|
||||
self.btnPersoColor.clicked.connect(self.lstCharacters.choseCharacterColor, AUC)
|
||||
self.btnPersoAddInfo.clicked.connect(self.lstCharacters.addCharacterInfo, AUC)
|
||||
self.btnPersoRmInfo.clicked.connect(self.lstCharacters.removeCharacterInfo, AUC)
|
||||
except TypeError:
|
||||
# Connection has already been made
|
||||
pass
|
||||
|
||||
for w, c in [
|
||||
(self.txtPersoName, Perso.name.value),
|
||||
(self.sldPersoImportance, Perso.importance.value),
|
||||
(self.txtPersoMotivation, Perso.motivation.value),
|
||||
(self.txtPersoGoal, Perso.goal.value),
|
||||
(self.txtPersoConflict, Perso.conflict.value),
|
||||
(self.txtPersoEpiphany, Perso.epiphany.value),
|
||||
(self.txtPersoSummarySentance, Perso.summarySentance.value),
|
||||
(self.txtPersoSummaryPara, Perso.summaryPara.value),
|
||||
(self.txtPersoSummaryFull, Perso.summaryFull.value),
|
||||
(self.txtPersoNotes, Perso.notes.value)
|
||||
(self.txtPersoName, Character.name.value),
|
||||
(self.sldPersoImportance, Character.importance.value),
|
||||
(self.txtPersoMotivation, Character.motivation.value),
|
||||
(self.txtPersoGoal, Character.goal.value),
|
||||
(self.txtPersoConflict, Character.conflict.value),
|
||||
(self.txtPersoEpiphany, Character.epiphany.value),
|
||||
(self.txtPersoSummarySentence, Character.summarySentence.value),
|
||||
(self.txtPersoSummaryPara, Character.summaryPara.value),
|
||||
(self.txtPersoSummaryFull, Character.summaryFull.value),
|
||||
(self.txtPersoNotes, Character.notes.value)
|
||||
]:
|
||||
w.setModel(self.mdlPersos)
|
||||
w.setModel(self.mdlCharacter)
|
||||
w.setColumn(c)
|
||||
self.tabPersos.setEnabled(False)
|
||||
|
||||
|
@ -672,13 +619,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
self.tabPlot.setEnabled(False)
|
||||
self.mdlPlots.updatePlotPersoButton()
|
||||
self.mdlPersos.dataChanged.connect(self.mdlPlots.updatePlotPersoButton)
|
||||
self.mdlCharacter.dataChanged.connect(self.mdlPlots.updatePlotPersoButton)
|
||||
self.lstOutlinePlots.setPlotModel(self.mdlPlots)
|
||||
self.lstOutlinePlots.setShowSubPlot(True)
|
||||
self.plotPersoDelegate = outlinePersoDelegate(self.mdlPersos, self)
|
||||
self.lstPlotPerso.setItemDelegate(self.plotPersoDelegate)
|
||||
self.plotCharacterDelegate = outlineCharacterDelegate(self.mdlCharacter, self)
|
||||
self.lstPlotPerso.setItemDelegate(self.plotCharacterDelegate)
|
||||
self.plotDelegate = plotDelegate(self)
|
||||
self.lstSubPlots.setItemDelegateForColumn(Subplot.meta.value, self.plotDelegate)
|
||||
self.lstSubPlots.setItemDelegateForColumn(PlotStep.meta.value, self.plotDelegate)
|
||||
|
||||
# World
|
||||
self.treeWorld.setModel(self.mdlWorld)
|
||||
|
@ -702,18 +649,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
# Outline
|
||||
self.treeRedacOutline.setModel(self.mdlOutline)
|
||||
self.treeOutlineOutline.setModelPersos(self.mdlPersos)
|
||||
self.treeOutlineOutline.setModelCharacters(self.mdlCharacter)
|
||||
self.treeOutlineOutline.setModelLabels(self.mdlLabels)
|
||||
self.treeOutlineOutline.setModelStatus(self.mdlStatus)
|
||||
|
||||
self.redacMetadata.setModels(self.mdlOutline, self.mdlPersos,
|
||||
self.redacMetadata.setModels(self.mdlOutline, self.mdlCharacter,
|
||||
self.mdlLabels, self.mdlStatus)
|
||||
self.outlineItemEditor.setModels(self.mdlOutline, self.mdlPersos,
|
||||
self.outlineItemEditor.setModels(self.mdlOutline, self.mdlCharacter,
|
||||
self.mdlLabels, self.mdlStatus)
|
||||
|
||||
self.treeOutlineOutline.setModel(self.mdlOutline)
|
||||
# self.redacEditor.setModel(self.mdlOutline)
|
||||
self.storylineView.setModels(self.mdlOutline, self.mdlPersos, self.mdlPlots)
|
||||
self.storylineView.setModels(self.mdlOutline, self.mdlCharacter, self.mdlPlots)
|
||||
|
||||
self.treeOutlineOutline.selectionModel().selectionChanged.connect(lambda:
|
||||
self.outlineItemEditor.selectionChanged(
|
||||
|
@ -735,12 +682,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
# Debug
|
||||
self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"])
|
||||
self.tblDebugFlatData.setModel(self.mdlFlatData)
|
||||
self.tblDebugPersos.setModel(self.mdlPersos)
|
||||
self.tblDebugPersosInfos.setModel(self.mdlPersos)
|
||||
self.tblDebugPersos.setModel(self.mdlCharacter)
|
||||
self.tblDebugPersosInfos.setModel(self.mdlCharacter)
|
||||
self.tblDebugPersos.selectionModel().currentChanged.connect(
|
||||
lambda: self.tblDebugPersosInfos.setRootIndex(self.mdlPersos.index(
|
||||
lambda: self.tblDebugPersosInfos.setRootIndex(self.mdlCharacter.index(
|
||||
self.tblDebugPersos.selectionModel().currentIndex().row(),
|
||||
Perso.name.value)), AUC)
|
||||
Character.name.value)), AUC)
|
||||
|
||||
self.tblDebugPlots.setModel(self.mdlPlots)
|
||||
self.tblDebugPlotsPersos.setModel(self.mdlPlots)
|
||||
|
@ -748,11 +695,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.tblDebugPlots.selectionModel().currentChanged.connect(
|
||||
lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index(
|
||||
self.tblDebugPlots.selectionModel().currentIndex().row(),
|
||||
Plot.persos.value)), AUC)
|
||||
Plot.characters.value)), AUC)
|
||||
self.tblDebugPlots.selectionModel().currentChanged.connect(
|
||||
lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
|
||||
self.tblDebugPlots.selectionModel().currentIndex().row(),
|
||||
Plot.subplots.value)), AUC)
|
||||
Plot.steps.value)), AUC)
|
||||
self.treeDebugWorld.setModel(self.mdlWorld)
|
||||
self.treeDebugOutline.setModel(self.mdlOutline)
|
||||
self.lstDebugLabels.setModel(self.mdlLabels)
|
||||
|
@ -787,14 +734,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
def wordCount(self, i):
|
||||
|
||||
src = {
|
||||
0: self.txtSummarySentance,
|
||||
0: self.txtSummarySentence,
|
||||
1: self.txtSummaryPara,
|
||||
2: self.txtSummaryPage,
|
||||
3: self.txtSummaryFull
|
||||
}[i]
|
||||
|
||||
lbl = {
|
||||
0: self.lblSummaryWCSentance,
|
||||
0: self.lblSummaryWCSentence,
|
||||
1: self.lblSummaryWCPara,
|
||||
2: self.lblSummaryWCPage,
|
||||
3: self.lblSummaryWCFull
|
||||
|
@ -881,7 +828,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
1),
|
||||
(self.lytSummary,
|
||||
self.tr(
|
||||
"""Take time to think about a one sentance (~50 words) summary of your book. Then expand it to
|
||||
"""Take time to think about a one sentence (~50 words) summary of your book. Then expand it to
|
||||
a paragraph, then to a page, then to a full summary."""),
|
||||
1),
|
||||
(self.lytTabPersos,
|
||||
|
@ -1046,6 +993,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
}
|
||||
|
||||
self.menuView.clear()
|
||||
self.menuView.addMenu(self.menuMode)
|
||||
self.menuView.addSeparator()
|
||||
|
||||
# print("Generating menus with", settings.viewSettings)
|
||||
|
||||
|
@ -1081,6 +1030,48 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
if item == "Tree":
|
||||
self.treeRedacOutline.viewport().update()
|
||||
|
||||
###############################################################################
|
||||
# VIEW MODES
|
||||
###############################################################################
|
||||
|
||||
def setViewModeSimple(self):
|
||||
settings.viewMode = "simple"
|
||||
self.tabMain.setCurrentIndex(self.TabRedac)
|
||||
self.viewModeFictionVisibilitySwitch(False)
|
||||
self.actModeSimple.setChecked(True)
|
||||
|
||||
def setViewModeFiction(self):
|
||||
settings.viewMode = "fiction"
|
||||
self.viewModeFictionVisibilitySwitch(True)
|
||||
self.actModeFiction.setChecked(True)
|
||||
|
||||
def viewModeFictionVisibilitySwitch(self, val):
|
||||
"""
|
||||
Swtiches the visibility of some UI components useful for fiction only
|
||||
@param val: sets visibility to val
|
||||
"""
|
||||
|
||||
# Menu navigation & boutton in toolbar
|
||||
self.toolbar.setDockVisibility(self.dckNavigation, val)
|
||||
|
||||
# POV in metadatas
|
||||
from manuskript.ui.views.propertiesView import propertiesView
|
||||
for w in findWidgetsOfClass(propertiesView):
|
||||
w.lblPOV.setVisible(val)
|
||||
w.cmbPOV.setVisible(val)
|
||||
|
||||
# POV in outline view
|
||||
if Outline.POV.value in settings.outlineViewColumns:
|
||||
settings.outlineViewColumns.remove(Outline.POV.value)
|
||||
|
||||
from manuskript.ui.views.outlineView import outlineView
|
||||
for w in findWidgetsOfClass(outlineView):
|
||||
w.hideColumns()
|
||||
|
||||
# TODO: clean up all other fiction things in non-fiction view mode
|
||||
# Character in search widget
|
||||
# POV in settings / views
|
||||
|
||||
###############################################################################
|
||||
# COMPILE
|
||||
###############################################################################
|
||||
|
|
299
manuskript/models/characterModel.py
Normal file
299
manuskript/models/characterModel.py
Normal file
|
@ -0,0 +1,299 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import QModelIndex, Qt, QAbstractItemModel, QVariant
|
||||
from PyQt5.QtGui import QIcon, QPixmap, QColor
|
||||
|
||||
from manuskript.functions import randomColor, iconColor, mainWindow
|
||||
from manuskript.enums import Character as C
|
||||
|
||||
|
||||
class characterModel(QAbstractItemModel):
|
||||
|
||||
def __init__(self, parent):
|
||||
QAbstractItemModel.__init__(self, parent)
|
||||
|
||||
# CharacterItems are stored in this list
|
||||
self.characters = []
|
||||
|
||||
###############################################################################
|
||||
# QAbstractItemModel subclassed
|
||||
###############################################################################
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
if parent.isValid():
|
||||
c = parent.internalPointer()
|
||||
return len(c.infos)
|
||||
else:
|
||||
return len(self.characters)
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
if parent.isValid():
|
||||
# Returns characters infos
|
||||
return 2
|
||||
else:
|
||||
return len(C)
|
||||
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
c = index.internalPointer()
|
||||
if type(c) == Character:
|
||||
if role == Qt.DisplayRole:
|
||||
if index.column() in c._data:
|
||||
return c._data[index.column()]
|
||||
else:
|
||||
return ""
|
||||
|
||||
elif role == Qt.DecorationRole:
|
||||
if index.column() == C.name.value:
|
||||
return c.icon
|
||||
else:
|
||||
return QVariant()
|
||||
|
||||
elif type(c) == CharacterInfo:
|
||||
if role == Qt.DisplayRole or role == Qt.EditRole:
|
||||
if index.column() == 0:
|
||||
return c.description
|
||||
elif index.column() == 1:
|
||||
return c.value
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
c = index.internalPointer()
|
||||
if type(c) == Character:
|
||||
if role == Qt.EditRole:
|
||||
# We update only if data is different
|
||||
if index.column() not in c._data or c._data[index.column()] != value:
|
||||
c._data[index.column()] = value
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
elif type(c) == CharacterInfo:
|
||||
if role == Qt.EditRole:
|
||||
if index.column() == 0:
|
||||
c.description = value
|
||||
elif index.column() == 1:
|
||||
c.value = value
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def index(self, row, column, parent=QModelIndex()):
|
||||
if not parent.isValid():
|
||||
return self.createIndex(row, column, self.characters[row])
|
||||
|
||||
else:
|
||||
c = parent.internalPointer()
|
||||
if row < len(c.infos):
|
||||
return self.createIndex(row, column, c.infos[row])
|
||||
else:
|
||||
return QModelIndex()
|
||||
|
||||
def indexFromItem(self, item, column=0):
|
||||
if not item:
|
||||
return QModelIndex()
|
||||
|
||||
row = self.characters.index(item)
|
||||
col = column
|
||||
return self.createIndex(row, col, item)
|
||||
|
||||
def parent(self, index):
|
||||
if not index.isValid():
|
||||
return QModelIndex()
|
||||
|
||||
child = index.internalPointer()
|
||||
|
||||
if type(child) == Character:
|
||||
return QModelIndex()
|
||||
|
||||
elif type(child) == CharacterInfo:
|
||||
return child.character.index()
|
||||
|
||||
def flags(self, index):
|
||||
if index.parent().isValid():
|
||||
return QAbstractItemModel.flags(self, index) | Qt.ItemIsEditable
|
||||
else:
|
||||
return QAbstractItemModel.flags(self, index)
|
||||
|
||||
###############################################################################
|
||||
# CHARACTER QUERRIES
|
||||
###############################################################################
|
||||
|
||||
def character(self, row):
|
||||
return self.characters[row]
|
||||
|
||||
def name(self, row):
|
||||
return self.character(row).name()
|
||||
|
||||
def icon(self, row):
|
||||
return self.character(row).icon
|
||||
|
||||
def ID(self, row):
|
||||
return self.character(row).ID()
|
||||
|
||||
def importance(self, row):
|
||||
return self.character(row).importance()
|
||||
|
||||
###############################################################################
|
||||
# MODEL QUERRIES
|
||||
###############################################################################
|
||||
|
||||
def getCharactersByImportance(self):
|
||||
"""
|
||||
Lists characters by importance.
|
||||
|
||||
@return: array of array of ´character´, by importance.
|
||||
"""
|
||||
r = [[], [], []]
|
||||
for c in self.characters:
|
||||
r[2-int(c.importance())].append(c)
|
||||
return r
|
||||
|
||||
def getCharacterByID(self, ID):
|
||||
if ID is not None:
|
||||
ID = str(ID)
|
||||
for c in self.characters:
|
||||
if c.ID() == ID:
|
||||
return c
|
||||
return None
|
||||
|
||||
###############################################################################
|
||||
# ADDING / REMOVING
|
||||
###############################################################################
|
||||
|
||||
def addCharacter(self):
|
||||
"""
|
||||
Creates a new character
|
||||
@return: the character
|
||||
"""
|
||||
c = Character(model=self, name=self.tr("New character"))
|
||||
self.beginInsertRows(QModelIndex(), len(self.characters), len(self.characters))
|
||||
self.characters.append(c)
|
||||
self.endInsertRows()
|
||||
return c
|
||||
|
||||
def removeCharacter(self, ID):
|
||||
"""
|
||||
Removes character whose ID is ID...
|
||||
@param ID: the ID of the character to remove
|
||||
@return: nothing
|
||||
"""
|
||||
c = self.getCharacterByID(ID)
|
||||
self.beginRemoveRows(QModelIndex(), self.characters.index(c), self.characters.index(c))
|
||||
self.characters.remove(c)
|
||||
self.endRemoveRows()
|
||||
|
||||
###############################################################################
|
||||
# CHARACTER INFOS
|
||||
###############################################################################
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
||||
if section == 0:
|
||||
return self.tr("Name")
|
||||
elif section == 1:
|
||||
return self.tr("Value")
|
||||
else:
|
||||
return C(section).name
|
||||
|
||||
def addCharacterInfo(self, ID):
|
||||
c = self.getCharacterByID(ID)
|
||||
self.beginInsertRows(c.index(), len(c.infos), len(c.infos))
|
||||
c.infos.append(CharacterInfo(c, description="Description", value="Value"))
|
||||
self.endInsertRows()
|
||||
|
||||
mainWindow().updatePersoInfoView()
|
||||
|
||||
def removeCharacterInfo(self, ID):
|
||||
c = self.getCharacterByID(ID)
|
||||
|
||||
rm = []
|
||||
for idx in mainWindow().tblPersoInfos.selectedIndexes():
|
||||
if not idx.row() in rm:
|
||||
rm.append(idx.row())
|
||||
|
||||
rm.sort()
|
||||
rm.reverse()
|
||||
for r in rm:
|
||||
self.beginRemoveRows(c.index(), r, r)
|
||||
c.infos.pop(r)
|
||||
self.endRemoveRows()
|
||||
|
||||
###############################################################################
|
||||
# CHARACTER
|
||||
###############################################################################
|
||||
|
||||
class Character():
|
||||
def __init__(self, model, name="No name"):
|
||||
self._model = model
|
||||
self.lastPath = ""
|
||||
|
||||
self._data = {}
|
||||
self._data[C.name.value] = name
|
||||
self.assignUniqueID()
|
||||
self.assignRandomColor()
|
||||
self._data[C.importance.value] = "0"
|
||||
|
||||
self.infos = []
|
||||
|
||||
def name(self):
|
||||
return self._data[C.name.value]
|
||||
|
||||
def importance(self):
|
||||
return self._data[C.importance.value]
|
||||
|
||||
def ID(self):
|
||||
return self._data[C.ID.value]
|
||||
|
||||
def index(self, column=0):
|
||||
return self._model.indexFromItem(self, column)
|
||||
|
||||
def assignRandomColor(self):
|
||||
"""
|
||||
Assigns a random color the the character.
|
||||
"""
|
||||
color = randomColor(QColor(Qt.white))
|
||||
self.setColor(color)
|
||||
|
||||
def setColor(self, color):
|
||||
"""
|
||||
Sets the character's color
|
||||
@param color: QColor.
|
||||
"""
|
||||
px = QPixmap(32, 32)
|
||||
px.fill(color)
|
||||
self.icon = QIcon(px)
|
||||
try:
|
||||
self._model.dataChanged.emit(self.index(), self.index())
|
||||
except:
|
||||
# If it is the initialisation, won't be able to emit
|
||||
pass
|
||||
|
||||
def color(self):
|
||||
"""
|
||||
Returns character's color in QColor
|
||||
@return: QColor
|
||||
"""
|
||||
return iconColor(self.icon)
|
||||
|
||||
def assignUniqueID(self, parent=QModelIndex()):
|
||||
"""Assigns an unused character ID."""
|
||||
vals = []
|
||||
for c in self._model.characters:
|
||||
vals.append(int(c.ID()))
|
||||
|
||||
k = 0
|
||||
while k in vals:
|
||||
k += 1
|
||||
|
||||
self._data[C.ID.value] = str(k)
|
||||
|
||||
def listInfos(self):
|
||||
r = []
|
||||
for i in self.infos:
|
||||
r.append((i.description, i.value))
|
||||
return r
|
||||
|
||||
class CharacterInfo():
|
||||
def __init__(self, character, description="", value=""):
|
||||
self.description = description
|
||||
self.value = value
|
||||
self.character = character
|
|
@ -15,10 +15,10 @@ from manuskript import settings
|
|||
from lxml import etree as ET
|
||||
|
||||
from manuskript.enums import Outline
|
||||
from manuskript.functions import mainWindow, toInt, wordCount
|
||||
from manuskript.functions import mainWindow, toInt, wordCount, HTML2PlainText
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
import time
|
||||
import time, os
|
||||
|
||||
|
||||
class outlineModel(QAbstractItemModel):
|
||||
|
@ -27,6 +27,9 @@ class outlineModel(QAbstractItemModel):
|
|||
|
||||
self.rootItem = outlineItem(self, title="root", ID="0")
|
||||
|
||||
# Stores removed item, in order to remove them on disk when saving, depending on the file format.
|
||||
self.removed = []
|
||||
|
||||
def index(self, row, column, parent):
|
||||
|
||||
if not self.hasIndex(row, column, parent):
|
||||
|
@ -74,9 +77,7 @@ class outlineModel(QAbstractItemModel):
|
|||
in columns ``columns`` (being a list of int)."""
|
||||
return self.rootItem.findItemsContaining(text, columns, mainWindow(), caseSensitive)
|
||||
|
||||
def getIndexByID(self, ID):
|
||||
"Returns the index of item whose ID is ``ID``. If none, returns QModelIndex()."
|
||||
|
||||
def getItemByID(self, ID):
|
||||
def search(item):
|
||||
if item.ID() == ID:
|
||||
return item
|
||||
|
@ -86,6 +87,11 @@ class outlineModel(QAbstractItemModel):
|
|||
return r
|
||||
|
||||
item = search(self.rootItem)
|
||||
return item
|
||||
|
||||
def getIndexByID(self, ID):
|
||||
"Returns the index of item whose ID is ``ID``. If none, returns QModelIndex()."
|
||||
item = self.getItemByID(ID)
|
||||
if not item:
|
||||
return QModelIndex()
|
||||
else:
|
||||
|
@ -363,7 +369,8 @@ class outlineModel(QAbstractItemModel):
|
|||
|
||||
self.beginRemoveRows(parent, row, row + count - 1)
|
||||
for i in range(count):
|
||||
parentItem.removeChild(row)
|
||||
item = parentItem.removeChild(row)
|
||||
self.removed.append(item)
|
||||
|
||||
self.endRemoveRows()
|
||||
return True
|
||||
|
@ -400,19 +407,6 @@ class outlineModel(QAbstractItemModel):
|
|||
self.rootItem = outlineItem(model=self, xml=ET.tostring(root), ID="0")
|
||||
self.rootItem.checkIDs()
|
||||
|
||||
def pathToIndex(self, index, path=""):
|
||||
# FIXME: Use item's ID instead of rows
|
||||
if not index.isValid():
|
||||
return ""
|
||||
if index.parent().isValid():
|
||||
path = self.pathToIndex(index.parent())
|
||||
if path:
|
||||
path = "{},{}".format(path, str(index.row()))
|
||||
else:
|
||||
path = str(index.row())
|
||||
|
||||
return path
|
||||
|
||||
def indexFromPath(self, path):
|
||||
path = path.split(",")
|
||||
item = self.rootItem
|
||||
|
@ -431,6 +425,8 @@ class outlineItem():
|
|||
self._model = model
|
||||
self.defaultTextType = None
|
||||
self.IDs = [] # used by root item to store unique IDs
|
||||
self._lastPath = "" # used by loadSave version_1 to remember which files the items comes from,
|
||||
# in case it is renamed / removed
|
||||
|
||||
if title:
|
||||
self._data[Outline.title] = title
|
||||
|
@ -485,12 +481,8 @@ class outlineItem():
|
|||
elif role == Qt.DecorationRole and column == Outline.title.value:
|
||||
if self.isFolder():
|
||||
return QIcon.fromTheme("folder")
|
||||
elif self.isText():
|
||||
elif self.isMD():
|
||||
return QIcon.fromTheme("text-x-generic")
|
||||
elif self.isT2T():
|
||||
return QIcon.fromTheme("text-x-script")
|
||||
elif self.isHTML():
|
||||
return QIcon.fromTheme("text-html")
|
||||
|
||||
# elif role == Qt.ForegroundRole:
|
||||
# if self.isCompile() in [0, "0"]:
|
||||
|
@ -531,17 +523,7 @@ class outlineItem():
|
|||
updateWordCount = not Outline(column) in self._data or self._data[Outline(column)] != data
|
||||
|
||||
# Stuff to do before
|
||||
if column == Outline.type.value:
|
||||
oldType = self._data[Outline.type]
|
||||
if oldType == "html" and data in ["txt", "t2t"]:
|
||||
# Resource inneficient way to convert HTML to plain text
|
||||
e = QTextEdit()
|
||||
e.setHtml(self._data[Outline.text])
|
||||
self._data[Outline.text] = e.toPlainText()
|
||||
elif oldType in ["txt", "t2t"] and data == "html" and Outline.text in self._data:
|
||||
self._data[Outline.text] = self._data[Outline.text].replace("\n", "<br>")
|
||||
|
||||
elif column == Outline.text.value:
|
||||
if column == Outline.text.value:
|
||||
self.addRevision()
|
||||
|
||||
# Setting data
|
||||
|
@ -603,7 +585,7 @@ class outlineItem():
|
|||
self.parent().updateWordCount(emit)
|
||||
|
||||
def row(self):
|
||||
if self.parent:
|
||||
if self.parent():
|
||||
return self.parent().childItems.index(self)
|
||||
|
||||
def appendChild(self, child):
|
||||
|
@ -645,9 +627,15 @@ class outlineItem():
|
|||
c.emitDataChanged(cols, recursive=True)
|
||||
|
||||
def removeChild(self, row):
|
||||
self.childItems.pop(row)
|
||||
"""
|
||||
Removes child at position `row` and returns it.
|
||||
@param row: index (int) of the child to remove.
|
||||
@return: the removed outlineItem
|
||||
"""
|
||||
r = self.childItems.pop(row)
|
||||
# Might be causing segfault when updateWordCount emits dataChanged
|
||||
self.updateWordCount(emit=False)
|
||||
return r
|
||||
|
||||
def parent(self):
|
||||
return self._parent
|
||||
|
@ -658,14 +646,14 @@ class outlineItem():
|
|||
def isFolder(self):
|
||||
return self._data[Outline.type] == "folder"
|
||||
|
||||
def isT2T(self):
|
||||
return self._data[Outline.type] == "t2t"
|
||||
|
||||
def isHTML(self):
|
||||
return self._data[Outline.type] == "html"
|
||||
|
||||
def isText(self):
|
||||
return self._data[Outline.type] == "txt"
|
||||
return self._data[Outline.type] == "md"
|
||||
|
||||
def isMD(self):
|
||||
return self._data[Outline.type] == "md"
|
||||
|
||||
def isMMD(self):
|
||||
return self._data[Outline.type] == "md"
|
||||
|
||||
def text(self):
|
||||
return self.data(Outline.text.value)
|
||||
|
@ -758,6 +746,9 @@ class outlineItem():
|
|||
revItem.set("text", r[1])
|
||||
item.append(revItem)
|
||||
|
||||
# Saving lastPath
|
||||
item.set("lastPath", self._lastPath)
|
||||
|
||||
for i in self.childItems:
|
||||
item.append(ET.XML(i.toXML()))
|
||||
|
||||
|
@ -773,6 +764,18 @@ class outlineItem():
|
|||
# else:
|
||||
self.setData(Outline.__members__[k].value, str(root.attrib[k]))
|
||||
|
||||
if "lastPath" in root.attrib:
|
||||
self._lastPath = root.attrib["lastPath"]
|
||||
|
||||
# If loading from an old file format, convert to md and remove html markup
|
||||
if self.type() in ["txt", "t2t"]:
|
||||
self.setData(Outline.type.value, "md")
|
||||
|
||||
elif self.type() == "html":
|
||||
self.setData(Outline.type.value, "md")
|
||||
self.setData(Outline.text.value, HTML2PlainText(self.data(Outline.text.value)))
|
||||
self.setData(Outline.notes.value, HTML2PlainText(self.data(Outline.notes.value)))
|
||||
|
||||
for child in root:
|
||||
if child.tag == "outlineItem":
|
||||
item = outlineItem(self._model, xml=ET.tostring(child), parent=self)
|
||||
|
@ -854,8 +857,13 @@ class outlineItem():
|
|||
text = text.lower() if not caseSensitive else text
|
||||
for c in columns:
|
||||
|
||||
if c == Outline.POV.value:
|
||||
searchIn = mainWindow.mdlPersos.getPersoNameByID(self.POV())
|
||||
if c == Outline.POV.value and self.POV():
|
||||
c = mainWindow.mdlCharacter.getCharacterByID(self.POV())
|
||||
if c:
|
||||
searchIn = c.name()
|
||||
else:
|
||||
searchIn = ""
|
||||
print("Character POV not found:", self.POV())
|
||||
|
||||
elif c == Outline.status.value:
|
||||
searchIn = mainWindow.mdlStatus.item(toInt(self.status()), 0).text()
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- 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):
|
||||
|
||||
def __init__(self, parent):
|
||||
QStandardItemModel.__init__(self, 0, 3, parent)
|
||||
self.setHorizontalHeaderLabels([i.name for i in Perso])
|
||||
self.mw = mainWindow()
|
||||
# self._proxy = plotsProxyModel()
|
||||
# self._proxy.setSourceModel(self)
|
||||
|
||||
###############################################################################
|
||||
# PERSOS QUERRIES
|
||||
###############################################################################
|
||||
|
||||
def name(self, row):
|
||||
return self.item(row, Perso.name.value).text()
|
||||
|
||||
def icon(self, row):
|
||||
return self.item(row, Perso.name.value).icon()
|
||||
|
||||
def ID(self, row):
|
||||
return self.item(row, Perso.ID.value).text()
|
||||
|
||||
def importance(self, row):
|
||||
return self.item(row, Perso.importance.value).text()
|
||||
|
||||
###############################################################################
|
||||
# MODEL QUERRIES
|
||||
###############################################################################
|
||||
|
||||
def getPersosByImportance(self):
|
||||
persos = [[], [], []]
|
||||
for i in range(self.rowCount()):
|
||||
importance = self.item(i, Perso.importance.value).text()
|
||||
ID = self.item(i, Perso.ID.value).text()
|
||||
persos[2-toInt(importance)].append(ID)
|
||||
return persos
|
||||
|
||||
def getPersoNameByID(self, ID):
|
||||
index = self.getIndexFromID(ID)
|
||||
if index.isValid():
|
||||
return self.name(index.row())
|
||||
return ""
|
||||
|
||||
def getIndexFromID(self, ID):
|
||||
for i in range(self.rowCount()):
|
||||
_ID = self.item(i, Perso.ID.value).text()
|
||||
if _ID == ID or toInt(_ID) == ID:
|
||||
return self.index(i, 0)
|
||||
return QModelIndex()
|
||||
|
||||
def getPersoColorByID(self, ID):
|
||||
idx = self.getIndexFromID(ID)
|
||||
return self.getPersoColorName(idx)
|
||||
|
||||
def getPersoColorName(self, index):
|
||||
icon = self.item(index.row()).icon()
|
||||
return iconColor(icon).name() if icon else ""
|
||||
|
||||
def currentListIndex(self):
|
||||
i = self.mw.lstPersos.currentIndex()
|
||||
if i .isValid():
|
||||
return i
|
||||
else:
|
||||
return None
|
||||
|
||||
def currentPersoIndex(self):
|
||||
return self.mw.lstPersos.currentPersoIndex()
|
||||
|
||||
###############################################################################
|
||||
# ADDING / REMOVING
|
||||
###############################################################################
|
||||
|
||||
def addPerso(self):
|
||||
"""Creates a perso by adding a row in mdlPersos
|
||||
and a column in mdlPersosInfos with same ID"""
|
||||
p = QStandardItem(self.tr("New character"))
|
||||
self.setPersoColor(p, randomColor(QColor(Qt.white)))
|
||||
|
||||
pid = self.getUniqueID()
|
||||
self.appendRow([p, QStandardItem(pid), QStandardItem("0")])
|
||||
|
||||
def getUniqueID(self, parent=QModelIndex()):
|
||||
"""Returns an unused perso ID (row 1)."""
|
||||
vals = []
|
||||
for i in range(self.rowCount(parent)):
|
||||
index = self.index(i, Perso.ID.value, parent)
|
||||
if index.isValid() and index.data():
|
||||
vals.append(int(index.data()))
|
||||
|
||||
k = 0
|
||||
while k in vals:
|
||||
k += 1
|
||||
return str(k)
|
||||
|
||||
def removePerso(self):
|
||||
index = self.currentPersoIndex()
|
||||
self.takeRow(index.row())
|
||||
|
||||
def setPersoColor(self, item, color):
|
||||
px = QPixmap(32, 32)
|
||||
px.fill(color)
|
||||
item.setIcon(QIcon(px))
|
||||
|
||||
def chosePersoColor(self):
|
||||
idx = self.currentPersoIndex()
|
||||
item = self.item(idx.row(), Perso.name.value)
|
||||
if item:
|
||||
color = iconColor(item.icon())
|
||||
else:
|
||||
color = Qt.white
|
||||
self.colorDialog = QColorDialog(color, self.mw)
|
||||
color = self.colorDialog.getColor(color)
|
||||
if color.isValid():
|
||||
self.setPersoColor(item, color)
|
||||
self.updatePersoColor(idx)
|
||||
|
||||
###############################################################################
|
||||
# UI
|
||||
###############################################################################
|
||||
|
||||
def updatePersoColor(self, idx):
|
||||
# idx = self.currentPersoIndex()
|
||||
color = self.getPersoColorName(idx)
|
||||
self.mw.btnPersoColor.setStyleSheet("background:{};".format(color))
|
||||
|
||||
###############################################################################
|
||||
# PERSO INFOS
|
||||
###############################################################################
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
||||
if section == Perso.infoName.value:
|
||||
return self.tr("Name")
|
||||
elif section == Perso.infoData.value:
|
||||
return self.tr("Value")
|
||||
else:
|
||||
return Perso(section).name
|
||||
else:
|
||||
return QStandardItemModel.headerData(self, section, orientation, role)
|
||||
|
||||
def addPersoInfo(self):
|
||||
perso = self.itemFromIndex(self.currentPersoIndex())
|
||||
row = perso.rowCount()
|
||||
perso.setChild(row, Perso.infoName.value, QStandardItem(""))
|
||||
perso.setChild(row, Perso.infoData.value, QStandardItem(""))
|
||||
|
||||
self.mw.updatePersoInfoView()
|
||||
|
||||
def removePersoInfo(self):
|
||||
perso = self.itemFromIndex(self.currentPersoIndex())
|
||||
|
||||
rm = []
|
||||
for idx in self.mw.tblPersoInfos.selectedIndexes():
|
||||
if not idx.row() in rm:
|
||||
rm.append(idx.row())
|
||||
|
||||
rm.sort()
|
||||
rm.reverse()
|
||||
for r in rm:
|
||||
perso.takeRow(r)
|
||||
|
||||
def listPersoInfos(self, index):
|
||||
infos = []
|
||||
for i in range(self.rowCount(index)):
|
||||
name = self.data(index.child(i, Perso.infoName.value))
|
||||
val = self.data(index.child(i, Perso.infoData.value))
|
||||
infos.append((name, val))
|
||||
|
||||
return infos
|
|
@ -9,7 +9,7 @@ from PyQt5.QtGui import QStandardItemModel
|
|||
from PyQt5.QtWidgets import QAction, QMenu
|
||||
|
||||
from manuskript.enums import Plot
|
||||
from manuskript.enums import Subplot
|
||||
from manuskript.enums import PlotStep
|
||||
from manuskript.functions import toInt, mainWindow
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ class plotModel(QStandardItemModel):
|
|||
index = self.getIndexFromID(ID)
|
||||
if not index.isValid():
|
||||
return
|
||||
index = index.sibling(index.row(), Plot.subplots.value)
|
||||
index = index.sibling(index.row(), Plot.steps.value)
|
||||
item = self.itemFromIndex(index)
|
||||
lst = []
|
||||
for i in range(item.rowCount()):
|
||||
|
@ -86,8 +86,8 @@ class plotModel(QStandardItemModel):
|
|||
p = QStandardItem(self.tr("New plot"))
|
||||
_id = QStandardItem(self.getUniqueID())
|
||||
importance = QStandardItem(str(0))
|
||||
self.appendRow([p, _id, importance, QStandardItem("Persos"),
|
||||
QStandardItem(), QStandardItem(), QStandardItem("Subplots")])
|
||||
self.appendRow([p, _id, importance, QStandardItem("Characters"),
|
||||
QStandardItem(), QStandardItem(), QStandardItem("Resolution steps")])
|
||||
|
||||
def getUniqueID(self, parent=QModelIndex()):
|
||||
"""Returns an unused ID"""
|
||||
|
@ -114,9 +114,9 @@ class plotModel(QStandardItemModel):
|
|||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if role == Qt.DisplayRole:
|
||||
if orientation == Qt.Horizontal:
|
||||
if section == Subplot.name.value:
|
||||
if section == PlotStep.name.value:
|
||||
return self.tr("Name")
|
||||
elif section == Subplot.meta.value:
|
||||
elif section == PlotStep.meta.value:
|
||||
return self.tr("Meta")
|
||||
else:
|
||||
return ""
|
||||
|
@ -127,8 +127,8 @@ class plotModel(QStandardItemModel):
|
|||
|
||||
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.steps.value and \
|
||||
index.column() == PlotStep.meta.value:
|
||||
if role == Qt.TextAlignmentRole:
|
||||
return Qt.AlignRight | Qt.AlignVCenter
|
||||
elif role == Qt.ForegroundRole:
|
||||
|
@ -144,13 +144,13 @@ class plotModel(QStandardItemModel):
|
|||
if not index.isValid():
|
||||
return
|
||||
|
||||
parent = index.sibling(index.row(), Plot.subplots.value)
|
||||
parentItem = self.item(index.row(), Plot.subplots.value)
|
||||
parent = index.sibling(index.row(), Plot.steps.value)
|
||||
parentItem = self.item(index.row(), Plot.steps.value)
|
||||
|
||||
if not parentItem:
|
||||
return
|
||||
|
||||
p = QStandardItem(self.tr("New subplot"))
|
||||
p = QStandardItem(self.tr("New step"))
|
||||
_id = QStandardItem(self.getUniqueID(parent))
|
||||
summary = QStandardItem()
|
||||
|
||||
|
@ -182,10 +182,10 @@ class plotModel(QStandardItemModel):
|
|||
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())
|
||||
if not self.item(index.row(), Plot.characters.value):
|
||||
self.setItem(index.row(), Plot.characters.value, QStandardItem())
|
||||
|
||||
item = self.item(index.row(), Plot.persos.value)
|
||||
item = self.item(index.row(), Plot.characters.value)
|
||||
|
||||
# We check that the PersoID is not in the list yet
|
||||
for i in range(item.rowCount()):
|
||||
|
@ -212,13 +212,13 @@ class plotModel(QStandardItemModel):
|
|||
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))
|
||||
for i in range(self.mw.mdlCharacter.rowCount()):
|
||||
a = QAction(self.mw.mdlCharacter.name(i), menu)
|
||||
a.setIcon(self.mw.mdlCharacter.icon(i))
|
||||
a.triggered.connect(mpr.map)
|
||||
mpr.setMapping(a, int(self.mw.mdlPersos.ID(i)))
|
||||
mpr.setMapping(a, int(self.mw.mdlCharacter.ID(i)))
|
||||
|
||||
imp = toInt(self.mw.mdlPersos.importance(i))
|
||||
imp = toInt(self.mw.mdlCharacter.importance(i))
|
||||
|
||||
menus[2 - imp].addAction(a)
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import re
|
|||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from manuskript.enums import Outline
|
||||
from manuskript.enums import Perso
|
||||
from manuskript.enums import Character
|
||||
from manuskript.enums import Plot
|
||||
from manuskript.enums import Subplot
|
||||
from manuskript.enums import PlotStep
|
||||
from manuskript.functions import mainWindow
|
||||
|
||||
RegEx = r"{(\w):(\d+):?.*?}"
|
||||
|
@ -22,7 +22,7 @@ RegExNonCapturing = r"{\w:\d+:?.*?}"
|
|||
# The basic format of the references
|
||||
EmptyRef = "{{{}:{}:{}}}"
|
||||
EmptyRefSearchable = "{{{}:{}:"
|
||||
PersoLetter = "C"
|
||||
CharacterLetter = "C"
|
||||
TextLetter = "T"
|
||||
PlotLetter = "P"
|
||||
WorldLetter = "W"
|
||||
|
@ -37,13 +37,13 @@ def plotReference(ID, searchable=False):
|
|||
return EmptyRefSearchable.format(PlotLetter, ID, "")
|
||||
|
||||
|
||||
def persoReference(ID, searchable=False):
|
||||
def characterReference(ID, searchable=False):
|
||||
"""Takes the ID of a character and returns a reference for that character.
|
||||
@searchable: returns a stripped version that allows simple text search."""
|
||||
if not searchable:
|
||||
return EmptyRef.format(PersoLetter, ID, "")
|
||||
return EmptyRef.format(CharacterLetter, ID, "")
|
||||
else:
|
||||
return EmptyRefSearchable.format(PersoLetter, ID, "")
|
||||
return EmptyRefSearchable.format(CharacterLetter, ID, "")
|
||||
|
||||
|
||||
def textReference(ID, searchable=False):
|
||||
|
@ -103,8 +103,8 @@ def infos(ref):
|
|||
POV = ""
|
||||
if item.POV():
|
||||
POV = "<a href='{ref}'>{text}</a>".format(
|
||||
ref=persoReference(item.POV()),
|
||||
text=mainWindow().mdlPersos.getPersoNameByID(item.POV()))
|
||||
ref=characterReference(item.POV()),
|
||||
text=mainWindow().mdlCharacter.getCharacterByID(item.POV()).name())
|
||||
|
||||
# The status of the scene
|
||||
status = item.status()
|
||||
|
@ -130,7 +130,7 @@ def infos(ref):
|
|||
path = " > ".join(pathStr)
|
||||
|
||||
# Summaries and notes
|
||||
ss = item.data(Outline.summarySentance.value)
|
||||
ss = item.data(Outline.summarySentence.value)
|
||||
ls = item.data(Outline.summaryFull.value)
|
||||
notes = item.data(Outline.notes.value)
|
||||
|
||||
|
@ -167,17 +167,19 @@ def infos(ref):
|
|||
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 "",
|
||||
notes=linkifyAllRefs(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())
|
||||
elif _type == CharacterLetter:
|
||||
m = mainWindow().mdlCharacter
|
||||
c = m.getCharacterByID(int(_ref))
|
||||
index = c.index()
|
||||
|
||||
name = c.name()
|
||||
|
||||
# Titles
|
||||
basicTitle = qApp.translate("references", "Basic infos")
|
||||
|
@ -191,14 +193,16 @@ def infos(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.summaryPara, qApp.translate("references", "Longer summary"), True),
|
||||
(Character.motivation, qApp.translate("references", "Motivation"), False),
|
||||
(Character.goal, qApp.translate("references", "Goal"), False),
|
||||
(Character.conflict, qApp.translate("references", "Conflict"), False),
|
||||
(Character.epiphany, qApp.translate("references", "Epiphany"), False),
|
||||
(Character.summarySentence, qApp.translate("references", "Short summary"), True),
|
||||
(Character.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],
|
||||
|
@ -208,7 +212,7 @@ def infos(ref):
|
|||
|
||||
# detailed infos
|
||||
detailed = []
|
||||
for _name, _val in m.listPersoInfos(index):
|
||||
for _name, _val in c.listInfos():
|
||||
detailed.append("<b>{}:</b> {}".format(
|
||||
_name,
|
||||
_val))
|
||||
|
@ -272,24 +276,24 @@ def infos(ref):
|
|||
Plot.result.value))
|
||||
|
||||
# Characters
|
||||
pM = mainWindow().mdlPersos
|
||||
item = m.item(index.row(), Plot.persos.value)
|
||||
pM = mainWindow().mdlCharacter
|
||||
item = m.item(index.row(), Plot.characters.value)
|
||||
characters = ""
|
||||
if item:
|
||||
for r in range(item.rowCount()):
|
||||
ID = item.child(r, 0).text()
|
||||
characters += "<li><a href='{link}'>{text}</a>".format(
|
||||
link=persoReference(ID),
|
||||
link=characterReference(ID),
|
||||
text=pM.getPersoNameByID(ID))
|
||||
|
||||
# Resolution steps
|
||||
steps = ""
|
||||
item = m.item(index.row(), Plot.subplots.value)
|
||||
item = m.item(index.row(), Plot.steps.value)
|
||||
if item:
|
||||
for r in range(item.rowCount()):
|
||||
title = item.child(r, Subplot.name.value).text()
|
||||
summary = item.child(r, Subplot.summary.value).text()
|
||||
meta = item.child(r, Subplot.meta.value).text()
|
||||
title = item.child(r, PlotStep.name.value).text()
|
||||
summary = item.child(r, PlotStep.summary.value).text()
|
||||
meta = item.child(r, PlotStep.meta.value).text()
|
||||
if meta:
|
||||
meta = " <span style='color:gray;'>({})</span>".format(meta)
|
||||
steps += "<li><b>{title}</b>{summary}{meta}</li>".format(
|
||||
|
@ -373,56 +377,126 @@ def infos(ref):
|
|||
return qApp.translate("references", "Unknown reference: {}.").format(ref)
|
||||
|
||||
|
||||
def tooltip(ref):
|
||||
"""Returns a tooltip in HTML for the reference ``ref``."""
|
||||
def shortInfos(ref):
|
||||
"""Returns infos about reference ``ref``.
|
||||
Returns -1 if ``ref`` is not a valid reference, and None if it is valid but unknown."""
|
||||
match = re.fullmatch(RegEx, ref)
|
||||
|
||||
if not match:
|
||||
return qApp.translate("references", "Not a reference: {}.").format(ref)
|
||||
return -1
|
||||
|
||||
_type = match.group(1)
|
||||
_ref = match.group(2)
|
||||
|
||||
infos = {}
|
||||
infos["ID"] = _ref
|
||||
|
||||
if _type == TextLetter:
|
||||
|
||||
infos["type"] = TextLetter
|
||||
|
||||
m = mainWindow().mdlOutline
|
||||
idx = m.getIndexByID(_ref)
|
||||
|
||||
if not idx.isValid():
|
||||
return qApp.translate("references", "Unknown reference: {}.").format(ref)
|
||||
return None
|
||||
|
||||
item = idx.internalPointer()
|
||||
|
||||
if item.isFolder():
|
||||
tt = qApp.translate("references", "Folder: <b>{}</b>").format(item.title())
|
||||
infos["text_type"] = "folder"
|
||||
else:
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(item.title())
|
||||
tt += "<br><i>{}</i>".format(item.path())
|
||||
infos["text_type"] = "text"
|
||||
|
||||
return tt
|
||||
infos["title"] = item.title()
|
||||
infos["path"] = item.path()
|
||||
return infos
|
||||
|
||||
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 == CharacterLetter:
|
||||
|
||||
infos["type"] = CharacterLetter
|
||||
|
||||
m = mainWindow().mdlCharacter
|
||||
c = m.getCharacterByID(_ref)
|
||||
|
||||
if c:
|
||||
infos["title"] = c.name()
|
||||
infos["name"] = c.name()
|
||||
return infos
|
||||
|
||||
elif _type == PlotLetter:
|
||||
|
||||
infos["type"] = PlotLetter
|
||||
|
||||
m = mainWindow().mdlPlots
|
||||
name = m.getPlotNameByID(_ref)
|
||||
if name:
|
||||
return qApp.translate("references", "Plot: <b>{}</b>").format(name)
|
||||
infos["title"] = name
|
||||
return infos
|
||||
|
||||
elif _type == WorldLetter:
|
||||
|
||||
infos["type"] = WorldLetter
|
||||
|
||||
m = mainWindow().mdlWorld
|
||||
item = m.itemByID(_ref)
|
||||
if item:
|
||||
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 "")
|
||||
infos["title"] = name
|
||||
infos["path"] = path
|
||||
return infos
|
||||
|
||||
return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
|
||||
return None
|
||||
|
||||
|
||||
def title(ref):
|
||||
"""Returns a the title (or name) for the reference ``ref``."""
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1 and "title" in infos:
|
||||
return infos["title"]
|
||||
else:
|
||||
return None
|
||||
|
||||
def type(ref):
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1:
|
||||
return infos["type"]
|
||||
|
||||
def ID(ref):
|
||||
infos = shortInfos(ref)
|
||||
if infos and infos != -1:
|
||||
return infos["ID"]
|
||||
|
||||
def tooltip(ref):
|
||||
"""Returns a tooltip in HTML for the reference ``ref``."""
|
||||
infos = shortInfos(ref)
|
||||
|
||||
if not infos:
|
||||
return qApp.translate("references", "<b>Unknown reference:</b> {}.").format(ref)
|
||||
|
||||
if infos == -1:
|
||||
return qApp.translate("references", "Not a reference: {}.").format(ref)
|
||||
|
||||
|
||||
if infos["type"] == TextLetter:
|
||||
if infos["text_type"] == "folder":
|
||||
tt = qApp.translate("references", "Folder: <b>{}</b>").format(infos["title"])
|
||||
else:
|
||||
tt = qApp.translate("references", "Text: <b>{}</b>").format(infos["title"])
|
||||
tt += "<br><i>{}</i>".format(infos["path"])
|
||||
return tt
|
||||
|
||||
elif infos["type"] == CharacterLetter:
|
||||
return qApp.translate("references", "Character: <b>{}</b>").format(infos["title"])
|
||||
|
||||
elif infos["type"] == PlotLetter:
|
||||
return qApp.translate("references", "Plot: <b>{}</b>").format(infos["title"])
|
||||
|
||||
elif infos["type"] == WorldLetter:
|
||||
return qApp.translate("references", "World: <b>{name}</b>{path}").format(
|
||||
name=infos["title"],
|
||||
path=" <span style='color:gray;'>({})</span>".format(infos["path"]) if infos["path"] else "")
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
@ -446,9 +520,9 @@ def refToLink(ref):
|
|||
item = idx.internalPointer()
|
||||
text = item.title()
|
||||
|
||||
elif _type == PersoLetter:
|
||||
m = mainWindow().mdlPersos
|
||||
text = m.item(int(_ref), Perso.name.value).text()
|
||||
elif _type == CharacterLetter:
|
||||
m = mainWindow().mdlCharacter
|
||||
text = m.getCharacterByID(int(_ref)).name()
|
||||
|
||||
elif _type == PlotLetter:
|
||||
m = mainWindow().mdlPlots
|
||||
|
@ -508,30 +582,6 @@ def listReferences(ref, title=qApp.translate("references", "Referenced in:")):
|
|||
ref=listRefs) if listRefs else ""
|
||||
|
||||
|
||||
def basicT2TFormat(text, formatting=True, EOL=True, titles=True):
|
||||
"""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)
|
||||
r2 = '^\s*{s}([^\+].*[^\+]){s}\s*$'.format(s="\\+" * i)
|
||||
t = "<h{n}>\\1</h{n}>".format(n=i)
|
||||
line = re.sub(r1, t, line)
|
||||
line = re.sub(r2, t, line)
|
||||
text[n] = line
|
||||
text = "\n".join(text)
|
||||
if EOL:
|
||||
text = text.replace("\n", "<br>")
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def basicFormat(text):
|
||||
if not text:
|
||||
return ""
|
||||
|
@ -549,16 +599,16 @@ def open(ref):
|
|||
_type = match.group(1)
|
||||
_ref = match.group(2)
|
||||
|
||||
if _type == PersoLetter:
|
||||
if _type == CharacterLetter:
|
||||
mw = mainWindow()
|
||||
item = mw.lstPersos.getItemByID(_ref)
|
||||
item = mw.lstCharacters.getItemByID(int(_ref))
|
||||
|
||||
if item:
|
||||
mw.tabMain.setCurrentIndex(mw.TabPersos)
|
||||
mw.lstPersos.setCurrentItem(item)
|
||||
mw.lstCharacters.setCurrentItem(item)
|
||||
return True
|
||||
|
||||
print("Ref not found")
|
||||
print("Error: Ref {} not found".format(ref))
|
||||
return False
|
||||
|
||||
elif _type == TextLetter:
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import collections
|
||||
import json
|
||||
import pickle
|
||||
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from manuskript.enums import Outline
|
||||
|
||||
# TODO: move some/all of those settings to application settings and not project settings
|
||||
# in order to allow a shared project between several writers
|
||||
|
||||
viewSettings = {
|
||||
"Tree": {
|
||||
"Icon": "Nothing",
|
||||
|
@ -28,7 +32,8 @@ viewSettings = {
|
|||
"Background": "Nothing",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Application
|
||||
spellcheck = False
|
||||
dict = None
|
||||
corkSizeFactor = 100
|
||||
|
@ -47,7 +52,7 @@ corkBackground = {
|
|||
"color": "#926239",
|
||||
"image": ""
|
||||
}
|
||||
defaultTextType = "t2t"
|
||||
defaultTextType = "md"
|
||||
fullScreenTheme = "spacedreams"
|
||||
|
||||
textEditor = {
|
||||
|
@ -80,12 +85,16 @@ frequencyAnalyzer = {
|
|||
"phraseMin": 2,
|
||||
"phraseMax": 5
|
||||
}
|
||||
|
||||
viewMode = "fiction" # simple, fiction
|
||||
saveToZip = True
|
||||
|
||||
def save(filename=None):
|
||||
def save(filename=None, protocol=None):
|
||||
|
||||
global spellcheck, dict, corkSliderFactor, viewSettings, corkSizeFactor, folderView, lastTab, openIndexes, \
|
||||
autoSave, autoSaveDelay, saveOnQuit, autoSaveNoChanges, autoSaveNoChangesDelay, outlineViewColumns, \
|
||||
corkBackground, fullScreenTheme, defaultTextType, textEditor, revisions, frequencyAnalyzer
|
||||
corkBackground, fullScreenTheme, defaultTextType, textEditor, revisions, frequencyAnalyzer, viewMode, \
|
||||
saveToZip
|
||||
|
||||
allSettings = {
|
||||
"viewSettings": viewSettings,
|
||||
|
@ -106,8 +115,10 @@ def save(filename=None):
|
|||
"defaultTextType":defaultTextType,
|
||||
"textEditor":textEditor,
|
||||
"revisions":revisions,
|
||||
"frequencyAnalyzer": frequencyAnalyzer
|
||||
}
|
||||
"frequencyAnalyzer": frequencyAnalyzer,
|
||||
"viewMode": viewMode,
|
||||
"saveToZip": saveToZip,
|
||||
}
|
||||
|
||||
#pp=pprint.PrettyPrinter(indent=4, compact=False)
|
||||
#print("Saving:")
|
||||
|
@ -117,9 +128,16 @@ def save(filename=None):
|
|||
f = open(filename, "wb")
|
||||
pickle.dump(allSettings, f)
|
||||
else:
|
||||
return pickle.dumps(allSettings)
|
||||
|
||||
def load(string, fromString=False):
|
||||
if protocol == 0:
|
||||
# This looks stupid
|
||||
# But a simple json.dumps with sort_keys will throw a TypeError
|
||||
# because of unorderable types.
|
||||
return json.dumps(json.loads(json.dumps(allSettings)), indent=4, sort_keys=True)
|
||||
else:
|
||||
return pickle.dumps(allSettings)
|
||||
|
||||
|
||||
def load(string, fromString=False, protocol=None):
|
||||
"""Load settings from 'string'. 'string' is the filename of the pickle dump.
|
||||
If fromString=True, string is the data of the pickle dumps."""
|
||||
global allSettings
|
||||
|
@ -133,8 +151,11 @@ def load(string, fromString=False):
|
|||
print("{} doesn't exist, cannot load settings.".format(string))
|
||||
return
|
||||
else:
|
||||
allSettings = pickle.loads(string)
|
||||
|
||||
if protocol == 0:
|
||||
allSettings = json.loads(string)
|
||||
else:
|
||||
allSettings = pickle.loads(string)
|
||||
|
||||
#pp=pprint.PrettyPrinter(indent=4, compact=False)
|
||||
#print("Loading:")
|
||||
#pp.pprint(allSettings)
|
||||
|
@ -211,7 +232,28 @@ def load(string, fromString=False):
|
|||
global revisions
|
||||
revisions = allSettings["revisions"]
|
||||
|
||||
# With JSON we had to convert int keys to str, and None to "null", so we roll back.
|
||||
r = {}
|
||||
for i in revisions["rules"]:
|
||||
if i == "null":
|
||||
r[None] = revisions["rules"]["null"]
|
||||
|
||||
elif i == None:
|
||||
r[None] = revisions["rules"][None]
|
||||
|
||||
else:
|
||||
r[int(i)] = revisions["rules"][i]
|
||||
|
||||
revisions["rules"] = r
|
||||
|
||||
if "frequencyAnalyzer" in allSettings:
|
||||
global frequencyAnalyzer
|
||||
frequencyAnalyzer = allSettings["frequencyAnalyzer"]
|
||||
|
||||
if "viewMode" in allSettings:
|
||||
global viewMode
|
||||
viewMode = allSettings["viewMode"]
|
||||
|
||||
if "saveToZip" in allSettings:
|
||||
global saveToZip
|
||||
saveToZip = allSettings["saveToZip"]
|
|
@ -1,23 +1,26 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
from PyQt5.QtCore import QSize, QSettings, QRegExp
|
||||
from PyQt5.QtCore import QSize, QSettings, QRegExp, QTranslator, QObject
|
||||
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 QStyleFactory, QWidget, QStyle, QColorDialog, QListWidgetItem, QMessageBox
|
||||
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 allPaths, iconColor, writablePath, appPath, findWidgetsOfClass
|
||||
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.outlineView import outlineView
|
||||
from manuskript.ui.views.textEditView import textEditView
|
||||
from manuskript.ui.welcome import welcome
|
||||
|
||||
try:
|
||||
import enchant
|
||||
|
@ -43,6 +46,21 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
self.cmbStyle.setCurrentIndex([i.lower() for i in list(QStyleFactory.keys())].index(qApp.style().objectName()))
|
||||
self.cmbStyle.currentIndexChanged[str].connect(self.setStyle)
|
||||
|
||||
self.cmbTranslation.clear()
|
||||
tr = OrderedDict()
|
||||
tr["English"] = ""
|
||||
tr["Français"] = "manuskript_fr.qm"
|
||||
tr["Español"] = "manuskript_es.qm"
|
||||
|
||||
for name in tr:
|
||||
self.cmbTranslation.addItem(name, tr[name])
|
||||
|
||||
sttgs = QSettings(qApp.organizationName(), qApp.applicationName())
|
||||
if sttgs.contains("applicationTranslation") and sttgs.value("applicationTranslation") in tr.values():
|
||||
self.cmbTranslation.setCurrentText([i for i in tr if tr[i] == sttgs.value("applicationTranslation")][0])
|
||||
|
||||
self.cmbTranslation.currentIndexChanged.connect(self.setTranslation)
|
||||
|
||||
self.txtAutoSave.setValidator(QIntValidator(0, 999, self))
|
||||
self.txtAutoSaveNoChanges.setValidator(QIntValidator(0, 999, self))
|
||||
self.chkAutoSave.setChecked(settings.autoSave)
|
||||
|
@ -50,28 +68,17 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
self.txtAutoSave.setText(str(settings.autoSaveDelay))
|
||||
self.txtAutoSaveNoChanges.setText(str(settings.autoSaveNoChangesDelay))
|
||||
self.chkSaveOnQuit.setChecked(settings.saveOnQuit)
|
||||
self.chkSaveToZip.setChecked(settings.saveToZip)
|
||||
self.chkAutoSave.stateChanged.connect(self.saveSettingsChanged)
|
||||
self.chkAutoSaveNoChanges.stateChanged.connect(self.saveSettingsChanged)
|
||||
self.chkSaveOnQuit.stateChanged.connect(self.saveSettingsChanged)
|
||||
self.chkSaveToZip.stateChanged.connect(self.saveSettingsChanged)
|
||||
self.txtAutoSave.textEdited.connect(self.saveSettingsChanged)
|
||||
self.txtAutoSaveNoChanges.textEdited.connect(self.saveSettingsChanged)
|
||||
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])
|
||||
i = self.cmbDefaultTextType.findData(settings.defaultTextType)
|
||||
if i != -1:
|
||||
self.cmbDefaultTextType.setCurrentIndex(i)
|
||||
self.cmbDefaultTextType.currentIndexChanged.connect(self.saveSettingsChanged)
|
||||
|
||||
# Revisions
|
||||
opt = settings.revisions
|
||||
self.chkRevisionsKeep.setChecked(opt["keep"])
|
||||
|
@ -102,6 +109,8 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
chk.setChecked(col in settings.outlineViewColumns)
|
||||
chk.stateChanged.connect(self.outlineColumnsChanged)
|
||||
|
||||
self.chkOutlinePOV.setVisible(settings.viewMode != "simple") # Hides checkbox if non-fiction view mode
|
||||
|
||||
for item, what, value in [
|
||||
(self.rdoTreeItemCount, "InfoFolder", "Count"),
|
||||
(self.rdoTreeWC, "InfoFolder", "WC"),
|
||||
|
@ -209,6 +218,14 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
sttgs.setValue("applicationStyle", style)
|
||||
qApp.setStyle(style)
|
||||
|
||||
def setTranslation(self, index):
|
||||
path = self.cmbTranslation.currentData()
|
||||
# Save settings
|
||||
sttgs = QSettings(qApp.organizationName(), qApp.applicationName())
|
||||
sttgs.setValue("applicationTranslation", path)
|
||||
|
||||
# QMessageBox.information(self, "Warning", "You'll have to restart manuskript.")
|
||||
|
||||
def saveSettingsChanged(self):
|
||||
if self.txtAutoSave.text() in ["", "0"]:
|
||||
self.txtAutoSave.setText("1")
|
||||
|
@ -222,11 +239,11 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
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
|
||||
settings.saveToZip = True if self.chkSaveToZip.checkState() else False
|
||||
settings.autoSaveDelay = int(self.txtAutoSave.text())
|
||||
settings.autoSaveNoChangesDelay = int(self.txtAutoSaveNoChanges.text())
|
||||
self.mw.saveTimer.setInterval(settings.autoSaveDelay * 60 * 1000)
|
||||
self.mw.saveTimerNoChanges.setInterval(settings.autoSaveNoChangesDelay * 1000)
|
||||
settings.defaultTextType = self.cmbDefaultTextType.currentData()
|
||||
|
||||
####################################################################################################
|
||||
# REVISION #
|
||||
|
@ -267,6 +284,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
item, part = self.viewSettingsDatas()[cmb]
|
||||
element = lst[cmb.currentIndex()]
|
||||
self.mw.setViewSettings(item, part, element)
|
||||
self.mw.generateViewMenu()
|
||||
|
||||
def outlineColumnsData(self):
|
||||
return {
|
||||
|
@ -290,8 +308,8 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
settings.outlineViewColumns.remove(col)
|
||||
|
||||
# Update views
|
||||
self.mw.redacEditor.outlineView.hideColumns()
|
||||
self.mw.treePlanOutline.hideColumns()
|
||||
for w in findWidgetsOfClass(outlineView):
|
||||
w.hideColumns()
|
||||
|
||||
def treeViewSettignsChanged(self):
|
||||
for item, what, value in [
|
||||
|
@ -325,6 +343,7 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
|
||||
def setCorkBackground(self, i):
|
||||
img = self.cmbCorkImage.itemData(i)
|
||||
img = os.path.basename(img)
|
||||
if img:
|
||||
settings.corkBackground["image"] = img
|
||||
else:
|
||||
|
|
|
@ -4,7 +4,7 @@ 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 Character
|
||||
from manuskript.enums import Plot
|
||||
from manuskript.functions import lightBlue
|
||||
from manuskript.functions import mainWindow
|
||||
|
@ -36,7 +36,7 @@ class cheatSheet(QWidget, Ui_cheatSheet):
|
|||
self.line.hide()
|
||||
|
||||
self.outlineModel = None
|
||||
self.persoModel = None
|
||||
self.characterModel = None
|
||||
self.plotModel = None
|
||||
self.worldModel = None
|
||||
|
||||
|
@ -53,12 +53,14 @@ class cheatSheet(QWidget, Ui_cheatSheet):
|
|||
def setModels(self):
|
||||
mw = mainWindow()
|
||||
self.outlineModel = mw.mdlOutline
|
||||
self.persoModel = mw.mdlPersos
|
||||
self.characterModel = mw.mdlCharacter
|
||||
self.plotModel = mw.mdlPlots
|
||||
self.worldModel = mw.mdlWorld
|
||||
|
||||
self.outlineModel.dataChanged.connect(self.populateTimer.start)
|
||||
self.persoModel.dataChanged.connect(self.populateTimer.start)
|
||||
self.characterModel.dataChanged.connect(self.populateTimer.start)
|
||||
self.characterModel.rowsInserted.connect(self.populateTimer.start)
|
||||
self.characterModel.rowsRemoved.connect(self.populateTimer.start)
|
||||
self.plotModel.dataChanged.connect(self.populateTimer.start)
|
||||
self.worldModel.dataChanged.connect(self.populateTimer.start)
|
||||
|
||||
|
@ -75,17 +77,14 @@ class cheatSheet(QWidget, Ui_cheatSheet):
|
|||
self.list.hide()
|
||||
|
||||
def populate(self):
|
||||
if self.persoModel:
|
||||
if self.characterModel:
|
||||
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))
|
||||
for c in self.characterModel.characters:
|
||||
imp = [self.tr("Minor"), self.tr("Secondary"), self.tr("Main")][int(c.importance())]
|
||||
d.append((c.name(), c.ID(), imp))
|
||||
|
||||
self.data[(self.tr("Characters"), Ref.PersoLetter)] = d
|
||||
self.data[(self.tr("Characters"), Ref.CharacterLetter)] = d
|
||||
|
||||
if self.outlineModel:
|
||||
d = []
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QToolBar, QDockWidget, QAction, QToolButton, QSizePolicy, QStylePainter, \
|
||||
QStyleOptionButton, QStyle, QLabel
|
||||
QStyleOptionButton, QStyle
|
||||
|
||||
|
||||
class collapsibleDockWidgets(QToolBar):
|
||||
|
@ -31,6 +31,8 @@ class collapsibleDockWidgets(QToolBar):
|
|||
# self.setAllowedAreas(self.TRANSPOSED_AREA[self._area])
|
||||
self.parent().addToolBar(self.TRANSPOSED_AREA[self._area], self)
|
||||
|
||||
self._dockToButtonAction = {}
|
||||
|
||||
# Dock widgets
|
||||
for d in self._dockWidgets():
|
||||
b = verticalButton(self)
|
||||
|
@ -48,7 +50,8 @@ class collapsibleDockWidgets(QToolBar):
|
|||
background: lightBlue;
|
||||
}
|
||||
""")
|
||||
self.addWidget(b)
|
||||
a = self.addWidget(b)
|
||||
self._dockToButtonAction[d] = a
|
||||
|
||||
self.addSeparator()
|
||||
|
||||
|
@ -88,6 +91,10 @@ class collapsibleDockWidgets(QToolBar):
|
|||
else:
|
||||
action.setVisible(True)
|
||||
|
||||
def setDockVisibility(self, dock, val):
|
||||
dock.setVisible(val)
|
||||
self._dockToButtonAction[dock].setVisible(val)
|
||||
|
||||
def saveState(self):
|
||||
# We just need to save states of the custom widgets.
|
||||
state = []
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/compileDialog_ui.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.4.1
|
||||
# Created: Wed Mar 2 00:30:17 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_compileDialog(object):
|
||||
def setupUi(self, compileDialog):
|
||||
|
|
19
manuskript/ui/editors/MDFunctions.py
Normal file
19
manuskript/ui/editors/MDFunctions.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
|
||||
from PyQt5.QtCore import QRegExp
|
||||
from PyQt5.QtGui import QTextCursor
|
||||
|
||||
|
||||
def MDFormatSelection(editor, style):
|
||||
"""
|
||||
Formats the current selection of ``editor`` in the format given by ``style``,
|
||||
style being:
|
||||
0: bold
|
||||
1: italic
|
||||
2: code
|
||||
"""
|
||||
print("Formatting:", style, " (Unimplemented yet !)")
|
||||
# FIXME
|
130
manuskript/ui/editors/MMDHighlighter.py
Normal file
130
manuskript/ui/editors/MMDHighlighter.py
Normal file
|
@ -0,0 +1,130 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf8 -*-
|
||||
import re
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QTextCharFormat, QFont, QTextCursor, QFontMetrics
|
||||
|
||||
from manuskript.ui.editors.basicHighlighter import basicHighlighter
|
||||
|
||||
|
||||
class MMDHighlighter(basicHighlighter):
|
||||
|
||||
MARKDOWN_REGEX = {
|
||||
'Bold': '(\*\*)(.+?)(\*\*)',
|
||||
'Bold2': '(__)(.+?)(__)',
|
||||
'Italic': '(\*)([^\*].+?[^\*])(\*)',
|
||||
'Italic2': '(_)([^_].+?[^_])(_)',
|
||||
'Title': '^(#+)(\s*)(.*)(#*)',
|
||||
'HTML': '<.+?>',
|
||||
'Blockquotes': '^(> )+.*$',
|
||||
'OrderedList': '^\d+\.\s+',
|
||||
'UnorderedList': '^[\*\+-]\s+',
|
||||
'Code': '^\s{4,}.*$',
|
||||
'Links-inline': '(\[)(.*?)(\])(\()(.*?)(\))',
|
||||
'Links-ref': '(\[)(.*?)(\])\s?(\[)(.*?)(\])',
|
||||
'Links-ref2': '^\s{,3}(\[)(.*?)(\]:)\s+([^\s]*)\s*(.*?)*$',
|
||||
}
|
||||
|
||||
def __init__(self, editor, style="Default"):
|
||||
basicHighlighter.__init__(self, editor)
|
||||
|
||||
self.editor = editor
|
||||
|
||||
self.rules = {}
|
||||
for key in self.MARKDOWN_REGEX:
|
||||
self.rules[key] = re.compile(self.MARKDOWN_REGEX[key])
|
||||
|
||||
def highlightBlock(self, text):
|
||||
basicHighlighter.highlightBlockBefore(self, text)
|
||||
|
||||
self.doHighlightBlock(text)
|
||||
|
||||
basicHighlighter.highlightBlockAfter(self, text)
|
||||
|
||||
def doHighlightBlock(self, text):
|
||||
"""
|
||||
A quick-n-dirty very basic highlighter, that fails in most non-trivial cases. And is ugly.
|
||||
"""
|
||||
|
||||
# Creates textCharFormat
|
||||
cfOperator = QTextCharFormat()
|
||||
cfOperator.setForeground(Qt.lightGray)
|
||||
cfBold = QTextCharFormat()
|
||||
cfBold.setFontWeight(QFont.Bold)
|
||||
cfItalic = QTextCharFormat()
|
||||
cfItalic.setFontItalic(True)
|
||||
|
||||
# Titles (only atx-style, with #, not underlined)
|
||||
defaultSize = self._defaultCharFormat.font().pointSize()
|
||||
r = self.rules["Title"]
|
||||
for m in r.finditer(text):
|
||||
cfOperator.setFontPointSize(defaultSize + 12 - 2 * len(m.group(1)))
|
||||
cfBold.setFontPointSize(defaultSize + 12 - 2 * len(m.group(1)))
|
||||
|
||||
self.setFormat(m.start(1), len(m.group(1)), cfOperator)
|
||||
self.setFormat(m.start(3), len(m.group(3)), cfBold)
|
||||
self.setFormat(m.start(4), len(m.group(4)), cfOperator)
|
||||
|
||||
# Code blocks
|
||||
r = self.rules["Code"]
|
||||
format = QTextCharFormat()
|
||||
format.setForeground(Qt.darkGray)
|
||||
format.setFontFixedPitch(True)
|
||||
for m in r.finditer(text):
|
||||
self.setFormat(m.start(), m.end() - m.start(), format)
|
||||
|
||||
# Basic stuff
|
||||
stuff = [
|
||||
("Blockquotes", Qt.blue),
|
||||
("OrderedList", Qt.red),
|
||||
("UnorderedList", Qt.darkRed),
|
||||
("HTML", Qt.darkGreen),
|
||||
]
|
||||
for name, color in stuff:
|
||||
r = self.rules[name]
|
||||
format = QTextCharFormat()
|
||||
format.setForeground(color)
|
||||
for m in r.finditer(text):
|
||||
self.setFormat(m.start(), m.end() - m.start(), format)
|
||||
|
||||
# Bold and Italic
|
||||
for name, style in [
|
||||
("Italic", cfItalic),
|
||||
("Italic2", cfItalic),
|
||||
("Bold", cfBold),
|
||||
("Bold2", cfBold),
|
||||
]:
|
||||
r = self.rules[name]
|
||||
|
||||
for m in r.finditer(text):
|
||||
self.setFormat(m.start(1), len(m.group(1)), cfOperator)
|
||||
self.setFormat(m.start(2), len(m.group(2)), style)
|
||||
self.setFormat(m.start(3), len(m.group(3)), cfOperator)
|
||||
|
||||
# Links
|
||||
cfURL = QTextCharFormat()
|
||||
cfURL.setForeground(Qt.darkGreen)
|
||||
cfURL.setFontItalic(True)
|
||||
cfText = QTextCharFormat()
|
||||
cfText.setForeground(Qt.darkBlue)
|
||||
cfIdentifier = QTextCharFormat()
|
||||
cfIdentifier.setForeground(Qt.darkMagenta)
|
||||
|
||||
for type in ['Links-inline', 'Links-ref']:
|
||||
r = self.rules[type]
|
||||
for m in r.finditer(text):
|
||||
self.setFormat(m.start(1), len(m.group(1)), cfOperator)
|
||||
self.setFormat(m.start(2), len(m.group(2)), cfText)
|
||||
self.setFormat(m.start(3), len(m.group(3)), cfOperator)
|
||||
self.setFormat(m.start(4), len(m.group(4)), cfOperator)
|
||||
self.setFormat(m.start(5), len(m.group(5)), cfURL if "inline" in type else cfIdentifier)
|
||||
self.setFormat(m.start(6), len(m.group(6)), cfOperator)
|
||||
|
||||
r = self.rules["Links-ref2"]
|
||||
for m in r.finditer(text):
|
||||
self.setFormat(m.start(1), len(m.group(1)), cfOperator)
|
||||
self.setFormat(m.start(2), len(m.group(2)), cfIdentifier)
|
||||
self.setFormat(m.start(3), len(m.group(3)), cfOperator)
|
||||
self.setFormat(m.start(4), len(m.group(4)), cfURL)
|
||||
self.setFormat(m.start(5), len(m.group(5)), cfText)
|
|
@ -61,7 +61,7 @@ class basicHighlighter(QSyntaxHighlighter):
|
|||
fmt.setFontWeight(QFont.DemiBold)
|
||||
if txt.group(1) == Ref.TextLetter:
|
||||
fmt.setBackground(QBrush(QColor(Qt.blue).lighter(190)))
|
||||
elif txt.group(1) == Ref.PersoLetter:
|
||||
elif txt.group(1) == Ref.CharacterLetter:
|
||||
fmt.setBackground(QBrush(QColor(Qt.yellow).lighter(170)))
|
||||
elif txt.group(1) == Ref.PlotLetter:
|
||||
fmt.setBackground(QBrush(QColor(Qt.red).lighter(170)))
|
||||
|
|
|
@ -107,7 +107,7 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
|
|||
autoResize=True)
|
||||
edt.setFrameShape(QFrame.NoFrame)
|
||||
edt.setStyleSheet("background: {};".format(settings.textEditor["background"]))
|
||||
edt.setStatusTip("{} ({})".format(itm.path(), itm.type()))
|
||||
edt.setStatusTip("{}".format(itm.path()))
|
||||
self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC)
|
||||
self.dictChanged.connect(edt.setDict, AUC)
|
||||
# edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||
|
@ -173,7 +173,7 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
|
|||
|
||||
elif item and item.isFolder() and self.folderView == "outline":
|
||||
self.stack.setCurrentIndex(3)
|
||||
self.outlineView.setModelPersos(mainWindow().mdlPersos)
|
||||
self.outlineView.setModelCharacters(mainWindow().mdlCharacter)
|
||||
self.outlineView.setModelLabels(mainWindow().mdlLabels)
|
||||
self.outlineView.setModelStatus(mainWindow().mdlStatus)
|
||||
self.outlineView.setModel(self.mw.mdlOutline)
|
||||
|
|
|
@ -94,8 +94,13 @@ class fullScreenEditor(QWidget):
|
|||
lst = [i for i in os.listdir(p) if os.path.splitext(i)[1] == ".theme"]
|
||||
for t in lst:
|
||||
themeIni = os.path.join(p, t)
|
||||
self.lstThemes.addItem(os.path.splitext(t)[0])
|
||||
self.lstThemes.setCurrentText(settings.fullScreenTheme)
|
||||
name = loadThemeDatas(themeIni)["Name"]
|
||||
# self.lstThemes.addItem(os.path.splitext(t)[0])
|
||||
self.lstThemes.addItem(name)
|
||||
self.lstThemes.setItemData(self.lstThemes.count()-1, os.path.splitext(t)[0])
|
||||
|
||||
self.lstThemes.setCurrentIndex(self.lstThemes.findData(settings.fullScreenTheme))
|
||||
# self.lstThemes.setCurrentText(settings.fullScreenTheme)
|
||||
self.lstThemes.currentTextChanged.connect(self.setTheme)
|
||||
self.lstThemes.setMaximumSize(QSize(300, QFontMetrics(qApp.font()).height()))
|
||||
self.bottomPanel.layout().addWidget(QLabel(self.tr("Theme:"), self))
|
||||
|
@ -125,6 +130,7 @@ class fullScreenEditor(QWidget):
|
|||
self.btnClose.setVisible(not val)
|
||||
|
||||
def setTheme(self, themeName):
|
||||
themeName = self.lstThemes.currentData()
|
||||
settings.fullScreenTheme = themeName
|
||||
self._theme = findThemePath(themeName)
|
||||
self._themeDatas = loadThemeDatas(self._theme)
|
||||
|
|
|
@ -78,11 +78,15 @@ class mainEditor(QWidget, Ui_mainEditor):
|
|||
self.updateThingsVisible(index)
|
||||
|
||||
def closeTab(self, index):
|
||||
# FIXME: submit data if textedit?
|
||||
w = self.tab.widget(index)
|
||||
self.tab.removeTab(index)
|
||||
w.setCurrentModelIndex(QModelIndex())
|
||||
w.deleteLater()
|
||||
|
||||
def closeAllTabs(self):
|
||||
while(self.tab.count()):
|
||||
self.closeTab(0)
|
||||
|
||||
def allTabs(self):
|
||||
return [self.tab.widget(i) for i in range(self.tab.count())]
|
||||
|
||||
|
|
|
@ -1,376 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
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``,
|
||||
style being:
|
||||
0: bold
|
||||
1: italic
|
||||
2: underline
|
||||
3: strike
|
||||
4: code
|
||||
5: tagged
|
||||
"""
|
||||
print("Formatting:", style)
|
||||
formatChar = "*/_-`'"[style]
|
||||
|
||||
# FIXME: doesn't work if selection spans over several blocks.
|
||||
|
||||
cursor = editor.textCursor()
|
||||
cursor.beginEditBlock()
|
||||
|
||||
if cursor.hasSelection():
|
||||
pass
|
||||
else:
|
||||
# If no selection, selects the word in which the cursor is now
|
||||
cursor.movePosition(QTextCursor.StartOfWord,
|
||||
QTextCursor.MoveAnchor)
|
||||
cursor.movePosition(QTextCursor.EndOfWord,
|
||||
QTextCursor.KeepAnchor)
|
||||
|
||||
if not cursor.hasSelection():
|
||||
# No selection means we are outside a word,
|
||||
# so we insert markup and put cursor in the middle
|
||||
cursor.insertText(formatChar * 4)
|
||||
cursor.setPosition(cursor.position() - 2)
|
||||
cursor.endEditBlock()
|
||||
editor.setTextCursor(cursor)
|
||||
# And we are done
|
||||
return
|
||||
|
||||
# Get start and end of selection
|
||||
start = cursor.selectionStart() - cursor.block().position()
|
||||
end = cursor.selectionEnd() - cursor.block().position()
|
||||
if start > end:
|
||||
start, end = end, start
|
||||
|
||||
# Whole block
|
||||
text = cursor.block().text()
|
||||
|
||||
# Adjusts selection to exclude the markup
|
||||
while text[start:start + 1] == formatChar:
|
||||
start += 1
|
||||
while text[end - 1:end] == formatChar:
|
||||
end -= 1
|
||||
|
||||
# Get the text without formatting, and the array of format
|
||||
fText, fArray = textToFormatArrayNoMarkup(text)
|
||||
# Get the translated start and end of selection in the unformated text
|
||||
tStart, tEnd = translateSelectionToUnformattedText(text, start, end)
|
||||
|
||||
# We want only the array that contains the propper formatting
|
||||
propperArray = fArray[style]
|
||||
|
||||
if 0 in propperArray[tStart:tEnd]:
|
||||
# have some unformated text in the selection, so we format the
|
||||
# whole selection
|
||||
propperArray = propperArray[:tStart] + [1] * \
|
||||
(tEnd - tStart) + propperArray[tEnd:]
|
||||
else:
|
||||
# The whole selection is already formatted, so we remove the
|
||||
# formatting
|
||||
propperArray = propperArray[:tStart] + [0] * \
|
||||
(tEnd - tStart) + propperArray[tEnd:]
|
||||
|
||||
fArray = fArray[0:style] + [propperArray] + fArray[style + 1:]
|
||||
|
||||
text = reformatText(fText, fArray)
|
||||
|
||||
# Replaces the whole block
|
||||
cursor.movePosition(QTextCursor.StartOfBlock)
|
||||
cursor.movePosition(QTextCursor.EndOfBlock,
|
||||
QTextCursor.KeepAnchor)
|
||||
cursor.insertText(text)
|
||||
|
||||
cursor.setPosition(end + cursor.block().position())
|
||||
|
||||
cursor.endEditBlock()
|
||||
|
||||
editor.setTextCursor(cursor)
|
||||
|
||||
|
||||
def t2tClearFormat(editor):
|
||||
"""Clears format on ``editor``'s current selection."""
|
||||
|
||||
cursor = editor.textCursor()
|
||||
cursor.beginEditBlock()
|
||||
|
||||
text = cursor.selectedText()
|
||||
t, a = textToFormatArrayNoMarkup(text)
|
||||
|
||||
cursor.insertText(t)
|
||||
cursor.endEditBlock()
|
||||
editor.setTextCursor(cursor)
|
||||
|
||||
|
||||
def textToFormatArray(text):
|
||||
"""
|
||||
Take some text and returns an array of array containing informations
|
||||
about how the text is formatted:
|
||||
r = [ [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1],
|
||||
...
|
||||
]
|
||||
Each sub-array is for one of the beautifier:
|
||||
0: bold
|
||||
1: italic
|
||||
2: underline
|
||||
3: strike
|
||||
4: code
|
||||
5: tagged
|
||||
|
||||
Each sub-array contains an element for each character of the text, with the
|
||||
value 1 if it is formatted in the specific format, -1 if it is markup, and
|
||||
0 otherwise.
|
||||
|
||||
removeMarks returns a both the array and a string, in which all of the
|
||||
formatting marks have been removed.
|
||||
"""
|
||||
|
||||
result = []
|
||||
|
||||
for markup in ["\*", "/", "_", "-", "`", "\'"]:
|
||||
|
||||
rList = []
|
||||
|
||||
r = QRegExp(r'(' + markup * 2 + ')(.+)(' + markup * 2 + ')')
|
||||
r.setMinimal(True)
|
||||
pos = r.indexIn(text, 0)
|
||||
lastPos = 0
|
||||
while pos >= 0:
|
||||
# We have a winner
|
||||
rList += [0] * (pos - lastPos)
|
||||
rList += [2] * 2
|
||||
rList += [1] * len(r.cap(2))
|
||||
rList += [2] * 2
|
||||
lastPos = pos + len(r.cap(0))
|
||||
pos = r.indexIn(text, len(rList))
|
||||
|
||||
if len(rList) < len(text):
|
||||
rList += [0] * (len(text) - len(rList))
|
||||
|
||||
result.append(rList)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def textToFormatArrayNoMarkup(text):
|
||||
"""
|
||||
Same as textToFormatArray, except that it removes all the markup from the
|
||||
text and returns two elements:
|
||||
the array
|
||||
the text without markup
|
||||
"""
|
||||
|
||||
r = textToFormatArray(text)
|
||||
result = [[], [], [], [], [], []]
|
||||
rText = ""
|
||||
|
||||
for i in range(len(text)):
|
||||
t = max([k[i] for k in r]) # kind of flattens all the format array
|
||||
if t != 2:
|
||||
rText += text[i]
|
||||
[result[k].append(r[k][i]) for k in range(len(r))]
|
||||
|
||||
return rText, result
|
||||
|
||||
|
||||
def translateSelectionToUnformattedText(text, start, end):
|
||||
"""
|
||||
Translate the start / end of selection from a formatted text to an
|
||||
unformatted one.
|
||||
"""
|
||||
r = textToFormatArray(text)
|
||||
|
||||
rStart, rEnd = start, end
|
||||
|
||||
for i in range(len(text)):
|
||||
t = max([k[i] for k in r]) # kind of flattens all the format array
|
||||
if t == 2: # t == 2 means this character is markup
|
||||
if i <= start: rStart -= 1
|
||||
if i < end: rEnd -= 1
|
||||
|
||||
return rStart, rEnd
|
||||
|
||||
|
||||
def translateSelectionToFormattedText(text, start, end):
|
||||
"""
|
||||
Translate the start / end of selection from a formatted text to an
|
||||
unformatted one.
|
||||
"""
|
||||
r = textToFormatArray(text)
|
||||
|
||||
rStart, rEnd = start, end
|
||||
|
||||
for i in range(len(text)):
|
||||
t = max([k[i] for k in r]) # kind of flattens all the format array
|
||||
if t == 2: # t == 2 means this character is markup
|
||||
if i <= start: rStart -= 1
|
||||
if i < end: rEnd -= 1
|
||||
|
||||
return rStart, rEnd
|
||||
|
||||
|
||||
def printArray(array):
|
||||
print(("".join([str(j) for j in array])))
|
||||
|
||||
|
||||
def printArrays(arrays):
|
||||
for i in arrays: printArray(i)
|
||||
|
||||
|
||||
def reformatText(text, markupArray):
|
||||
"""
|
||||
Takes a text without formatting markup, and an array generated by
|
||||
textToFormatArray, and adds the propper markup.
|
||||
"""
|
||||
|
||||
rText = ""
|
||||
markup = ["**", "//", "__", "--", "``", "''"]
|
||||
|
||||
for k, m in enumerate(markupArray):
|
||||
# m = markupArray[k]
|
||||
_open = False # Are we in an _openned markup
|
||||
d = 0
|
||||
alreadySeen = []
|
||||
for i, t in enumerate(text):
|
||||
insert = False
|
||||
if not _open and m[i] == 1:
|
||||
insert = True
|
||||
_open = True
|
||||
|
||||
if _open and m[i] == 0:
|
||||
insert = True
|
||||
_open = False
|
||||
if _open and m[i] > 1:
|
||||
z = i
|
||||
while m[z] == m[i]: z += 1
|
||||
if m[z] != 1 and not m[i] in alreadySeen:
|
||||
insert = True
|
||||
_open = False
|
||||
alreadySeen.append(m[i])
|
||||
if insert:
|
||||
rText += markup[k]
|
||||
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.
|
||||
m2.insert(i + d, k + 2)
|
||||
m2.insert(i + d, k + 2)
|
||||
alreadySeen = []
|
||||
d += 2
|
||||
rText += t
|
||||
if _open:
|
||||
rText += markup[k]
|
||||
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.
|
||||
m2.insert(i + d, k + 2)
|
||||
m2.insert(i + d, k + 2)
|
||||
text = rText
|
||||
rText = ""
|
||||
|
||||
# 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")
|
||||
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")
|
||||
text = re.sub(r'(' + markup * 2 + ')(.+?)(\s+?)(' + markup * 2 + ')',
|
||||
"\\1\\2\\4\\3",
|
||||
text)
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def cleanFormat(text):
|
||||
"""Makes markup clean (removes doubles, etc.)"""
|
||||
t, a = textToFormatArrayNoMarkup(text)
|
||||
return reformatText(t, a)
|
||||
|
||||
|
||||
class State:
|
||||
NORMAL = 0
|
||||
TITLE_1 = 1
|
||||
TITLE_2 = 2
|
||||
TITLE_3 = 3
|
||||
TITLE_4 = 4
|
||||
TITLE_5 = 5
|
||||
NUMBERED_TITLE_1 = 6
|
||||
NUMBERED_TITLE_2 = 7
|
||||
NUMBERED_TITLE_3 = 8
|
||||
NUMBERED_TITLE_4 = 9
|
||||
NUMBERED_TITLE_5 = 10
|
||||
TITLES = [TITLE_1, TITLE_2, TITLE_3, TITLE_4, TITLE_5, NUMBERED_TITLE_1,
|
||||
NUMBERED_TITLE_2, NUMBERED_TITLE_3, NUMBERED_TITLE_4,
|
||||
NUMBERED_TITLE_5]
|
||||
# AREA
|
||||
COMMENT_AREA = 11
|
||||
CODE_AREA = 12
|
||||
RAW_AREA = 13
|
||||
TAGGED_AREA = 14
|
||||
# AREA MARKUP
|
||||
COMMENT_AREA_BEGINS = 15
|
||||
COMMENT_AREA_ENDS = 16
|
||||
CODE_AREA_BEGINS = 17
|
||||
CODE_AREA_ENDS = 18
|
||||
RAW_AREA_BEGINS = 19
|
||||
RAW_AREA_ENDS = 20
|
||||
TAGGED_AREA_BEGINS = 21
|
||||
TAGGED_AREA_ENDS = 22
|
||||
# LINE
|
||||
COMMENT_LINE = 30
|
||||
CODE_LINE = 31
|
||||
RAW_LINE = 32
|
||||
TAGGED_LINE = 33
|
||||
SETTINGS_LINE = 34
|
||||
BLOCKQUOTE_LINE = 35
|
||||
HORIZONTAL_LINE = 36
|
||||
HEADER_LINE = 37
|
||||
# LIST
|
||||
LIST_BEGINS = 40
|
||||
LIST_ENDS = 41
|
||||
LIST_EMPTY = 42
|
||||
LIST_BULLET = 43
|
||||
LIST_BULLET_ENDS = 44
|
||||
LIST = [40, 41, 42] + list(range(100, 201))
|
||||
# TABLE
|
||||
TABLE_LINE = 50
|
||||
TABLE_HEADER = 51
|
||||
# OTHER
|
||||
MARKUP = 60
|
||||
LINKS = 61
|
||||
MACRO = 62
|
||||
DEFAULT = 63
|
||||
|
||||
@staticmethod
|
||||
def titleLevel(state):
|
||||
"""
|
||||
Returns the level of the title, from the block state.
|
||||
"""
|
||||
return {
|
||||
State.TITLE_1: 1,
|
||||
State.TITLE_2: 2,
|
||||
State.TITLE_3: 3,
|
||||
State.TITLE_4: 4,
|
||||
State.TITLE_5: 5,
|
||||
State.NUMBERED_TITLE_1: 1,
|
||||
State.NUMBERED_TITLE_2: 2,
|
||||
State.NUMBERED_TITLE_3: 3,
|
||||
State.NUMBERED_TITLE_4: 4,
|
||||
State.NUMBERED_TITLE_5: 5,
|
||||
}.get(state, -1)
|
|
@ -1,547 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
|
||||
# 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.
|
||||
|
||||
# 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):
|
||||
"""Syntax highlighter for the Txt2Tags language.
|
||||
"""
|
||||
|
||||
def __init__(self, editor, style="Default"):
|
||||
basicHighlighter.__init__(self, editor)
|
||||
|
||||
# Stupid variable that fixes the loss of QTextBlockUserData.
|
||||
self.thisDocument = editor.document()
|
||||
|
||||
self.style = t2tHighlighterStyle(self.editor, self._defaultCharFormat, style)
|
||||
|
||||
self.inDocRules = []
|
||||
|
||||
rules = [
|
||||
(r'^\s*[-=_]{20,}\s*$', State.HORIZONTAL_LINE),
|
||||
(r'^\s*(\+{1})([^\+].*[^\+])(\+{1})(\[[A-Za-z0-9_-]*\])?\s*$', State.NUMBERED_TITLE_1),
|
||||
(r'^\s*(\+{2})([^\+].*[^\+])(\+{2})(\[[A-Za-z0-9_-]*\])?\s*$', State.NUMBERED_TITLE_2),
|
||||
(r'^\s*(\+{3})([^\+].*[^\+])(\+{3})(\[[A-Za-z0-9_-]*\])?\s*$', State.NUMBERED_TITLE_3),
|
||||
(r'^\s*(\+{4})([^\+].*[^\+])(\+{4})(\[[A-Za-z0-9_-]*\])?\s*$', State.NUMBERED_TITLE_4),
|
||||
(r'^\s*(\+{5})([^\+].*[^\+])(\+{5})(\[[A-Za-z0-9_-]*\])?\s*$', State.NUMBERED_TITLE_5),
|
||||
(r'^\s*(={1})([^=].*[^=])(={1})(\[[A-Za-z0-9_-]*\])?\s*$', State.TITLE_1),
|
||||
(r'^\s*(={2})([^=].*[^=])(={2})(\[[A-Za-z0-9_-]*\])?\s*$', State.TITLE_2),
|
||||
(r'^\s*(={3})([^=].*[^=])(={3})(\[[A-Za-z0-9_-]*\])?\s*$', State.TITLE_3),
|
||||
(r'^\s*(={4})([^=].*[^=])(={4})(\[[A-Za-z0-9_-]*\])?\s*$', State.TITLE_4),
|
||||
(r'^\s*(={5})([^=].*[^=])(={5})(\[[A-Za-z0-9_-]*\])?\s*$', State.TITLE_5),
|
||||
(r'^%!.*$', State.SETTINGS_LINE),
|
||||
(r'^%[^!]?.*$', State.COMMENT_LINE),
|
||||
(r'^\t.+$', State.BLOCKQUOTE_LINE),
|
||||
(r'^(```)(.+)$', State.CODE_LINE),
|
||||
(r'^(""")(.+)$', State.RAW_LINE),
|
||||
(r'^(\'\'\')(.+)$', State.TAGGED_LINE),
|
||||
(r'^\s*[-+:] [^ ].*$', State.LIST_BEGINS),
|
||||
(r'^\s*[-+:]\s*$', State.LIST_ENDS),
|
||||
(r'^ *\|\| .*$', State.TABLE_HEADER),
|
||||
(r'^ *\| .*$', State.TABLE_LINE)
|
||||
]
|
||||
|
||||
# Generate rules to identify blocks
|
||||
State.Rules = [(QRegExp(pattern), state)
|
||||
for (pattern, state) in rules]
|
||||
State.Recursion = 0
|
||||
|
||||
def setDefaultCharFormat(self, cf):
|
||||
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)
|
||||
|
||||
state = blockUserData.getUserState(block)
|
||||
data = blockUserData.getUserData(block)
|
||||
inList = self.isList(block)
|
||||
|
||||
op = self.style.format(State.MARKUP)
|
||||
|
||||
# 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
|
||||
for r in rlist:
|
||||
if r.indexIn(text) != -1:
|
||||
self.parseInDocRules()
|
||||
|
||||
# Format the whole line:
|
||||
for lineState in [
|
||||
State.BLOCKQUOTE_LINE,
|
||||
State.HORIZONTAL_LINE,
|
||||
State.HEADER_LINE,
|
||||
]:
|
||||
if not inList and state == lineState:
|
||||
self.setFormat(0, len(text), self.style.format(lineState))
|
||||
|
||||
for (lineState, marker) in [
|
||||
(State.COMMENT_LINE, "%"),
|
||||
(State.CODE_LINE, "```"),
|
||||
(State.RAW_LINE, "\"\"\""),
|
||||
(State.TAGGED_LINE, "'''"),
|
||||
(State.SETTINGS_LINE, "%!")
|
||||
]:
|
||||
if state == lineState and \
|
||||
not (inList and state == State.SETTINGS_LINE):
|
||||
n = 0
|
||||
# If it's a comment, we want to highlight all '%'.
|
||||
if state == State.COMMENT_LINE:
|
||||
while text[n:n + 1] == "%":
|
||||
n += 1
|
||||
n -= 1
|
||||
|
||||
# Apply Format
|
||||
self.setFormat(0, len(marker) + n, op)
|
||||
self.setFormat(len(marker) + n,
|
||||
len(text) - len(marker) - n,
|
||||
self.style.format(lineState))
|
||||
|
||||
# If it's a setting, we might do something
|
||||
if state == State.SETTINGS_LINE:
|
||||
# Target
|
||||
r = QRegExp(r'^%!([^\s]+)\s*:\s*(\b\w*\b)$')
|
||||
if r.indexIn(text) != -1:
|
||||
setting = r.cap(1)
|
||||
val = r.cap(2)
|
||||
if setting == "target" and \
|
||||
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:
|
||||
p = r.pos(1)
|
||||
length = len(r.cap(1))
|
||||
self.setFormat(p, length, self.style.makeFormat(base=self.format(p),
|
||||
fixedPitch=True))
|
||||
|
||||
# Tables
|
||||
for lineState in [State.TABLE_LINE, State.TABLE_HEADER]:
|
||||
if state == lineState:
|
||||
for i, t in enumerate(text):
|
||||
if t == "|":
|
||||
self.setFormat(i, 1, op)
|
||||
else:
|
||||
self.setFormat(i, 1, self.style.format(lineState))
|
||||
|
||||
# Lists
|
||||
# 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_ENDS:
|
||||
self.setFormat(0, len(text), self.style.format(State.LIST_BULLET_ENDS))
|
||||
|
||||
# Titles
|
||||
if not inList and state in State.TITLES:
|
||||
r = [i for (i, s) in State.Rules if s == state][0]
|
||||
pos = r.indexIn(text)
|
||||
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))
|
||||
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)
|
||||
|
||||
# Areas: comment, code, raw tagged
|
||||
for (begins, middle, ends) in [
|
||||
(State.COMMENT_AREA_BEGINS, State.COMMENT_AREA, State.COMMENT_AREA_ENDS),
|
||||
(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))
|
||||
elif state in [begins, ends]:
|
||||
self.setFormat(0, len(text), op)
|
||||
|
||||
# Inline formatting
|
||||
if state not in [
|
||||
# State.COMMENT_AREA,
|
||||
# State.COMMENT_LINE,
|
||||
State.RAW_AREA,
|
||||
State.RAW_LINE,
|
||||
State.CODE_AREA,
|
||||
State.CODE_LINE,
|
||||
State.TAGGED_AREA,
|
||||
State.TAGGED_LINE,
|
||||
State.SETTINGS_LINE,
|
||||
State.HORIZONTAL_LINE,
|
||||
] and state not in State.TITLES:
|
||||
formatArray = textToFormatArray(text)
|
||||
|
||||
# InDocRules
|
||||
for (r, c) in self.inDocRules:
|
||||
i = re.finditer(r.decode('utf8'), text, re.UNICODE)
|
||||
for m in i:
|
||||
f = self.format(m.start())
|
||||
l = m.end() - m.start()
|
||||
if "," in c:
|
||||
c1, c2 = c.split(",")
|
||||
self.setFormat(m.start(), l,
|
||||
self.style.makeFormat(color=c1, bgcolor=c2, base=f))
|
||||
else:
|
||||
self.setFormat(m.start(), l,
|
||||
self.style.makeFormat(color=c, base=f))
|
||||
|
||||
# Links
|
||||
if state not in [State.COMMENT_LINE, State.COMMENT_AREA]:
|
||||
r = QRegExp(r'\[(\[[^\]]*\])?[^\]]*\s*([^\s]+)\]')
|
||||
r.setMinimal(False)
|
||||
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:
|
||||
self.setFormat(pos, 1,
|
||||
self.style.format(State.MARKUP))
|
||||
self.setFormat(pos + 1, len(r.cap(0)) - 1,
|
||||
self.style.format(State.LINKS))
|
||||
self.setFormat(pos + len(r.cap(0)) - 1, 1,
|
||||
self.style.format(State.MARKUP))
|
||||
if r.pos(2) > 0:
|
||||
_f = QTextCharFormat(self.style.format(State.LINKS))
|
||||
_f.setForeground(QBrush(_f.foreground()
|
||||
.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)
|
||||
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)
|
||||
pos = r.indexIn(text)
|
||||
while pos >= 0:
|
||||
for k in links:
|
||||
# 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
|
||||
for i, t in enumerate(text):
|
||||
f = self.format(i)
|
||||
beautifiers = [k[i] for k in formatArray]
|
||||
self.setFormat(i, 1, self.style.beautifyFormat(f, beautifiers))
|
||||
|
||||
# Macro words
|
||||
for r in [r'(%%)\b\w+\b', r'(%%)\b\w+\b\(.+\)']:
|
||||
r = QRegExp(r)
|
||||
r.setMinimal(True)
|
||||
pos = r.indexIn(text)
|
||||
while pos >= 0:
|
||||
if max([k[pos] for k in formatArray]) == 0:
|
||||
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)
|
||||
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)
|
||||
|
||||
## 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):
|
||||
"""Identifies what block type it is, and set userState and userData
|
||||
accordingly."""
|
||||
|
||||
text = block.text()
|
||||
data = blockUserData.getUserData(block)
|
||||
|
||||
# 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
|
||||
|
||||
state = 0
|
||||
inList = False
|
||||
blankLinesBefore = 0
|
||||
|
||||
# if text.contains(QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$')):
|
||||
if QRegExp(r'^\s*[-+:] [^ ].*[^-+]{1}\s*$').indexIn(text) != -1:
|
||||
state = State.LIST_BEGINS
|
||||
|
||||
# List stuff
|
||||
if self.isList(block.previous()) or state == State.LIST_BEGINS:
|
||||
inList = True
|
||||
|
||||
# listLevel and leadingSpaces
|
||||
# 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.
|
||||
# We need to check if this is the same level, or a sublist
|
||||
if leadingSpaces > lastData.leadingSpaces():
|
||||
# This is a sublevel list
|
||||
data.setListLevel(lastData.listLevel() + 1)
|
||||
else:
|
||||
# This is same level
|
||||
data.setListLevel(lastData.listLevel())
|
||||
else:
|
||||
data.setListLevel(1)
|
||||
else:
|
||||
data.setListLevel(lastData.listLevel())
|
||||
data.setLeadingSpaces(lastData.leadingSpaces())
|
||||
data.setListSymbol(lastData.listSymbol())
|
||||
|
||||
# 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]:
|
||||
blankLinesBefore = 0
|
||||
elif not blockUserData.getUserState(block.previous()) in \
|
||||
[State.COMMENT_LINE, State.COMMENT_AREA,
|
||||
State.COMMENT_AREA_BEGINS, State.COMMENT_AREA_ENDS]:
|
||||
blankLinesBefore += 1
|
||||
if blankLinesBefore == 2:
|
||||
# End of list.
|
||||
blankLinesBefore = 0
|
||||
inList = False
|
||||
if inList and QRegExp(r'^\s*$').indexIn(text) != -1:
|
||||
state = State.LIST_EMPTY
|
||||
|
||||
# Areas
|
||||
for (begins, middle, ends, marker) in [
|
||||
(State.COMMENT_AREA_BEGINS, State.COMMENT_AREA, State.COMMENT_AREA_ENDS, "^%%%\s*$"),
|
||||
(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]:
|
||||
state = ends
|
||||
break
|
||||
else:
|
||||
state = begins
|
||||
break
|
||||
if blockUserData.getUserState(block.previous()) in [middle, begins]:
|
||||
state = middle
|
||||
break
|
||||
|
||||
# Patterns (for lines)
|
||||
if not state:
|
||||
for (pattern, lineState) in State.Rules:
|
||||
pos = pattern.indexIn(text)
|
||||
if pos >= 0:
|
||||
state = lineState
|
||||
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.
|
||||
inList = False
|
||||
|
||||
if inList and not state == State.LIST_BEGINS:
|
||||
state += 100
|
||||
if blankLinesBefore:
|
||||
state += 100
|
||||
|
||||
block.setUserState(state)
|
||||
block.setUserData(data)
|
||||
|
||||
def formatBlock(self, block):
|
||||
"""
|
||||
Formats the block according to its state.
|
||||
"""
|
||||
# TODO: Use QTextDocument format presets, and QTextBlock's
|
||||
# TODO: blockFormatIndex. And move that in t2tHighlighterStyle.
|
||||
state = block.userState()
|
||||
blockFormat = QTextBlockFormat()
|
||||
|
||||
if state in [State.BLOCKQUOTE_LINE,
|
||||
State.HEADER_LINE] + State.LIST:
|
||||
blockFormat = self.style.formatBlock(block, state)
|
||||
|
||||
QTextCursor(block).setBlockFormat(blockFormat)
|
||||
|
||||
def getBlankLines(self, block):
|
||||
"""Returns if there is a blank line before in the list."""
|
||||
state = block.userState()
|
||||
if state >= 200:
|
||||
return 1
|
||||
else:
|
||||
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:
|
||||
return True
|
||||
|
||||
def setStyle(self, style="Default"):
|
||||
if style in t2tHighlighterStyle.validStyles:
|
||||
self.style = t2tHighlighterStyle(self.editor, self._defaultCharFormat, style)
|
||||
else:
|
||||
self.style = None
|
||||
self.rehighlight()
|
||||
|
||||
def setFontPointSize(self, size):
|
||||
self.defaultFontPointSize = size
|
||||
self.style = t2tHighlighterStyle(self.editor, self.style.name)
|
||||
self.rehighlight()
|
||||
|
||||
def parseInDocRules(self):
|
||||
oldRules = self.inDocRules
|
||||
self.inDocRules = []
|
||||
|
||||
t = self.thisDocument.toPlainText()
|
||||
|
||||
# Get all conf files
|
||||
confs = []
|
||||
lines = t.split("\n")
|
||||
for l in lines:
|
||||
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)
|
||||
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()
|
||||
lastColor = ""
|
||||
|
||||
# while b.isValid():
|
||||
for l in lines:
|
||||
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]
|
||||
# Check if there was a color-comment above that post/preproc bloc
|
||||
if lastColor:
|
||||
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()
|
||||
r = QRegExp(r'^%.*\s\((.*)\)')
|
||||
if r.indexIn(previousText) != -1:
|
||||
lastColor = r.cap(1)
|
||||
self.inDocRules.append((str(rule), lastColor))
|
||||
else:
|
||||
lastColor = ""
|
||||
# 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?
|
||||
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()
|
|
@ -1,252 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
|
||||
# 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():
|
||||
"""Style for the Syntax highlighter for the Txt2Tags language.
|
||||
"""
|
||||
|
||||
validStyles = ["Default", "Monospace"]
|
||||
|
||||
def __init__(self, editor, charFormat, name="Default"):
|
||||
|
||||
self.editor = editor
|
||||
self.name = name
|
||||
self._defaultCharFormat = charFormat
|
||||
|
||||
# Defaults
|
||||
# self.defaultFontPointSize = self.editor.defaultFontPointSize
|
||||
self.defaultFontFamily = qApp.font().family()
|
||||
self.tabStopWidth = 40
|
||||
|
||||
self.setupEditor()
|
||||
|
||||
if self.name == "Default":
|
||||
self.initDefaults()
|
||||
# Temporary other theme
|
||||
elif self.name == "Monospace":
|
||||
self.defaultFontFamily = "Monospace"
|
||||
self.initDefaults()
|
||||
for i in self.styles:
|
||||
f = self.styles[i]
|
||||
f.setFontFixedPitch(True)
|
||||
f.setFontFamily(self.defaultFontFamily)
|
||||
f.setFontPointSize(self._defaultCharFormat.font().pointSize())
|
||||
self.styles[i] = f
|
||||
|
||||
def setupEditor(self):
|
||||
self.editor.setTabStopWidth(self.tabStopWidth)
|
||||
|
||||
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]:
|
||||
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"""
|
||||
if max(beautifiers) == 2:
|
||||
return self.makeFormat(preset=State.MARKUP, base=base)
|
||||
else:
|
||||
if beautifiers[0]: # bold
|
||||
base.setFontWeight(QFont.Bold)
|
||||
if beautifiers[1]: # italic
|
||||
base.setFontItalic(True)
|
||||
if beautifiers[2]: # underline
|
||||
base.setFontUnderline(True)
|
||||
if beautifiers[3]: # strikeout
|
||||
base.setFontStrikeOut(True)
|
||||
if beautifiers[4]: # code
|
||||
base = self.makeFormat(base=base, preset=State.CODE_LINE)
|
||||
if beautifiers[5]: # tagged
|
||||
base = self.makeFormat(base=base, preset=State.TAGGED_LINE)
|
||||
return base
|
||||
|
||||
def formatBlock(self, block, state):
|
||||
"""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.setAlignment(Qt.AlignJustify)
|
||||
if self.name == "Default":
|
||||
blockFormat.setTopMargin(5)
|
||||
blockFormat.setBottomMargin(5)
|
||||
elif state == State.HEADER_LINE:
|
||||
blockFormat.setBackground(QColor("#EEEEEE"))
|
||||
elif state in State.LIST:
|
||||
data = blockUserData.getUserData(block)
|
||||
if str(data.listSymbol()) in "+-":
|
||||
blockFormat.setBackground(QColor("#EEFFEE"))
|
||||
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":
|
||||
blockFormat.setTopMargin(5)
|
||||
return blockFormat
|
||||
|
||||
def makeFormat(self, color='', style='', size='', base='', fixedPitch='',
|
||||
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(self._defaultCharFormat)
|
||||
|
||||
# Base
|
||||
if base:
|
||||
_format = base
|
||||
|
||||
# Presets
|
||||
if preset in [State.CODE_AREA, State.CODE_LINE, "code"]:
|
||||
style = "bold"
|
||||
color = "black"
|
||||
fixedPitch = True
|
||||
_format.setBackground(QColor("#EEEEEE"))
|
||||
|
||||
if preset in [State.COMMENT_AREA, State.COMMENT_LINE, "comment"]:
|
||||
style = "italic"
|
||||
color = "darkGreen"
|
||||
|
||||
if preset in [State.SETTINGS_LINE, "setting", State.MACRO]:
|
||||
# style = "italic"
|
||||
color = "magenta"
|
||||
|
||||
if preset in [State.BLOCKQUOTE_LINE]:
|
||||
color = "red"
|
||||
|
||||
if preset in [State.HEADER_LINE]:
|
||||
size *= 2
|
||||
# print size
|
||||
|
||||
if preset in [State.RAW_AREA, State.RAW_LINE, "raw"]:
|
||||
color = "blue"
|
||||
|
||||
if preset in [State.TAGGED_AREA, State.TAGGED_LINE, "tagged"]:
|
||||
color = "purple"
|
||||
|
||||
if preset in State.TITLES:
|
||||
style = "bold"
|
||||
color = "darkRed" if State.titleLevel(preset) % 2 == 1 else "blue"
|
||||
size = (self._defaultCharFormat.font().pointSize()
|
||||
+ 11 - 2 * State.titleLevel(preset))
|
||||
|
||||
if preset == State.TABLE_HEADER:
|
||||
style = "bold"
|
||||
color = "darkMagenta"
|
||||
|
||||
if preset == State.TABLE_LINE:
|
||||
color = "darkMagenta"
|
||||
|
||||
if preset == State.LIST_BULLET:
|
||||
color = "red"
|
||||
style = "bold"
|
||||
fixedPitch = True
|
||||
|
||||
if preset == State.LIST_BULLET_ENDS:
|
||||
color = "darkGray"
|
||||
fixedPitch = True
|
||||
|
||||
if preset in [State.MARKUP, "markup"]:
|
||||
color = "darkGray"
|
||||
|
||||
if preset in [State.HORIZONTAL_LINE]:
|
||||
color = "cyan"
|
||||
fixedPitch = True
|
||||
|
||||
if preset == State.LINKS:
|
||||
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)
|
||||
|
||||
# Manual formatting
|
||||
if color:
|
||||
_color.setNamedColor(color)
|
||||
_format.setForeground(_color)
|
||||
if bgcolor:
|
||||
_color.setNamedColor(bgcolor)
|
||||
_format.setBackground(_color)
|
||||
|
||||
if 'bold' in style:
|
||||
_format.setFontWeight(QFont.Bold)
|
||||
if 'italic' in style:
|
||||
_format.setFontItalic(True)
|
||||
if 'strike' in style:
|
||||
_format.setFontStrikeOut(True)
|
||||
if 'underline' in style:
|
||||
_format.setFontUnderline(True)
|
||||
if size:
|
||||
_format.setFontPointSize(size)
|
||||
if fixedPitch:
|
||||
_format.setFontFixedPitch(True)
|
||||
|
||||
return _format
|
|
@ -61,9 +61,6 @@ class textFormat(QWidget, Ui_textFormat):
|
|||
|
||||
elif item.isText():
|
||||
self.align.setVisible(False)
|
||||
self.format.setVisible(False)
|
||||
elif item.isT2T():
|
||||
self.align.setVisible(False)
|
||||
|
||||
def setFormat(self):
|
||||
act = self.sender()
|
||||
|
|
|
@ -9,7 +9,7 @@ from PyQt5.QtCore import QSettings, QRect, QSize, Qt, QPoint, QFile, QIODevice,
|
|||
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.functions import allPaths, appPath, findBackground, findFirstFile
|
||||
from manuskript.ui.views.textEditView import textEditView
|
||||
|
||||
|
||||
|
@ -119,19 +119,6 @@ def findThemePath(themeName):
|
|||
return p
|
||||
|
||||
|
||||
def findBackground(filename):
|
||||
return findFirstFile(re.escape(filename), "resources/backgrounds")
|
||||
|
||||
|
||||
def findFirstFile(regex, path="resources"):
|
||||
paths = allPaths(path)
|
||||
for p in paths:
|
||||
lst = os.listdir(p)
|
||||
for l in lst:
|
||||
if re.match(regex, l):
|
||||
return os.path.join(p, l)
|
||||
|
||||
|
||||
def generateTheme(themeDatas, screenRect):
|
||||
# Window Background
|
||||
px = QPixmap(screenRect.size())
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/mainWindow.ui'
|
||||
#
|
||||
# Created: Sun Feb 28 13:22:17 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
# Created by: PyQt5 UI code generator 5.4.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
@ -17,8 +16,8 @@ class Ui_MainWindow(object):
|
|||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout_2.setSpacing(0)
|
||||
self.horizontalLayout_2.setContentsMargins(0, 6, 0, 0)
|
||||
self.horizontalLayout_2.setSpacing(0)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.stack = QtWidgets.QStackedWidget(self.centralwidget)
|
||||
self.stack.setObjectName("stack")
|
||||
|
@ -165,18 +164,18 @@ class Ui_MainWindow(object):
|
|||
self.label = QtWidgets.QLabel(self.tabSummaryPage1)
|
||||
self.label.setObjectName("label")
|
||||
self.verticalLayout_5.addWidget(self.label)
|
||||
self.txtSummarySentance = textEditView(self.tabSummaryPage1)
|
||||
self.txtSummarySentence = textEditView(self.tabSummaryPage1)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.txtSummarySentance.sizePolicy().hasHeightForWidth())
|
||||
self.txtSummarySentance.setSizePolicy(sizePolicy)
|
||||
self.txtSummarySentance.setObjectName("txtSummarySentance")
|
||||
self.verticalLayout_5.addWidget(self.txtSummarySentance)
|
||||
self.lblSummaryWCSentance = QtWidgets.QLabel(self.tabSummaryPage1)
|
||||
self.lblSummaryWCSentance.setText("")
|
||||
self.lblSummaryWCSentance.setObjectName("lblSummaryWCSentance")
|
||||
self.verticalLayout_5.addWidget(self.lblSummaryWCSentance)
|
||||
sizePolicy.setHeightForWidth(self.txtSummarySentence.sizePolicy().hasHeightForWidth())
|
||||
self.txtSummarySentence.setSizePolicy(sizePolicy)
|
||||
self.txtSummarySentence.setObjectName("txtSummarySentence")
|
||||
self.verticalLayout_5.addWidget(self.txtSummarySentence)
|
||||
self.lblSummaryWCSentence = QtWidgets.QLabel(self.tabSummaryPage1)
|
||||
self.lblSummaryWCSentence.setText("")
|
||||
self.lblSummaryWCSentence.setObjectName("lblSummaryWCSentence")
|
||||
self.verticalLayout_5.addWidget(self.lblSummaryWCSentence)
|
||||
spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_5.addItem(spacerItem5)
|
||||
self.tabSummary.addWidget(self.tabSummaryPage1)
|
||||
|
@ -189,15 +188,15 @@ class Ui_MainWindow(object):
|
|||
self.label_21 = QtWidgets.QLabel(self.tabSummaryPage2)
|
||||
self.label_21.setObjectName("label_21")
|
||||
self.verticalLayout.addWidget(self.label_21)
|
||||
self.txtSummarySentance_2 = textEditView(self.tabSummaryPage2)
|
||||
self.txtSummarySentence_2 = textEditView(self.tabSummaryPage2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.txtSummarySentance_2.sizePolicy().hasHeightForWidth())
|
||||
self.txtSummarySentance_2.setSizePolicy(sizePolicy)
|
||||
self.txtSummarySentance_2.setReadOnly(True)
|
||||
self.txtSummarySentance_2.setObjectName("txtSummarySentance_2")
|
||||
self.verticalLayout.addWidget(self.txtSummarySentance_2)
|
||||
sizePolicy.setHeightForWidth(self.txtSummarySentence_2.sizePolicy().hasHeightForWidth())
|
||||
self.txtSummarySentence_2.setSizePolicy(sizePolicy)
|
||||
self.txtSummarySentence_2.setReadOnly(True)
|
||||
self.txtSummarySentence_2.setObjectName("txtSummarySentence_2")
|
||||
self.verticalLayout.addWidget(self.txtSummarySentence_2)
|
||||
spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem6)
|
||||
self.horizontalLayout_4.addLayout(self.verticalLayout)
|
||||
|
@ -337,12 +336,12 @@ class Ui_MainWindow(object):
|
|||
self.groupBox.setObjectName("groupBox")
|
||||
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_8.setObjectName("verticalLayout_8")
|
||||
self.lstPersos = persoTreeView(self.groupBox)
|
||||
self.lstPersos.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.lstPersos.setDragEnabled(True)
|
||||
self.lstPersos.setObjectName("lstPersos")
|
||||
self.lstPersos.headerItem().setText(0, "1")
|
||||
self.verticalLayout_8.addWidget(self.lstPersos)
|
||||
self.lstCharacters = characterTreeView(self.groupBox)
|
||||
self.lstCharacters.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.lstCharacters.setDragEnabled(True)
|
||||
self.lstCharacters.setObjectName("lstCharacters")
|
||||
self.lstCharacters.headerItem().setText(0, "1")
|
||||
self.verticalLayout_8.addWidget(self.lstCharacters)
|
||||
self.horizontalLayout_14 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_14.setObjectName("horizontalLayout_14")
|
||||
self.btnAddPerso = QtWidgets.QPushButton(self.groupBox)
|
||||
|
@ -433,9 +432,9 @@ class Ui_MainWindow(object):
|
|||
self.txtPersoEpiphany = textEditView(self.infos)
|
||||
self.txtPersoEpiphany.setObjectName("txtPersoEpiphany")
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.txtPersoEpiphany)
|
||||
self.txtPersoSummarySentance = textEditView(self.infos)
|
||||
self.txtPersoSummarySentance.setObjectName("txtPersoSummarySentance")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.txtPersoSummarySentance)
|
||||
self.txtPersoSummarySentence = textEditView(self.infos)
|
||||
self.txtPersoSummarySentence.setObjectName("txtPersoSummarySentence")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.txtPersoSummarySentence)
|
||||
self.txtPersoSummaryPara = textEditView(self.infos)
|
||||
self.txtPersoSummaryPara.setObjectName("txtPersoSummaryPara")
|
||||
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.txtPersoSummaryPara)
|
||||
|
@ -809,7 +808,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)
|
||||
|
@ -996,7 +994,7 @@ class Ui_MainWindow(object):
|
|||
self.horizontalLayout_2.addWidget(self.stack)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1112, 20))
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1112, 30))
|
||||
self.menubar.setObjectName("menubar")
|
||||
self.menuFile = QtWidgets.QMenu(self.menubar)
|
||||
self.menuFile.setObjectName("menuFile")
|
||||
|
@ -1004,8 +1002,6 @@ class Ui_MainWindow(object):
|
|||
icon = QtGui.QIcon.fromTheme("folder-recent")
|
||||
self.menuRecents.setIcon(icon)
|
||||
self.menuRecents.setObjectName("menuRecents")
|
||||
self.menuMode = QtWidgets.QMenu(self.menubar)
|
||||
self.menuMode.setObjectName("menuMode")
|
||||
self.menuHelp = QtWidgets.QMenu(self.menubar)
|
||||
self.menuHelp.setObjectName("menuHelp")
|
||||
self.menuTools = QtWidgets.QMenu(self.menubar)
|
||||
|
@ -1014,6 +1010,8 @@ class Ui_MainWindow(object):
|
|||
self.menuEdit.setObjectName("menuEdit")
|
||||
self.menuView = QtWidgets.QMenu(self.menubar)
|
||||
self.menuView.setObjectName("menuView")
|
||||
self.menuMode = QtWidgets.QMenu(self.menuView)
|
||||
self.menuMode.setObjectName("menuMode")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
|
@ -1113,16 +1111,16 @@ class Ui_MainWindow(object):
|
|||
self.actStatus.setObjectName("actStatus")
|
||||
self.actViewTree = QtWidgets.QAction(MainWindow)
|
||||
self.actViewTree.setObjectName("actViewTree")
|
||||
self.actModeNorma = QtWidgets.QAction(MainWindow)
|
||||
self.actModeNorma.setCheckable(True)
|
||||
self.actModeNorma.setChecked(True)
|
||||
self.actModeNorma.setObjectName("actModeNorma")
|
||||
self.actModeSimple = QtWidgets.QAction(MainWindow)
|
||||
self.actModeSimple.setCheckable(True)
|
||||
self.actModeSimple.setChecked(True)
|
||||
self.actModeSimple.setObjectName("actModeSimple")
|
||||
self.actModeFractal = QtWidgets.QAction(MainWindow)
|
||||
self.actModeFractal.setCheckable(True)
|
||||
self.actModeFractal.setObjectName("actModeFractal")
|
||||
self.actModeFiction = QtWidgets.QAction(MainWindow)
|
||||
self.actModeFiction.setCheckable(True)
|
||||
self.actModeFiction.setObjectName("actModeFiction")
|
||||
self.actModeSnowflake = QtWidgets.QAction(MainWindow)
|
||||
self.actModeSnowflake.setCheckable(True)
|
||||
self.actModeSnowflake.setObjectName("actModeSnowflake")
|
||||
self.actViewCork = QtWidgets.QAction(MainWindow)
|
||||
self.actViewCork.setObjectName("actViewCork")
|
||||
self.actViewOutline = QtWidgets.QAction(MainWindow)
|
||||
|
@ -1148,25 +1146,26 @@ class Ui_MainWindow(object):
|
|||
self.menuFile.addAction(self.actCompile)
|
||||
self.menuFile.addSeparator()
|
||||
self.menuFile.addAction(self.actQuit)
|
||||
self.menuMode.addAction(self.actModeNorma)
|
||||
self.menuMode.addAction(self.actModeSimple)
|
||||
self.menuMode.addAction(self.actModeFractal)
|
||||
self.menuHelp.addAction(self.actShowHelp)
|
||||
self.menuTools.addAction(self.actSpellcheck)
|
||||
self.menuTools.addAction(self.actToolFrequency)
|
||||
self.menuEdit.addAction(self.actLabels)
|
||||
self.menuEdit.addAction(self.actStatus)
|
||||
self.menuEdit.addAction(self.actSettings)
|
||||
self.menuMode.addAction(self.actModeSimple)
|
||||
self.menuMode.addAction(self.actModeFiction)
|
||||
self.menuMode.addAction(self.actModeSnowflake)
|
||||
self.menuView.addAction(self.menuMode.menuAction())
|
||||
self.menuView.addSeparator()
|
||||
self.menubar.addAction(self.menuFile.menuAction())
|
||||
self.menubar.addAction(self.menuEdit.menuAction())
|
||||
self.menubar.addAction(self.menuMode.menuAction())
|
||||
self.menubar.addAction(self.menuView.menuAction())
|
||||
self.menubar.addAction(self.menuTools.menuAction())
|
||||
self.menubar.addAction(self.menuHelp.menuAction())
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
self.stack.setCurrentIndex(1)
|
||||
self.tabMain.setCurrentIndex(6)
|
||||
self.tabMain.setCurrentIndex(4)
|
||||
self.tabSummary.setCurrentIndex(0)
|
||||
self.tabPersos.setCurrentIndex(0)
|
||||
self.tabPlot.setCurrentIndex(0)
|
||||
|
@ -1196,12 +1195,12 @@ class Ui_MainWindow(object):
|
|||
self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabOverview), _translate("MainWindow", "General"))
|
||||
self.label_9.setText(_translate("MainWindow", "Situation:"))
|
||||
self.label_29.setText(_translate("MainWindow", "Summary:"))
|
||||
self.cmbSummary.setItemText(0, _translate("MainWindow", "One sentance"))
|
||||
self.cmbSummary.setItemText(0, _translate("MainWindow", "One sentence"))
|
||||
self.cmbSummary.setItemText(1, _translate("MainWindow", "One paragraph"))
|
||||
self.cmbSummary.setItemText(2, _translate("MainWindow", "One page"))
|
||||
self.cmbSummary.setItemText(3, _translate("MainWindow", "Full"))
|
||||
self.label.setText(_translate("MainWindow", "One sentance summary"))
|
||||
self.label_21.setText(_translate("MainWindow", "One sentance summary"))
|
||||
self.label.setText(_translate("MainWindow", "One sentence summary"))
|
||||
self.label_21.setText(_translate("MainWindow", "One sentence summary"))
|
||||
self.label_2.setText(_translate("MainWindow", "One paragraph summary"))
|
||||
self.label_22.setText(_translate("MainWindow", "One paragraph summary"))
|
||||
self.label_17.setText(_translate("MainWindow", "Expand each sentence of your one paragraph summary to a paragraph"))
|
||||
|
@ -1221,7 +1220,7 @@ class Ui_MainWindow(object):
|
|||
self.label_5.setText(_translate("MainWindow", "Goal"))
|
||||
self.label_6.setText(_translate("MainWindow", "Conflict"))
|
||||
self.label_7.setText(_translate("MainWindow", "Epiphany"))
|
||||
self.label_24.setText(_translate("MainWindow", "<html><head/><body><p align=\"right\">One sentance<br/>summary</p></body></html>"))
|
||||
self.label_24.setText(_translate("MainWindow", "<html><head/><body><p align=\"right\">One sentence<br/>summary</p></body></html>"))
|
||||
self.label_8.setText(_translate("MainWindow", "<html><head/><body><p align=\"right\">One paragraph<br/>summary</p></body></html>"))
|
||||
self.btnStepFour.setText(_translate("MainWindow", "Next"))
|
||||
self.tabPersos.setTabText(self.tabPersos.indexOf(self.infos), _translate("MainWindow", "Basic infos"))
|
||||
|
@ -1266,13 +1265,13 @@ 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", "Fi&le"))
|
||||
self.menuFile.setTitle(_translate("MainWindow", "&File"))
|
||||
self.menuRecents.setTitle(_translate("MainWindow", "&Recents"))
|
||||
self.menuMode.setTitle(_translate("MainWindow", "&Mode"))
|
||||
self.menuHelp.setTitle(_translate("MainWindow", "Help"))
|
||||
self.menuHelp.setTitle(_translate("MainWindow", "&Help"))
|
||||
self.menuTools.setTitle(_translate("MainWindow", "&Tools"))
|
||||
self.menuEdit.setTitle(_translate("MainWindow", "E&dit"))
|
||||
self.menuEdit.setTitle(_translate("MainWindow", "&Edit"))
|
||||
self.menuView.setTitle(_translate("MainWindow", "&View"))
|
||||
self.menuMode.setTitle(_translate("MainWindow", "&Mode"))
|
||||
self.dckCheatSheet.setWindowTitle(_translate("MainWindow", "&Cheat sheet"))
|
||||
self.dckSearch.setWindowTitle(_translate("MainWindow", "Sea&rch"))
|
||||
self.dckNavigation.setWindowTitle(_translate("MainWindow", "&Navigation"))
|
||||
|
@ -1291,9 +1290,9 @@ class Ui_MainWindow(object):
|
|||
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.actModeFiction.setText(_translate("MainWindow", "&Fiction"))
|
||||
self.actModeSnowflake.setText(_translate("MainWindow", "S&nowflake"))
|
||||
self.actViewCork.setText(_translate("MainWindow", "Index cards"))
|
||||
self.actViewOutline.setText(_translate("MainWindow", "Outline"))
|
||||
self.actSettings.setText(_translate("MainWindow", "S&ettings"))
|
||||
|
@ -1303,18 +1302,18 @@ class Ui_MainWindow(object):
|
|||
self.actCompile.setShortcut(_translate("MainWindow", "F6"))
|
||||
self.actToolFrequency.setText(_translate("MainWindow", "&Frequency Analyzer"))
|
||||
|
||||
from manuskript.ui.views.lineEditView import lineEditView
|
||||
from manuskript.ui.cheatSheet import cheatSheet
|
||||
from manuskript.ui.editors.mainEditor import mainEditor
|
||||
from manuskript.ui.views.outlineView import outlineView
|
||||
from manuskript.ui.views.treeView import treeView
|
||||
from manuskript.ui.views.textEditView import textEditView
|
||||
from manuskript.ui.views.storylineView import storylineView
|
||||
from manuskript.ui.views.persoTreeView import persoTreeView
|
||||
from manuskript.ui.views.plotTreeView import plotTreeView
|
||||
from manuskript.ui.search import search
|
||||
from manuskript.ui.views.basicItemView import basicItemView
|
||||
from manuskript.ui.welcome import welcome
|
||||
from manuskript.ui.views.textEditCompleter import textEditCompleter
|
||||
from manuskript.ui.sldImportance import sldImportance
|
||||
from manuskript.ui.views.characterTreeView import characterTreeView
|
||||
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.plotTreeView import plotTreeView
|
||||
from manuskript.ui.views.sldImportance import sldImportance
|
||||
from manuskript.ui.views.storylineView import storylineView
|
||||
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
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>6</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
|
@ -342,7 +342,7 @@
|
|||
<widget class="QComboBox" name="cmbSummary">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>One sentance</string>
|
||||
<string>One sentence</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -374,12 +374,12 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>One sentance summary</string>
|
||||
<string>One sentence summary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="textEditView" name="txtSummarySentance">
|
||||
<widget class="textEditView" name="txtSummarySentence">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -389,7 +389,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblSummaryWCSentance">
|
||||
<widget class="QLabel" name="lblSummaryWCSentence">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -417,12 +417,12 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>One sentance summary</string>
|
||||
<string>One sentence summary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="textEditView" name="txtSummarySentance_2">
|
||||
<widget class="textEditView" name="txtSummarySentence_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -714,7 +714,7 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="persoTreeView" name="lstPersos">
|
||||
<widget class="characterTreeView" name="lstCharacters">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
|
@ -823,7 +823,7 @@
|
|||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="right">One sentance<br/>summary</p></body></html></string>
|
||||
<string><html><head/><body><p align="right">One sentence<br/>summary</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -899,7 +899,7 @@
|
|||
<widget class="textEditView" name="txtPersoEpiphany"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="textEditView" name="txtPersoSummarySentance"/>
|
||||
<widget class="textEditView" name="txtPersoSummarySentence"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="textEditView" name="txtPersoSummaryPara"/>
|
||||
|
@ -1979,12 +1979,12 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1112</width>
|
||||
<height>20</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>Fi&le</string>
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuRecents">
|
||||
<property name="title">
|
||||
|
@ -2006,17 +2006,9 @@
|
|||
<addaction name="separator"/>
|
||||
<addaction name="actQuit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuMode">
|
||||
<property name="title">
|
||||
<string>&Mode</string>
|
||||
</property>
|
||||
<addaction name="actModeNorma"/>
|
||||
<addaction name="actModeSimple"/>
|
||||
<addaction name="actModeFractal"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actShowHelp"/>
|
||||
</widget>
|
||||
|
@ -2029,7 +2021,7 @@
|
|||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>E&dit</string>
|
||||
<string>&Edit</string>
|
||||
</property>
|
||||
<addaction name="actLabels"/>
|
||||
<addaction name="actStatus"/>
|
||||
|
@ -2039,10 +2031,19 @@
|
|||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuMode">
|
||||
<property name="title">
|
||||
<string>&Mode</string>
|
||||
</property>
|
||||
<addaction name="actModeSimple"/>
|
||||
<addaction name="actModeFiction"/>
|
||||
<addaction name="actModeSnowflake"/>
|
||||
</widget>
|
||||
<addaction name="menuMode"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuMode"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuHelp"/>
|
||||
|
@ -2266,31 +2267,31 @@ QListView::item:hover {
|
|||
<string>Tree</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actModeNorma">
|
||||
<action name="actModeSimple">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Normal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actModeSimple">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Simple</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actModeFractal">
|
||||
<action name="actModeFiction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Fractal</string>
|
||||
<string>&Fiction</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actModeSnowflake">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>S&nowflake</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actViewCork">
|
||||
|
@ -2358,7 +2359,7 @@ QListView::item:hover {
|
|||
<customwidget>
|
||||
<class>sldImportance</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>manuskript.ui.sldImportance.h</header>
|
||||
<header>manuskript.ui.views.sldImportance.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
|
@ -2396,9 +2397,9 @@ QListView::item:hover {
|
|||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>persoTreeView</class>
|
||||
<class>characterTreeView</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>manuskript.ui.views.persoTreeView.h</header>
|
||||
<header>manuskript.ui.views.characterTreeView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>cheatSheet</class>
|
||||
|
|
|
@ -144,8 +144,6 @@ class revisions(QWidget, Ui_revisions):
|
|||
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
|
||||
|
||||
|
@ -160,7 +158,7 @@ class revisions(QWidget, Ui_revisions):
|
|||
else:
|
||||
_format = lambda x: x
|
||||
|
||||
extra = "" if item.type() == "html" else "<br>"
|
||||
extra = "<br>"
|
||||
diff = [d for d in diff if d and not d[:2] == "? "]
|
||||
mydiff = ""
|
||||
skip = False
|
||||
|
@ -177,8 +175,6 @@ class revisions(QWidget, Ui_revisions):
|
|||
|
||||
# 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 == "+ ":
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/revisions_ui.ui'
|
||||
#
|
||||
# Created: Tue Jul 14 19:00:07 2015
|
||||
# Created: Wed Mar 2 00:30:17 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
|
|
@ -84,7 +84,7 @@ class search(QWidget, Ui_search):
|
|||
lstColumns = [
|
||||
("Title", Outline.title.value),
|
||||
("Text", Outline.text.value),
|
||||
("Summary", Outline.summarySentance.value),
|
||||
("Summary", Outline.summarySentence.value),
|
||||
("Summary", Outline.summaryFull.value),
|
||||
("Notes", Outline.notes.value),
|
||||
("POV", Outline.POV.value),
|
||||
|
|
|
@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_Settings(object):
|
||||
def setupUi(self, Settings):
|
||||
Settings.setObjectName("Settings")
|
||||
Settings.resize(658, 491)
|
||||
Settings.resize(658, 507)
|
||||
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(Settings)
|
||||
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
|
||||
self.lstMenu = QtWidgets.QListWidget(Settings)
|
||||
|
@ -76,6 +76,30 @@ class Ui_Settings(object):
|
|||
self.cmbStyle.setObjectName("cmbStyle")
|
||||
self.verticalLayout_5.addWidget(self.cmbStyle)
|
||||
self.verticalLayout_7.addWidget(self.groupBox_2)
|
||||
self.groupBox_14 = QtWidgets.QGroupBox(self.stackedWidgetPage1)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.groupBox_14.setFont(font)
|
||||
self.groupBox_14.setObjectName("groupBox_14")
|
||||
self.verticalLayout_20 = QtWidgets.QVBoxLayout(self.groupBox_14)
|
||||
self.verticalLayout_20.setObjectName("verticalLayout_20")
|
||||
self.label_52 = QtWidgets.QLabel(self.groupBox_14)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.label_52.setFont(font)
|
||||
self.label_52.setWordWrap(True)
|
||||
self.label_52.setObjectName("label_52")
|
||||
self.verticalLayout_20.addWidget(self.label_52)
|
||||
self.cmbTranslation = QtWidgets.QComboBox(self.groupBox_14)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.cmbTranslation.setFont(font)
|
||||
self.cmbTranslation.setObjectName("cmbTranslation")
|
||||
self.verticalLayout_20.addWidget(self.cmbTranslation)
|
||||
self.verticalLayout_7.addWidget(self.groupBox_14)
|
||||
self.groupBox_10 = QtWidgets.QGroupBox(self.stackedWidgetPage1)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
|
@ -181,31 +205,16 @@ class Ui_Settings(object):
|
|||
self.chkSaveOnQuit.setChecked(True)
|
||||
self.chkSaveOnQuit.setObjectName("chkSaveOnQuit")
|
||||
self.verticalLayout_6.addWidget(self.chkSaveOnQuit)
|
||||
self.chkSaveToZip = QtWidgets.QCheckBox(self.groupBox)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.chkSaveToZip.setFont(font)
|
||||
self.chkSaveToZip.setStatusTip("")
|
||||
self.chkSaveToZip.setChecked(True)
|
||||
self.chkSaveToZip.setObjectName("chkSaveToZip")
|
||||
self.verticalLayout_6.addWidget(self.chkSaveToZip)
|
||||
self.verticalLayout_7.addWidget(self.groupBox)
|
||||
self.groupBox_11 = QtWidgets.QGroupBox(self.stackedWidgetPage1)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.groupBox_11.setFont(font)
|
||||
self.groupBox_11.setObjectName("groupBox_11")
|
||||
self.verticalLayout_19 = QtWidgets.QVBoxLayout(self.groupBox_11)
|
||||
self.verticalLayout_19.setObjectName("verticalLayout_19")
|
||||
self.label_35 = QtWidgets.QLabel(self.groupBox_11)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.label_35.setFont(font)
|
||||
self.label_35.setWordWrap(True)
|
||||
self.label_35.setObjectName("label_35")
|
||||
self.verticalLayout_19.addWidget(self.label_35)
|
||||
self.cmbDefaultTextType = QtWidgets.QComboBox(self.groupBox_11)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
self.cmbDefaultTextType.setFont(font)
|
||||
self.cmbDefaultTextType.setObjectName("cmbDefaultTextType")
|
||||
self.verticalLayout_19.addWidget(self.cmbDefaultTextType)
|
||||
self.verticalLayout_7.addWidget(self.groupBox_11)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_7.addItem(spacerItem2)
|
||||
self.stack.addWidget(self.stackedWidgetPage1)
|
||||
|
@ -1599,7 +1608,7 @@ class Ui_Settings(object):
|
|||
self.horizontalLayout_8.addWidget(self.stack)
|
||||
|
||||
self.retranslateUi(Settings)
|
||||
self.stack.setCurrentIndex(2)
|
||||
self.stack.setCurrentIndex(0)
|
||||
self.tabViews.setCurrentIndex(0)
|
||||
self.themeStack.setCurrentIndex(1)
|
||||
self.themeEditStack.setCurrentIndex(0)
|
||||
|
@ -1628,6 +1637,8 @@ class Ui_Settings(object):
|
|||
self.lblTitleGeneral.setText(_translate("Settings", "General settings"))
|
||||
self.groupBox_2.setTitle(_translate("Settings", "Application style"))
|
||||
self.label_2.setText(_translate("Settings", "You might need to restart manuskript in order to avoid some visual issues."))
|
||||
self.groupBox_14.setTitle(_translate("Settings", "Application language"))
|
||||
self.label_52.setText(_translate("Settings", "You will need to restart manuskript for the translation to take effect."))
|
||||
self.groupBox_10.setTitle(_translate("Settings", "Loading"))
|
||||
self.chkAutoLoad.setText(_translate("Settings", "Automatically load last project on startup"))
|
||||
self.groupBox.setTitle(_translate("Settings", "Saving"))
|
||||
|
@ -1636,8 +1647,8 @@ class Ui_Settings(object):
|
|||
self.chkAutoSaveNoChanges.setText(_translate("Settings", "If no changes during"))
|
||||
self.label_14.setText(_translate("Settings", "seconds."))
|
||||
self.chkSaveOnQuit.setText(_translate("Settings", "Save on quit"))
|
||||
self.groupBox_11.setTitle(_translate("Settings", "Default text format"))
|
||||
self.label_35.setText(_translate("Settings", "The format set by default when you create a new text item. You can change this on a per item basis."))
|
||||
self.chkSaveToZip.setToolTip(_translate("Settings", "<html><head/><body><p>If you check this option, your project will be save as one single file. Easier to copy or backup, but does not allow collaborative editing, or versionning.<br/>If this is unchecked, your project will be save as a folder containing many small files.</p></body></html>"))
|
||||
self.chkSaveToZip.setText(_translate("Settings", "Save to one single file"))
|
||||
self.lblTitleGeneral_2.setText(_translate("Settings", "Revisions"))
|
||||
self.label_44.setText(_translate("Settings", "Revisions are a way to keep track of modifications. For each text item, it stores any changes you make to the main text, allowing you to see and restoring previous versions."))
|
||||
self.chkRevisionsKeep.setText(_translate("Settings", "Keep revisions"))
|
||||
|
@ -1674,7 +1685,7 @@ class Ui_Settings(object):
|
|||
self.rdoTreeWC.setText(_translate("Settings", "Show wordcount"))
|
||||
self.rdoTreeProgress.setText(_translate("Settings", "Show progress"))
|
||||
self.rdoTreeSummary.setText(_translate("Settings", "Show summary"))
|
||||
self.rdoTreeNothing.setText(_translate("Settings", "Nothing"))
|
||||
self.rdoTreeNothing.setText(_translate("Settings", "&Nothing"))
|
||||
self.groupBox_9.setTitle(_translate("Settings", "Text"))
|
||||
self.rdoTreeTextWC.setText(_translate("Settings", "Show wordcount"))
|
||||
self.rdoTreeTextProgress.setText(_translate("Settings", "Show progress"))
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<height>491</height>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -51,7 +51,7 @@
|
|||
<item>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="stackedWidgetPage1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
|
@ -133,6 +133,47 @@ text-align:center;</string>
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Application language</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_52">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>You will need to restart manuskript for the translation to take effect.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbTranslation">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="font">
|
||||
|
@ -358,47 +399,28 @@ text-align:center;</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Default text format</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_35">
|
||||
<widget class="QCheckBox" name="chkSaveToZip">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If you check this option, your project will be save as one single file. Easier to copy or backup, but does not allow collaborative editing, or versionning.<br/>If this is unchecked, your project will be save as a folder containing many small files.</p></body></html></string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>The format set by default when you create a new text item. You can change this on a per item basis.</string>
|
||||
<string>Save to one single file</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbDefaultTextType">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -1032,7 +1054,7 @@ text-align:center;</string>
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Nothing</string>
|
||||
<string>&Nothing</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -45,12 +45,6 @@ class frequencyAnalyzer(QWidget, Ui_FrequencyAnalyzer):
|
|||
def listPhrases(item, nMin, nMax):
|
||||
txt = item.text()
|
||||
|
||||
# Convert to plain text
|
||||
if item.isHTML():
|
||||
e = QTextEdit()
|
||||
e.setHtml(item.text())
|
||||
txt = e.toPlainText()
|
||||
|
||||
# Split into words
|
||||
lst = re.findall(r"[\w']+", txt) # Ignores punctuation
|
||||
# lst = re.findall(r"[\w']+|[.,!?;]", txt) # Includes punctuation
|
||||
|
@ -92,12 +86,6 @@ class frequencyAnalyzer(QWidget, Ui_FrequencyAnalyzer):
|
|||
def listWords(item):
|
||||
txt = item.text()
|
||||
|
||||
# Convert to plain text
|
||||
if item.isHTML():
|
||||
e = QTextEdit()
|
||||
e.setHtml(item.text())
|
||||
txt = e.toPlainText()
|
||||
|
||||
lst = re.findall(r"[\w']+", txt)
|
||||
for c in item.children():
|
||||
lst += listWords(c)
|
||||
|
|
|
@ -10,13 +10,13 @@ class basicItemView(QWidget, Ui_basicItemView):
|
|||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self)
|
||||
self.setupUi(self)
|
||||
self.txtSummarySentance.setColumn(Outline.summarySentance.value)
|
||||
self.txtSummarySentence.setColumn(Outline.summarySentence.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)
|
||||
def setModels(self, mdlOutline, mdlCharacter, mdlLabels, mdlStatus):
|
||||
self.cmbPOV.setModels(mdlCharacter, mdlOutline)
|
||||
self.txtSummarySentence.setModel(mdlOutline)
|
||||
self.txtSummaryFull.setModel(mdlOutline)
|
||||
self.txtGoal.setModel(mdlOutline)
|
||||
|
||||
|
@ -43,14 +43,14 @@ class basicItemView(QWidget, Ui_basicItemView):
|
|||
elif len(indexes) == 1:
|
||||
self.setEnabled(True)
|
||||
idx = indexes[0]
|
||||
self.txtSummarySentance.setCurrentModelIndex(idx)
|
||||
self.txtSummarySentence.setCurrentModelIndex(idx)
|
||||
self.txtSummaryFull.setCurrentModelIndex(idx)
|
||||
self.cmbPOV.setCurrentModelIndex(idx)
|
||||
self.txtGoal.setCurrentModelIndex(idx)
|
||||
|
||||
else:
|
||||
self.setEnabled(True)
|
||||
self.txtSummarySentance.setCurrentModelIndexes(indexes)
|
||||
self.txtSummarySentence.setCurrentModelIndexes(indexes)
|
||||
self.txtSummaryFull.setCurrentModelIndexes(indexes)
|
||||
self.cmbPOV.setCurrentModelIndexes(indexes)
|
||||
self.txtGoal.setCurrentModelIndexes(indexes)
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/views/basicItemView_ui.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.4.2
|
||||
# Created: Thu Mar 3 17:26:11 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
@ -23,7 +24,7 @@ class Ui_basicItemView(object):
|
|||
self.lblPlanPOV.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.lblPlanPOV.setObjectName("lblPlanPOV")
|
||||
self.horizontalLayout_11.addWidget(self.lblPlanPOV)
|
||||
self.cmbPOV = cmbOutlinePersoChoser(basicItemView)
|
||||
self.cmbPOV = cmbOutlineCharacterChoser(basicItemView)
|
||||
self.cmbPOV.setFrame(False)
|
||||
self.cmbPOV.setObjectName("cmbPOV")
|
||||
self.horizontalLayout_11.addWidget(self.cmbPOV)
|
||||
|
@ -43,10 +44,10 @@ class Ui_basicItemView(object):
|
|||
self.txtGoal.setObjectName("txtGoal")
|
||||
self.horizontalLayout_11.addWidget(self.txtGoal)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_11)
|
||||
self.txtSummarySentance = lineEditView(basicItemView)
|
||||
self.txtSummarySentance.setText("")
|
||||
self.txtSummarySentance.setObjectName("txtSummarySentance")
|
||||
self.verticalLayout.addWidget(self.txtSummarySentance)
|
||||
self.txtSummarySentence = lineEditView(basicItemView)
|
||||
self.txtSummarySentence.setText("")
|
||||
self.txtSummarySentence.setObjectName("txtSummarySentence")
|
||||
self.verticalLayout.addWidget(self.txtSummarySentence)
|
||||
self.label_9 = QtWidgets.QLabel(basicItemView)
|
||||
self.label_9.setObjectName("label_9")
|
||||
self.verticalLayout.addWidget(self.label_9)
|
||||
|
@ -63,9 +64,9 @@ class Ui_basicItemView(object):
|
|||
self.lblPlanPOV.setText(_translate("basicItemView", "POV:"))
|
||||
self.lblGoal.setText(_translate("basicItemView", "Goal:"))
|
||||
self.txtGoal.setPlaceholderText(_translate("basicItemView", "Word count"))
|
||||
self.txtSummarySentance.setPlaceholderText(_translate("basicItemView", "One line summary"))
|
||||
self.txtSummarySentence.setPlaceholderText(_translate("basicItemView", "One line summary"))
|
||||
self.label_9.setText(_translate("basicItemView", "Few sentences summary:"))
|
||||
|
||||
from manuskript.ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser
|
||||
from manuskript.ui.views.cmbOutlineCharacterChoser import cmbOutlineCharacterChoser
|
||||
from manuskript.ui.views.lineEditView import lineEditView
|
||||
from manuskript.ui.views.textEditView import textEditView
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="cmbOutlinePersoChoser" name="cmbPOV">
|
||||
<widget class="cmbOutlineCharacterChoser" name="cmbPOV">
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
@ -84,7 +84,7 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="lineEditView" name="txtSummarySentance">
|
||||
<widget class="lineEditView" name="txtSummarySentence">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -112,9 +112,9 @@
|
|||
<header>manuskript.ui.views.textEditView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>cmbOutlinePersoChoser</class>
|
||||
<class>cmbOutlineCharacterChoser</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>manuskript.ui.views.cmbOutlinePersoChoser.h</header>
|
||||
<header>manuskript.ui.views.cmbOutlineCharacterChoser.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>lineEditView</class>
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import QSize, QModelIndex, Qt
|
||||
from PyQt5.QtGui import QPixmap, QColor, QIcon, QBrush
|
||||
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
|
||||
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QColorDialog
|
||||
|
||||
from manuskript.enums import Perso
|
||||
from manuskript.enums import Character
|
||||
from manuskript.functions import iconColor, mainWindow
|
||||
|
||||
|
||||
class persoTreeView(QTreeWidget):
|
||||
class characterTreeView(QTreeWidget):
|
||||
"""
|
||||
A QTreeWidget that displays characters from a characterModel in respect of their importance.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
QTreeWidget.__init__(self, parent)
|
||||
self._model = None
|
||||
|
@ -24,7 +28,7 @@ class persoTreeView(QTreeWidget):
|
|||
self._rootItem = QTreeWidgetItem()
|
||||
self.insertTopLevelItem(0, self._rootItem)
|
||||
|
||||
def setPersosModel(self, model):
|
||||
def setCharactersModel(self, model):
|
||||
self._model = model
|
||||
self._model.dataChanged.connect(self.updateMaybe)
|
||||
self._model.rowsInserted.connect(self.updateMaybe2)
|
||||
|
@ -39,11 +43,11 @@ class persoTreeView(QTreeWidget):
|
|||
if topLeft.parent() != QModelIndex():
|
||||
return
|
||||
|
||||
if topLeft.column() <= Perso.name.value <= bottomRight.column():
|
||||
if topLeft.column() <= Character.name.value <= bottomRight.column():
|
||||
# Update name
|
||||
self.updateNames()
|
||||
|
||||
elif topLeft.column() <= Perso.importance.value <= bottomRight.column():
|
||||
elif topLeft.column() <= Character.importance.value <= bottomRight.column():
|
||||
# Importance changed
|
||||
self.updateItems()
|
||||
|
||||
|
@ -56,16 +60,17 @@ class persoTreeView(QTreeWidget):
|
|||
for i in range(self.topLevelItemCount()):
|
||||
item = self.topLevelItem(i)
|
||||
|
||||
for c in range(item.childCount()):
|
||||
sub = item.child(c)
|
||||
for child in range(item.childCount()):
|
||||
sub = item.child(child)
|
||||
ID = sub.data(0, Qt.UserRole)
|
||||
if ID:
|
||||
if ID is not None:
|
||||
# Update name
|
||||
name = self._model.getPersoNameByID(ID)
|
||||
c = self._model.getCharacterByID(ID)
|
||||
name = c.name()
|
||||
sub.setText(0, name)
|
||||
# Update icon
|
||||
px = QPixmap(32, 32)
|
||||
color = QColor(self._model.getPersoColorByID(ID))
|
||||
color = c.color()
|
||||
px.fill(color)
|
||||
sub.setIcon(0, QIcon(px))
|
||||
|
||||
|
@ -78,10 +83,12 @@ class persoTreeView(QTreeWidget):
|
|||
|
||||
self._updating = True
|
||||
self.clear()
|
||||
persos = self._model.getPersosByImportance()
|
||||
characters = self._model.getCharactersByImportance()
|
||||
|
||||
h = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
|
||||
|
||||
for i in range(3):
|
||||
# Create category item
|
||||
cat = QTreeWidgetItem(self, [h[i]])
|
||||
cat.setBackground(0, QBrush(QColor(Qt.blue).lighter(190)))
|
||||
cat.setForeground(0, QBrush(Qt.darkBlue))
|
||||
|
@ -92,23 +99,68 @@ class persoTreeView(QTreeWidget):
|
|||
self.addTopLevelItem(cat)
|
||||
# cat.setChildIndicatorPolicy(cat.DontShowIndicator)
|
||||
|
||||
for ID in persos[i]:
|
||||
name = self._model.getPersoNameByID(ID)
|
||||
for c in characters[i]:
|
||||
name = c.name()
|
||||
# Check if name passes filter
|
||||
if not self._filter.lower() in name.lower():
|
||||
continue
|
||||
|
||||
item = QTreeWidgetItem(cat, [name])
|
||||
item.setData(0, Qt.UserRole, ID)
|
||||
item.setData(0, Qt.UserRole, c.ID())
|
||||
px = QPixmap(32, 32)
|
||||
color = QColor(self._model.getPersoColorByID(ID))
|
||||
color = QColor(c.color())
|
||||
px.fill(color)
|
||||
item.setIcon(0, QIcon(px))
|
||||
|
||||
if ID == self._lastID:
|
||||
if c.ID() == self._lastID:
|
||||
self.setCurrentItem(item)
|
||||
|
||||
self.expandAll()
|
||||
self._updating = False
|
||||
|
||||
def removeCharacter(self):
|
||||
"""
|
||||
Removes selected character.
|
||||
"""
|
||||
ID = self.currentCharacterID()
|
||||
if ID:
|
||||
self._model.removeCharacter(ID)
|
||||
|
||||
def choseCharacterColor(self):
|
||||
ID = self.currentCharacterID()
|
||||
c = self._model.getCharacterByID(ID)
|
||||
if c:
|
||||
color = iconColor(c.icon)
|
||||
else:
|
||||
color = Qt.white
|
||||
self.colorDialog = QColorDialog(color, mainWindow())
|
||||
color = self.colorDialog.getColor(color)
|
||||
if color.isValid():
|
||||
c.setColor(color)
|
||||
mainWindow().updateCharacterColor(ID)
|
||||
|
||||
def addCharacterInfo(self):
|
||||
self._model.addCharacterInfo(self.currentCharacterID())
|
||||
|
||||
def removeCharacterInfo(self):
|
||||
self._model.removeCharacterInfo(self.currentCharacterID(),
|
||||
)
|
||||
|
||||
def currentCharacterID(self):
|
||||
ID = None
|
||||
if self.currentItem():
|
||||
ID = self.currentItem().data(0, Qt.UserRole)
|
||||
|
||||
return ID
|
||||
|
||||
def currentCharacter(self):
|
||||
"""
|
||||
Returns the selected character
|
||||
@return: Character
|
||||
"""
|
||||
ID = self.currentCharacterID()
|
||||
return self._model.getCharacterByID(ID)
|
||||
|
||||
def getItemByID(self, ID):
|
||||
for t in range(self.topLevelItemCount()):
|
||||
for i in range(self.topLevelItem(t).childCount()):
|
||||
|
@ -116,13 +168,6 @@ class persoTreeView(QTreeWidget):
|
|||
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
|
|
@ -8,7 +8,7 @@ from manuskript.enums import Outline
|
|||
from manuskript.functions import toInt
|
||||
|
||||
|
||||
class cmbOutlinePersoChoser(QComboBox):
|
||||
class cmbOutlineCharacterChoser(QComboBox):
|
||||
def __init__(self, parent=None):
|
||||
QComboBox.__init__(self, parent)
|
||||
self.activated[int].connect(self.submit)
|
||||
|
@ -18,9 +18,12 @@ class cmbOutlinePersoChoser(QComboBox):
|
|||
self._updating = False
|
||||
self._various = False
|
||||
|
||||
def setModels(self, mdlPersos, mdlOutline):
|
||||
self.mdlPersos = mdlPersos
|
||||
self.mdlPersos.dataChanged.connect(self.updateItems)
|
||||
def setModels(self, mdlCharacter, mdlOutline):
|
||||
self.mdlCharacters = mdlCharacter
|
||||
self.mdlCharacters.dataChanged.connect(self.updateItems)
|
||||
self.mdlCharacters.rowsInserted.connect(self.updateItems)
|
||||
self.mdlCharacters.rowsRemoved.connect(self.updateItems)
|
||||
|
||||
self.mdlOutline = mdlOutline
|
||||
self.mdlOutline.dataChanged.connect(self.update)
|
||||
self.updateItems()
|
||||
|
@ -37,14 +40,14 @@ class cmbOutlinePersoChoser(QComboBox):
|
|||
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))
|
||||
for i in range(self.mdlCharacters.rowCount()):
|
||||
imp = toInt(self.mdlCharacters.importance(i))
|
||||
|
||||
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.addItem(self.mdlCharacters.icon(i), self.mdlCharacters.name(i), self.mdlCharacters.ID(i))
|
||||
self.setItemData(self.count() - 1, self.mdlCharacters.name(i), Qt.ToolTipRole)
|
||||
|
||||
self._various = False
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- 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)
|
||||
self._column = Outline.type.value
|
||||
self._index = None
|
||||
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:
|
||||
index = index.sibling(index.row(), self._column)
|
||||
self._index = index
|
||||
# Disabled if item type is not text
|
||||
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():
|
||||
if i.column() != self._column:
|
||||
i = i.sibling(i.row(), self._column)
|
||||
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:
|
||||
if topLeft.row() <= i.row() <= bottomRight.row():
|
||||
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"))
|
||||
f = self.font()
|
||||
f.setItalic(True)
|
||||
self.setItemData(0, f, Qt.FontRole)
|
||||
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
|
|
@ -38,7 +38,7 @@ class corkDelegate(QStyledItemDelegate):
|
|||
|
||||
if self.mainLineRect.contains(self.lastPos):
|
||||
# One line summary
|
||||
self.editing = Outline.summarySentance
|
||||
self.editing = Outline.summarySentence
|
||||
edt = QLineEdit(parent)
|
||||
edt.setFocusPolicy(Qt.StrongFocus)
|
||||
edt.setFrame(False)
|
||||
|
@ -69,12 +69,16 @@ class corkDelegate(QStyledItemDelegate):
|
|||
edt = QPlainTextEdit(parent)
|
||||
edt.setFocusPolicy(Qt.StrongFocus)
|
||||
edt.setFrameShape(QFrame.NoFrame)
|
||||
edt.setPlaceholderText(self.tr("Full summary"))
|
||||
try:
|
||||
# QPlainTextEdit.setPlaceholderText was introduced in Qt 5.3
|
||||
edt.setPlaceholderText(self.tr("Full summary"))
|
||||
except AttributeError:
|
||||
pass
|
||||
return edt
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
|
||||
if self.editing == Outline.summarySentance:
|
||||
if self.editing == Outline.summarySentence:
|
||||
# One line summary
|
||||
editor.setGeometry(self.mainLineRect)
|
||||
|
||||
|
@ -89,9 +93,9 @@ class corkDelegate(QStyledItemDelegate):
|
|||
def setEditorData(self, editor, index):
|
||||
item = index.internalPointer()
|
||||
|
||||
if self.editing == Outline.summarySentance:
|
||||
if self.editing == Outline.summarySentence:
|
||||
# One line summary
|
||||
editor.setText(item.data(Outline.summarySentance.value))
|
||||
editor.setText(item.data(Outline.summarySentence.value))
|
||||
|
||||
elif self.editing == Outline.title:
|
||||
# Title
|
||||
|
@ -103,9 +107,9 @@ class corkDelegate(QStyledItemDelegate):
|
|||
|
||||
def setModelData(self, editor, model, index):
|
||||
|
||||
if self.editing == Outline.summarySentance:
|
||||
if self.editing == Outline.summarySentence:
|
||||
# One line summary
|
||||
model.setData(index.sibling(index.row(), Outline.summarySentance.value), editor.text())
|
||||
model.setData(index.sibling(index.row(), Outline.summarySentence.value), editor.text())
|
||||
|
||||
elif self.editing == Outline.title:
|
||||
# Title
|
||||
|
@ -133,7 +137,7 @@ 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.summarySentence.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))
|
||||
|
@ -218,7 +222,7 @@ class corkDelegate(QStyledItemDelegate):
|
|||
p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())
|
||||
|
||||
# One line summary background
|
||||
lineSummary = item.data(Outline.summarySentance.value)
|
||||
lineSummary = item.data(Outline.summarySentence.value)
|
||||
fullSummary = item.data(Outline.summaryFull.value)
|
||||
if lineSummary or not fullSummary:
|
||||
m = self.margin
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
from PyQt5.QtWidgets import QListView
|
||||
|
||||
from manuskript import settings
|
||||
from manuskript.functions import findBackground
|
||||
from manuskript.ui.views.corkDelegate import corkDelegate
|
||||
from manuskript.ui.views.dndView import dndView
|
||||
from manuskript.ui.views.outlineBasics import outlineBasics
|
||||
|
@ -24,12 +25,13 @@ class corkView(QListView, dndView, outlineBasics):
|
|||
self.updateBackground()
|
||||
|
||||
def updateBackground(self):
|
||||
img = findBackground(settings.corkBackground["image"])
|
||||
self.setStyleSheet("""QListView {{
|
||||
background:{color};
|
||||
background-image: url({url});
|
||||
}}""".format(
|
||||
color=settings.corkBackground["color"],
|
||||
url=settings.corkBackground["image"]
|
||||
url=img
|
||||
))
|
||||
|
||||
def dragMoveEvent(self, event):
|
||||
|
|
|
@ -11,14 +11,14 @@ class metadataView(QWidget, Ui_metadataView):
|
|||
QWidget.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self._lastIndexes = None
|
||||
self.txtSummarySentance.setColumn(Outline.summarySentance.value)
|
||||
self.txtSummarySentence.setColumn(Outline.summarySentence.value)
|
||||
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)
|
||||
def setModels(self, mdlOutline, mdlCharacter, mdlLabels, mdlStatus):
|
||||
self.properties.setModels(mdlOutline, mdlCharacter, mdlLabels, mdlStatus)
|
||||
self.txtSummarySentence.setModel(mdlOutline)
|
||||
self.txtSummaryFull.setModel(mdlOutline)
|
||||
self.txtNotes.setModel(mdlOutline)
|
||||
self.revisions.setModel(mdlOutline)
|
||||
|
@ -49,7 +49,7 @@ class metadataView(QWidget, Ui_metadataView):
|
|||
elif len(indexes) == 1:
|
||||
self.setEnabled(True)
|
||||
idx = indexes[0]
|
||||
self.txtSummarySentance.setCurrentModelIndex(idx)
|
||||
self.txtSummarySentence.setCurrentModelIndex(idx)
|
||||
self.txtSummaryFull.setCurrentModelIndex(idx)
|
||||
self.txtNotes.setCurrentModelIndex(idx)
|
||||
self.revisions.setEnabled(True)
|
||||
|
@ -57,7 +57,7 @@ class metadataView(QWidget, Ui_metadataView):
|
|||
|
||||
else:
|
||||
self.setEnabled(True)
|
||||
self.txtSummarySentance.setCurrentModelIndexes(indexes)
|
||||
self.txtSummarySentence.setCurrentModelIndexes(indexes)
|
||||
self.txtSummaryFull.setCurrentModelIndexes(indexes)
|
||||
self.txtNotes.setCurrentModelIndexes(indexes)
|
||||
self.revisions.setEnabled(False)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/views/metadataView_ui.ui'
|
||||
#
|
||||
# Created: Mon Feb 8 09:48:05 2016
|
||||
# Created: Wed Mar 2 00:30:18 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -43,11 +43,11 @@ class Ui_metadataView(object):
|
|||
self.verticalLayout_22.setSpacing(0)
|
||||
self.verticalLayout_22.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_22.setObjectName("verticalLayout_22")
|
||||
self.txtSummarySentance = lineEditView(self.grpSummary)
|
||||
self.txtSummarySentance.setInputMask("")
|
||||
self.txtSummarySentance.setFrame(False)
|
||||
self.txtSummarySentance.setObjectName("txtSummarySentance")
|
||||
self.verticalLayout_22.addWidget(self.txtSummarySentance)
|
||||
self.txtSummarySentence = lineEditView(self.grpSummary)
|
||||
self.txtSummarySentence.setInputMask("")
|
||||
self.txtSummarySentence.setFrame(False)
|
||||
self.txtSummarySentence.setObjectName("txtSummarySentence")
|
||||
self.verticalLayout_22.addWidget(self.txtSummarySentence)
|
||||
self.line = QtWidgets.QFrame(self.grpSummary)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Plain)
|
||||
self.line.setLineWidth(0)
|
||||
|
@ -95,15 +95,15 @@ class Ui_metadataView(object):
|
|||
metadataView.setWindowTitle(_translate("metadataView", "Form"))
|
||||
self.grpProperties.setTitle(_translate("metadataView", "Properties"))
|
||||
self.grpSummary.setTitle(_translate("metadataView", "Summary"))
|
||||
self.txtSummarySentance.setPlaceholderText(_translate("metadataView", "One line summary"))
|
||||
self.txtSummarySentence.setPlaceholderText(_translate("metadataView", "One line summary"))
|
||||
self.txtSummaryFull.setPlaceholderText(_translate("metadataView", "Full summary"))
|
||||
self.grpNotes.setTitle(_translate("metadataView", "Notes / References"))
|
||||
self.txtNotes.setPlaceholderText(_translate("metadataView", "Notes / References"))
|
||||
self.grpRevisions.setTitle(_translate("metadataView", "Revisions"))
|
||||
|
||||
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
|
||||
from manuskript.ui.views.lineEditView import lineEditView
|
||||
from manuskript.ui.collapsibleGroupBox2 import collapsibleGroupBox2
|
||||
from manuskript.ui.revisions import revisions
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="lineEditView" name="txtSummarySentance">
|
||||
<widget class="lineEditView" name="txtSummarySentence">
|
||||
<property name="inputMask">
|
||||
<string/>
|
||||
</property>
|
||||
|
|
|
@ -83,12 +83,12 @@ class outlineBasics(QAbstractItemView):
|
|||
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)
|
||||
for i in range(mw.mdlCharacter.rowCount()):
|
||||
a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i), self.menuPOV)
|
||||
a.triggered.connect(mpr.map)
|
||||
mpr.setMapping(a, int(mw.mdlPersos.ID(i)))
|
||||
mpr.setMapping(a, int(mw.mdlCharacter.ID(i)))
|
||||
|
||||
imp = toInt(mw.mdlPersos.importance(i))
|
||||
imp = toInt(mw.mdlCharacter.importance(i))
|
||||
|
||||
menus[2 - imp].addAction(a)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ from PyQt5.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem, QStyle, Q
|
|||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from manuskript import settings
|
||||
from manuskript.enums import Perso, Outline
|
||||
from manuskript.enums import Character, Outline
|
||||
from manuskript.functions import outlineItemColors, mixColors, colorifyPixmap, toInt, toFloat, drawProgress
|
||||
|
||||
|
||||
|
@ -92,18 +92,18 @@ class outlineTitleDelegate(QStyledItemDelegate):
|
|||
# QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
||||
|
||||
class outlinePersoDelegate(QStyledItemDelegate):
|
||||
def __init__(self, mdlPersos, parent=None):
|
||||
class outlineCharacterDelegate(QStyledItemDelegate):
|
||||
def __init__(self, mdlCharacter, parent=None):
|
||||
QStyledItemDelegate.__init__(self, parent)
|
||||
self.mdlPersos = mdlPersos
|
||||
self.mdlCharacter = mdlCharacter
|
||||
|
||||
def 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)
|
||||
character = self.mdlCharacter.getCharacterByID(index.data())
|
||||
if character:
|
||||
item = character.index(Character.name.value)
|
||||
|
||||
opt = QStyleOptionViewItem(option)
|
||||
self.initStyleOption(opt, item)
|
||||
|
@ -136,13 +136,13 @@ class outlinePersoDelegate(QStyledItemDelegate):
|
|||
editor.setItemData(editor.count() - 1, QBrush(QColor(Qt.blue).lighter(190)), Qt.BackgroundRole)
|
||||
item = editor.model().item(editor.count() - 1)
|
||||
item.setFlags(Qt.ItemIsEnabled)
|
||||
for i in range(self.mdlPersos.rowCount()):
|
||||
imp = toInt(self.mdlPersos.importance(i))
|
||||
for i in range(self.mdlCharacter.rowCount()):
|
||||
imp = toInt(self.mdlCharacter.importance(i))
|
||||
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)
|
||||
editor.addItem(self.mdlCharacter.icon(i), self.mdlCharacter.name(i), self.mdlCharacter.ID(i))
|
||||
editor.setItemData(editor.count() - 1, self.mdlCharacter.name(i), Qt.ToolTipRole)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
|
@ -158,18 +158,18 @@ class outlinePersoDelegate(QStyledItemDelegate):
|
|||
# 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)
|
||||
itemIndex = QModelIndex()
|
||||
character = self.mdlCharacter.getCharacterByID(index.data())
|
||||
if character:
|
||||
itemIndex = character.index(Character.name.value)
|
||||
|
||||
opt = QStyleOptionViewItem(option)
|
||||
self.initStyleOption(opt, item)
|
||||
self.initStyleOption(opt, itemIndex)
|
||||
|
||||
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 self.mdlPersos.data(index) not in ["", None]:
|
||||
if itemIndex.isValid() and self.mdlCharacter.data(itemIndex) not in ["", None]:
|
||||
opt = QStyleOptionComboBox()
|
||||
opt.rect = option.rect
|
||||
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
|
||||
|
@ -278,7 +278,7 @@ class outlineStatusDelegate(QStyledItemDelegate):
|
|||
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"]:
|
||||
if index.isValid() and index.internalPointer().data(Outline.status.value) not in ["", None, "0", 0]:
|
||||
opt = QStyleOptionComboBox()
|
||||
opt.rect = option.rect
|
||||
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
|
||||
|
@ -344,7 +344,7 @@ class outlineLabelDelegate(QStyledItemDelegate):
|
|||
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"]:
|
||||
if index.isValid() and index.internalPointer().data(Outline.label.value) not in ["", None, "0", 0]:
|
||||
opt = QStyleOptionComboBox()
|
||||
opt.rect = option.rect
|
||||
r = qApp.style().subControlRect(QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxArrow)
|
||||
|
|
|
@ -6,25 +6,25 @@ 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, \
|
||||
from manuskript.ui.views.outlineDelegates import outlineTitleDelegate, outlineCharacterDelegate, outlineCompileDelegate, \
|
||||
outlineStatusDelegate, outlineGoalPercentageDelegate, outlineLabelDelegate
|
||||
|
||||
|
||||
class outlineView(QTreeView, dndView, outlineBasics):
|
||||
def __init__(self, parent=None, modelPersos=None, modelLabels=None, modelStatus=None):
|
||||
def __init__(self, parent=None, modelCharacters=None, modelLabels=None, modelStatus=None):
|
||||
QTreeView.__init__(self, parent)
|
||||
dndView.__init__(self)
|
||||
outlineBasics.__init__(self, parent)
|
||||
|
||||
self.modelPersos = modelPersos
|
||||
self.modelCharacters = modelCharacters
|
||||
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 setModelCharacters(self, model):
|
||||
# This is used by outlineCharacterDelegate to select character
|
||||
self.modelCharacters = model
|
||||
|
||||
def setModelLabels(self, model):
|
||||
# This is used by outlineLabelDelegate to display labels
|
||||
|
@ -41,8 +41,8 @@ class outlineView(QTreeView, dndView, outlineBasics):
|
|||
self.outlineTitleDelegate = outlineTitleDelegate(self)
|
||||
# self.outlineTitleDelegate.setView(self)
|
||||
self.setItemDelegateForColumn(Outline.title.value, self.outlineTitleDelegate)
|
||||
self.outlinePersoDelegate = outlinePersoDelegate(self.modelPersos)
|
||||
self.setItemDelegateForColumn(Outline.POV.value, self.outlinePersoDelegate)
|
||||
self.outlineCharacterDelegate = outlineCharacterDelegate(self.modelCharacters)
|
||||
self.setItemDelegateForColumn(Outline.POV.value, self.outlineCharacterDelegate)
|
||||
self.outlineCompileDelegate = outlineCompileDelegate()
|
||||
self.setItemDelegateForColumn(Outline.compile.value, self.outlineCompileDelegate)
|
||||
self.outlineStatusDelegate = outlineStatusDelegate(self.modelStatus)
|
||||
|
@ -65,6 +65,10 @@ class outlineView(QTreeView, dndView, outlineBasics):
|
|||
self.header().setSectionResizeMode(Outline.goalPercentage.value, QHeaderView.ResizeToContents)
|
||||
|
||||
def hideColumns(self):
|
||||
if not self.model():
|
||||
# outlineView is probably not initialized, because editorWidgets shows index cards or text.
|
||||
return
|
||||
|
||||
for c in range(self.model().columnCount()):
|
||||
self.hideColumn(c)
|
||||
for c in settings.outlineViewColumns:
|
||||
|
|
|
@ -12,11 +12,10 @@ class propertiesView(QWidget, Ui_propertiesView):
|
|||
self.setupUi(self)
|
||||
self.txtGoal.setColumn(Outline.setGoal.value)
|
||||
|
||||
def setModels(self, mdlOutline, mdlPersos, mdlLabels, mdlStatus):
|
||||
self.cmbPOV.setModels(mdlPersos, mdlOutline)
|
||||
def setModels(self, mdlOutline, mdlCharacter, mdlLabels, mdlStatus):
|
||||
self.cmbPOV.setModels(mdlCharacter, mdlOutline)
|
||||
self.cmbLabel.setModels(mdlLabels, mdlOutline)
|
||||
self.cmbStatus.setModels(mdlStatus, mdlOutline)
|
||||
self.cmbType.setModel(mdlOutline)
|
||||
self.chkCompile.setModel(mdlOutline)
|
||||
self.txtTitle.setModel(mdlOutline)
|
||||
self.txtGoal.setModel(mdlOutline)
|
||||
|
@ -52,8 +51,6 @@ class propertiesView(QWidget, Ui_propertiesView):
|
|||
self.txtTitle.setCurrentModelIndex(idx)
|
||||
self.txtGoal.setCurrentModelIndex(idx)
|
||||
|
||||
self.cmbType.setCurrentModelIndex(idx)
|
||||
|
||||
else:
|
||||
self.setEnabled(True)
|
||||
self.setLabelsItalic(True)
|
||||
|
@ -64,8 +61,6 @@ class propertiesView(QWidget, Ui_propertiesView):
|
|||
self.cmbLabel.setCurrentModelIndexes(indexes)
|
||||
self.cmbStatus.setCurrentModelIndexes(indexes)
|
||||
|
||||
self.cmbType.setCurrentModelIndexes(indexes)
|
||||
|
||||
def setLabelsItalic(self, value):
|
||||
f = self.lblPOV.font()
|
||||
f.setItalic(value)
|
||||
|
|
|
@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_propertiesView(object):
|
||||
def setupUi(self, propertiesView):
|
||||
propertiesView.setObjectName("propertiesView")
|
||||
propertiesView.resize(192, 159)
|
||||
propertiesView.resize(192, 186)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(propertiesView)
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
|
@ -36,7 +36,7 @@ class Ui_propertiesView(object):
|
|||
self.lblPOV = QtWidgets.QLabel(self.page)
|
||||
self.lblPOV.setObjectName("lblPOV")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.lblPOV)
|
||||
self.cmbPOV = cmbOutlinePersoChoser(self.page)
|
||||
self.cmbPOV = cmbOutlineCharacterChoser(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
|
@ -71,14 +71,14 @@ class Ui_propertiesView(object):
|
|||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.cmbLabel)
|
||||
self.lblCompile = QtWidgets.QLabel(self.page)
|
||||
self.lblCompile.setObjectName("lblCompile")
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.lblCompile)
|
||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.lblCompile)
|
||||
self.chkCompile = chkOutlineCompile(self.page)
|
||||
self.chkCompile.setText("")
|
||||
self.chkCompile.setObjectName("chkCompile")
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.chkCompile)
|
||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.chkCompile)
|
||||
self.lblGoal = QtWidgets.QLabel(self.page)
|
||||
self.lblGoal.setObjectName("lblGoal")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.lblGoal)
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.lblGoal)
|
||||
self.txtGoal = lineEditView(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
|
@ -89,19 +89,7 @@ class Ui_propertiesView(object):
|
|||
self.txtGoal.setStyleSheet("border-radius: 6px;")
|
||||
self.txtGoal.setFrame(False)
|
||||
self.txtGoal.setObjectName("txtGoal")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.txtGoal)
|
||||
self.lblLabel_2 = QtWidgets.QLabel(self.page)
|
||||
self.lblLabel_2.setObjectName("lblLabel_2")
|
||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.lblLabel_2)
|
||||
self.cmbType = cmbOutlineTypeChoser(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.cmbType.sizePolicy().hasHeightForWidth())
|
||||
self.cmbType.setSizePolicy(sizePolicy)
|
||||
self.cmbType.setFrame(False)
|
||||
self.cmbType.setObjectName("cmbType")
|
||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.cmbType)
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.txtGoal)
|
||||
self.verticalLayout_2.addLayout(self.formLayout)
|
||||
self.stack.addWidget(self.page)
|
||||
self.page_2 = QtWidgets.QWidget()
|
||||
|
@ -115,7 +103,7 @@ class Ui_propertiesView(object):
|
|||
self.lblPOV_2 = QtWidgets.QLabel(self.page_2)
|
||||
self.lblPOV_2.setObjectName("lblPOV_2")
|
||||
self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.lblPOV_2)
|
||||
self.cmbPOVMulti = cmbOutlinePersoChoser(self.page_2)
|
||||
self.cmbPOVMulti = cmbOutlineCharacterChoser(self.page_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
|
@ -186,7 +174,6 @@ class Ui_propertiesView(object):
|
|||
self.lblCompile.setText(_translate("propertiesView", "Compile"))
|
||||
self.lblGoal.setText(_translate("propertiesView", "Goal"))
|
||||
self.txtGoal.setPlaceholderText(_translate("propertiesView", "Word count"))
|
||||
self.lblLabel_2.setText(_translate("propertiesView", "Text type:"))
|
||||
self.lblPOV_2.setText(_translate("propertiesView", "POV"))
|
||||
self.label_31.setText(_translate("propertiesView", "Status"))
|
||||
self.label_34.setText(_translate("propertiesView", "Label"))
|
||||
|
@ -195,8 +182,7 @@ class Ui_propertiesView(object):
|
|||
self.txtGoalMulti.setPlaceholderText(_translate("propertiesView", "Word count"))
|
||||
|
||||
from manuskript.ui.views.chkOutlineCompile import chkOutlineCompile
|
||||
from manuskript.ui.views.cmbOutlineCharacterChoser import cmbOutlineCharacterChoser
|
||||
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
|
||||
|
|
|
@ -7,14 +7,23 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>192</width>
|
||||
<height>159</height>
|
||||
<height>186</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<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>
|
||||
|
@ -40,7 +49,16 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<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>
|
||||
|
@ -53,7 +71,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="cmbOutlinePersoChoser" name="cmbPOV">
|
||||
<widget class="cmbOutlineCharacterChoser" name="cmbPOV">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -105,28 +123,28 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lblCompile">
|
||||
<property name="text">
|
||||
<string>Compile</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="chkOutlineCompile" name="chkCompile">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="lblGoal">
|
||||
<property name="text">
|
||||
<string>Goal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="lineEditView" name="txtGoal">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
|
@ -148,26 +166,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lblLabel_2">
|
||||
<property name="text">
|
||||
<string>Text type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="cmbOutlineTypeChoser" name="cmbType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -177,7 +175,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>
|
||||
|
@ -190,7 +197,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="cmbOutlinePersoChoser" name="cmbPOVMulti">
|
||||
<widget class="cmbOutlineCharacterChoser" name="cmbPOVMulti">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -300,9 +307,9 @@
|
|||
<header>manuskript.ui.views.lineEditView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>cmbOutlinePersoChoser</class>
|
||||
<class>cmbOutlineCharacterChoser</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>manuskript.ui.views.cmbOutlinePersoChoser.h</header>
|
||||
<header>manuskript.ui.views.cmbOutlineCharacterChoser.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>cmbOutlineStatusChoser</class>
|
||||
|
@ -319,11 +326,6 @@
|
|||
<extends>QComboBox</extends>
|
||||
<header>manuskript.ui.views.cmbOutlineLabelChoser.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>cmbOutlineTypeChoser</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>manuskript.ui.views.cmbOutlineTypeChoser.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtProperty
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
from manuskript.ui.views.sldImportance_ui import Ui_sldImportance
|
||||
|
||||
from manuskript.functions import toInt
|
||||
from manuskript.ui.sldImportance_ui import Ui_sldImportance
|
||||
|
||||
|
||||
class sldImportance(QWidget, Ui_sldImportance):
|
|
@ -1,12 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/sldImportance_ui.ui'
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/views/sldImportance_ui.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.4.1
|
||||
# Created: Thu Mar 3 18:52:22 2016
|
||||
# by: PyQt5 UI code generator 5.2.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_sldImportance(object):
|
||||
def setupUi(self, sldImportance):
|
|
@ -1,12 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
from PyQt5.QtCore import Qt, QTimer, QRectF
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics, QFontMetricsF
|
||||
from PyQt5.QtGui import QBrush, QPen, QFontMetrics, QFontMetricsF, QColor
|
||||
from PyQt5.QtWidgets import QWidget, QGraphicsScene, QGraphicsSimpleTextItem, QMenu, QAction, QGraphicsRectItem, \
|
||||
QGraphicsLineItem, QGraphicsEllipseItem
|
||||
|
||||
from manuskript.enums import Outline
|
||||
from manuskript.functions import randomColor
|
||||
from manuskript.models import references
|
||||
from manuskript.ui.views.storylineView_ui import Ui_storylineView
|
||||
|
||||
|
@ -32,33 +31,69 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
def generateMenu(self):
|
||||
m = QMenu()
|
||||
|
||||
for i in [
|
||||
self.tr("Show Plots"),
|
||||
self.tr("Show Characters"),
|
||||
self.tr("Show Objects"),
|
||||
]:
|
||||
a = QAction(i, m)
|
||||
a.setCheckable(True)
|
||||
a.setEnabled(False)
|
||||
m.addAction(a)
|
||||
self.actPlots = QAction(self.tr("Show Plots"), m)
|
||||
self.actPlots.setCheckable(True)
|
||||
self.actPlots.setChecked(True)
|
||||
self.actPlots.toggled.connect(self.reloadTimer.start)
|
||||
m.addAction(self.actPlots)
|
||||
|
||||
self.actCharacters = QAction(self.tr("Show Characters"), m)
|
||||
self.actCharacters.setCheckable(True)
|
||||
self.actCharacters.setChecked(False)
|
||||
self.actCharacters.toggled.connect(self.reloadTimer.start)
|
||||
m.addAction(self.actCharacters)
|
||||
|
||||
self.btnSettings.setMenu(m)
|
||||
|
||||
def setModels(self, mdlOutline, mdlPersos, mdlPlots):
|
||||
def setModels(self, mdlOutline, mdlCharacter, mdlPlots):
|
||||
self._mdlPlots = mdlPlots
|
||||
# self._mdlPlots.dataChanged.connect(self.refresh)
|
||||
# self._mdlPlots.rowsInserted.connect(self.refresh)
|
||||
|
||||
self._mdlOutline = mdlOutline
|
||||
self._mdlOutline.dataChanged.connect(self.reloadTimer.start)
|
||||
self._mdlOutline.dataChanged.connect(self.updateMaybe)
|
||||
|
||||
self._mdlPersos = mdlPersos
|
||||
self._mdlPersos.dataChanged.connect(self.reloadTimer.start)
|
||||
self._mdlCharacter = mdlCharacter
|
||||
self._mdlCharacter.dataChanged.connect(self.reloadTimer.start)
|
||||
|
||||
def updateMaybe(self, topLeft, bottomRight):
|
||||
if topLeft.column() <= Outline.notes.value <= bottomRight.column():
|
||||
self.reloadTimer.start
|
||||
|
||||
def plotReferences(self):
|
||||
"Returns a list of plot references"
|
||||
if not self._mdlPlots:
|
||||
pass
|
||||
|
||||
plotsID = self._mdlPlots.getPlotsByImportance()
|
||||
r = []
|
||||
for importance in plotsID:
|
||||
for ID in importance:
|
||||
ref = references.plotReference(ID)
|
||||
r.append(ref)
|
||||
|
||||
return r
|
||||
|
||||
def charactersReferences(self):
|
||||
"Returns a list of character references"
|
||||
if not self._mdlCharacter:
|
||||
pass
|
||||
|
||||
chars = self._mdlCharacter.getCharactersByImportance()
|
||||
r = []
|
||||
for importance in chars:
|
||||
for c in importance:
|
||||
ref = references.characterReference(c.ID())
|
||||
r.append(ref)
|
||||
|
||||
return r
|
||||
|
||||
def refresh(self):
|
||||
if not self._mdlPlots or not self._mdlOutline or not self._mdlPersos:
|
||||
pass
|
||||
if not self._mdlPlots or not self._mdlOutline or not self._mdlCharacter:
|
||||
return
|
||||
|
||||
if not self.isVisible():
|
||||
return
|
||||
|
||||
LINE_HEIGHT = 18
|
||||
SPACING = 3
|
||||
|
@ -82,24 +117,24 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
|
||||
MAX_LEVEL = maxLevel(root)
|
||||
|
||||
# Generate left entries
|
||||
# (As of now, plot only)
|
||||
plotsID = self._mdlPlots.getPlotsByImportance()
|
||||
# Get the list of tracked items (array of references)
|
||||
trackedItems = []
|
||||
fm = QFontMetrics(s.font())
|
||||
max_name = 0
|
||||
|
||||
for importance in plotsID:
|
||||
for ID in importance:
|
||||
name = self._mdlPlots.getPlotNameByID(ID)
|
||||
ref = references.plotReference(ID, searchable=True)
|
||||
if self.actPlots.isChecked():
|
||||
trackedItems += self.plotReferences()
|
||||
|
||||
trackedItems.append((ID, ref, name))
|
||||
max_name = max(fm.width(name), max_name)
|
||||
if self.actCharacters.isChecked():
|
||||
trackedItems += self.charactersReferences()
|
||||
|
||||
ROWS_HEIGHT = len(trackedItems) * (LINE_HEIGHT + SPACING )
|
||||
TITLE_WIDTH = max_name + 2 * SPACING
|
||||
|
||||
fm = QFontMetrics(s.font())
|
||||
max_name = 0
|
||||
for ref in trackedItems:
|
||||
name = references.title(ref)
|
||||
max_name = max(fm.width(name), max_name)
|
||||
|
||||
TITLE_WIDTH = max_name + 2 * SPACING
|
||||
|
||||
# Add Folders and Texts
|
||||
outline = OutlineRect(0, 0, 0, ROWS_HEIGHT + SPACING + MAX_LEVEL * LEVEL_HEIGHT)
|
||||
|
@ -150,9 +185,22 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
rectChild.setToolTip(references.tooltip(references.textReference(child.ID())))
|
||||
|
||||
# Find tracked references in that scene (or parent folders)
|
||||
for ID, ref, name in trackedItems:
|
||||
for ref in trackedItems:
|
||||
|
||||
result = []
|
||||
|
||||
# Tests if POV
|
||||
scenePOV = False # Will hold true of character is POV of the current text, not containing folder
|
||||
if references.type(ref) == references.CharacterLetter:
|
||||
ID = references.ID(ref)
|
||||
c = child
|
||||
while c:
|
||||
if c.POV() == ID:
|
||||
result.append(c.ID())
|
||||
if c == child: scenePOV = True
|
||||
c = c.parent()
|
||||
|
||||
# Search in notes/references
|
||||
c = child
|
||||
while c:
|
||||
result += references.findReferencesTo(ref, c, recursive=False)
|
||||
|
@ -162,7 +210,7 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
ref2 = result[0]
|
||||
|
||||
# Create a RefCircle with the reference
|
||||
c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2)
|
||||
c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2, important=scenePOV)
|
||||
|
||||
# Store it, with the position of that item, to display it on the line later on
|
||||
refCircles.append((ref, c, rect.mapToItem(outline, rectChild.pos())))
|
||||
|
@ -173,22 +221,34 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
|
||||
OUTLINE_WIDTH = itemWidth(root)
|
||||
|
||||
# Add Plots
|
||||
# Add Tracked items
|
||||
i = 0
|
||||
itemsRect = s.addRect(0, 0, 0, 0)
|
||||
itemsRect.setPos(0, MAX_LEVEL * LEVEL_HEIGHT + SPACING)
|
||||
|
||||
for ID, ref, name in trackedItems:
|
||||
color = randomColor()
|
||||
# Set of colors for plots (as long as they don't have their own colors)
|
||||
colors = [
|
||||
"#D97777", "#AE5F8C", "#D9A377", "#FFC2C2", "#FFDEC2", "#D2A0BC",
|
||||
"#7B0F0F", "#7B400F", "#620C3D", "#AA3939", "#AA6C39", "#882D61",
|
||||
"#4C0000", "#4C2200", "#3D0022",
|
||||
]
|
||||
|
||||
for ref in trackedItems:
|
||||
if references.type(ref) == references.CharacterLetter:
|
||||
color = self._mdlCharacter.getCharacterByID(references.ID(ref)).color()
|
||||
else:
|
||||
color = QColor(colors[i % len(colors)])
|
||||
|
||||
# Rect
|
||||
r = QGraphicsRectItem(0, 0, TITLE_WIDTH, LINE_HEIGHT, itemsRect)
|
||||
r.setPen(QPen(Qt.NoPen))
|
||||
r.setBrush(QBrush(color))
|
||||
r.setPos(0, i * LINE_HEIGHT + i * SPACING)
|
||||
r.setToolTip(references.tooltip(ref))
|
||||
i += 1
|
||||
|
||||
# Text
|
||||
name = references.title(ref)
|
||||
txt = QGraphicsSimpleTextItem(name, r)
|
||||
txt.setPos(r.boundingRect().center() - txt.boundingRect().center())
|
||||
|
||||
|
@ -198,7 +258,7 @@ class storylineView(QWidget, Ui_storylineView):
|
|||
line.setPos(TITLE_WIDTH, r.mapToScene(r.rect().center()).y())
|
||||
s.addItem(line)
|
||||
line.setPen(QPen(color, 5))
|
||||
line.setToolTip(self.tr("Plot: ") + name)
|
||||
line.setToolTip(references.tooltip(ref))
|
||||
|
||||
# We add the circles / references to text, on the line
|
||||
for ref2, circle, pos in refCircles:
|
||||
|
@ -225,13 +285,15 @@ class OutlineRect(QGraphicsRectItem):
|
|||
|
||||
|
||||
class RefCircle(QGraphicsEllipseItem):
|
||||
def __init__(self, x, y, diameter, parent=None, ID=None):
|
||||
def __init__(self, x, y, diameter, parent=None, ID=None, important=False):
|
||||
QGraphicsEllipseItem.__init__(self, x, y, diameter, diameter, parent)
|
||||
self.setBrush(Qt.white)
|
||||
self._ref = references.textReference(ID)
|
||||
self.setToolTip(references.tooltip(self._ref))
|
||||
self.setPen(QPen(Qt.black, 2))
|
||||
self.setAcceptHoverEvents(True)
|
||||
if important:
|
||||
self.setBrush(Qt.black)
|
||||
|
||||
def multiplyDiameter(self, factor):
|
||||
r1 = self.rect()
|
||||
|
|
|
@ -11,10 +11,9 @@ 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.MDFunctions import MDFormatSelection
|
||||
from manuskript.ui.editors.MMDHighlighter import MMDHighlighter
|
||||
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:
|
||||
|
@ -76,7 +75,11 @@ class textEditView(QTextEdit):
|
|||
|
||||
# Spellchecking
|
||||
if enchant and self.spellcheck:
|
||||
self._dict = enchant.Dict(self.currentDict if self.currentDict else enchant.get_default_language())
|
||||
try:
|
||||
self._dict = enchant.Dict(self.currentDict if self.currentDict else enchant.get_default_language())
|
||||
except enchant.errors.DictNotFoundError:
|
||||
self.spellcheck = False
|
||||
|
||||
else:
|
||||
self.spellcheck = False
|
||||
|
||||
|
@ -146,36 +149,25 @@ class textEditView(QTextEdit):
|
|||
self.updateText()
|
||||
|
||||
def setupEditorForIndex(self, index):
|
||||
# what type of text are we editing?
|
||||
# In which model are we editing?
|
||||
if type(index.model()) != outlineModel:
|
||||
self._textFormat = "text"
|
||||
return
|
||||
|
||||
# what type of text are we editing?
|
||||
if self._column not in [Outline.text.value, Outline.notes.value]:
|
||||
self._textFormat = "text"
|
||||
|
||||
else:
|
||||
item = index.internalPointer()
|
||||
if item.isHTML():
|
||||
self._textFormat = "html"
|
||||
elif item.isT2T():
|
||||
self._textFormat = "t2t"
|
||||
else:
|
||||
self._textFormat = "text"
|
||||
|
||||
# Accept richtext maybe
|
||||
if self._textFormat == "html":
|
||||
self.setAcceptRichText(True)
|
||||
else:
|
||||
self.setAcceptRichText(False)
|
||||
self._textFormat = "md"
|
||||
|
||||
# Setting highlighter
|
||||
if self._highlighting:
|
||||
item = index.internalPointer()
|
||||
if self._column == Outline.text.value and not item.isT2T():
|
||||
self.highlighter = basicHighlighter(self)
|
||||
if self._column in [Outline.text.value, Outline.notes.value]:
|
||||
self.highlighter = MMDHighlighter(self)
|
||||
else:
|
||||
self.highlighter = t2tHighlighter(self)
|
||||
self.highlighter = basicHighlighter(self)
|
||||
|
||||
self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat)
|
||||
|
||||
|
@ -190,11 +182,12 @@ class textEditView(QTextEdit):
|
|||
f = QFont()
|
||||
f.fromString(opt["font"])
|
||||
# self.setFont(f)
|
||||
self.setStyleSheet("""
|
||||
self.setStyleSheet("""QTextEdit{{
|
||||
background: {bg};
|
||||
color: {foreground};
|
||||
font-family: {ff};
|
||||
font-size: {fs};
|
||||
}}
|
||||
""".format(
|
||||
bg=opt["background"],
|
||||
foreground=opt["fontColor"],
|
||||
|
@ -235,15 +228,7 @@ class textEditView(QTextEdit):
|
|||
# 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():
|
||||
# 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():
|
||||
if topLeft.column() <= self._column <= bottomRight.column():
|
||||
self.updateText()
|
||||
|
||||
elif self._indexes:
|
||||
|
@ -279,15 +264,9 @@ class textEditView(QTextEdit):
|
|||
self._updating = True
|
||||
if self._index:
|
||||
self.disconnectDocument()
|
||||
if self._textFormat == "html":
|
||||
if self.toHtml() != toString(self._model.data(self._index)):
|
||||
# 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")
|
||||
self.document().setPlainText(toString(self._model.data(self._index)))
|
||||
if self.toPlainText() != toString(self._model.data(self._index)):
|
||||
# print(" Updating plaintext")
|
||||
self.document().setPlainText(toString(self._model.data(self._index)))
|
||||
self.reconnectDocument()
|
||||
|
||||
elif self._indexes:
|
||||
|
@ -304,7 +283,6 @@ class textEditView(QTextEdit):
|
|||
break
|
||||
|
||||
if same:
|
||||
# Assuming that we don't use HTML with multiple items
|
||||
self.document().setPlainText(t[0])
|
||||
else:
|
||||
self.document().setPlainText("")
|
||||
|
@ -323,26 +301,11 @@ class textEditView(QTextEdit):
|
|||
# print("Submitting", self.objectName())
|
||||
if self._index:
|
||||
# item = self._index.internalPointer()
|
||||
if self._textFormat == "html":
|
||||
if self.toHtml() != self._model.data(self._index):
|
||||
# print(" Submitting html")
|
||||
self._updating = True
|
||||
html = self.toHtml()
|
||||
# We don't store paragraph and font settings
|
||||
html = re.sub(r"font-family:.*?;\s*", "", html)
|
||||
html = re.sub(r"font-size:.*?;\s*", "", html)
|
||||
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)
|
||||
self._model.setData(self._index, html)
|
||||
self._updating = False
|
||||
else:
|
||||
if self.toPlainText() != self._model.data(self._index):
|
||||
# print(" Submitting plain text")
|
||||
self._updating = True
|
||||
self._model.setData(self._index, self.toPlainText())
|
||||
self._updating = False
|
||||
if self.toPlainText() != self._model.data(self._index):
|
||||
# print(" Submitting plain text")
|
||||
self._updating = True
|
||||
self._model.setData(self._index, self.toPlainText())
|
||||
self._updating = False
|
||||
|
||||
elif self._indexes:
|
||||
self._updating = True
|
||||
|
@ -393,7 +356,13 @@ class textEditView(QTextEdit):
|
|||
def toggleSpellcheck(self, v):
|
||||
self.spellcheck = v
|
||||
if enchant and self.spellcheck and not self._dict:
|
||||
self._dict = enchant.Dict(self.currentDict if self.currentDict else enchant.get_default_language())
|
||||
if self.currentDict:
|
||||
self._dict = enchant.Dict(self.currentDict)
|
||||
elif enchant.dict_exists(enchant.get_default_language()):
|
||||
self._dict = enchant.Dict(enchant.get_default_language())
|
||||
else:
|
||||
self.spellcheck = False
|
||||
|
||||
if self.highlighter:
|
||||
self.highlighter.rehighlight()
|
||||
else:
|
||||
|
@ -430,15 +399,19 @@ class textEditView(QTextEdit):
|
|||
return popup_menu
|
||||
|
||||
# Select the word under the cursor.
|
||||
# But only if there is no selection (otherwise it's impossible to select more text to copy/cut)
|
||||
cursor = self.textCursor()
|
||||
# cursor = self.cursorForPosition(pos)
|
||||
cursor.select(QTextCursor.WordUnderCursor)
|
||||
self.setTextCursor(cursor)
|
||||
if not cursor.hasSelection():
|
||||
cursor.select(QTextCursor.WordUnderCursor)
|
||||
self.setTextCursor(cursor)
|
||||
|
||||
# Check if the selected word is misspelled and offer spelling
|
||||
# suggestions if it is.
|
||||
if cursor.hasSelection():
|
||||
text = str(cursor.selectedText())
|
||||
if not self._dict.check(text):
|
||||
valid = self._dict.check(text)
|
||||
selectedWord = cursor.selectedText()
|
||||
if not valid:
|
||||
spell_menu = QMenu(self.tr('Spelling Suggestions'), self)
|
||||
for word in self._dict.suggest(text):
|
||||
action = self.SpellAction(word, spell_menu)
|
||||
|
@ -448,7 +421,23 @@ class textEditView(QTextEdit):
|
|||
# suggestions.
|
||||
if len(spell_menu.actions()) != 0:
|
||||
popup_menu.insertSeparator(popup_menu.actions()[0])
|
||||
# Adds: add to dictionary
|
||||
addAction = QAction(self.tr("&Add to dictionary"), popup_menu)
|
||||
addAction.triggered.connect(self.addWordToDict)
|
||||
addAction.setData(selectedWord)
|
||||
popup_menu.insertAction(popup_menu.actions()[0], addAction)
|
||||
# Adds: suggestions
|
||||
popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
|
||||
# popup_menu.insertSeparator(popup_menu.actions()[0])
|
||||
|
||||
# If word was added to custom dict, give the possibility to remove it
|
||||
elif valid and self._dict.is_added(selectedWord):
|
||||
popup_menu.insertSeparator(popup_menu.actions()[0])
|
||||
# Adds: remove from dictionary
|
||||
rmAction = QAction(self.tr("&Remove from custom dictionary"), popup_menu)
|
||||
rmAction.triggered.connect(self.rmWordFromDict)
|
||||
rmAction.setData(selectedWord)
|
||||
popup_menu.insertAction(popup_menu.actions()[0], rmAction)
|
||||
|
||||
return popup_menu
|
||||
|
||||
|
@ -464,6 +453,16 @@ class textEditView(QTextEdit):
|
|||
|
||||
cursor.endEditBlock()
|
||||
|
||||
def addWordToDict(self):
|
||||
word = self.sender().data()
|
||||
self._dict.add(word)
|
||||
self.highlighter.rehighlight()
|
||||
|
||||
def rmWordFromDict(self):
|
||||
word = self.sender().data()
|
||||
self._dict.remove(word)
|
||||
self.highlighter.rehighlight()
|
||||
|
||||
###############################################################################
|
||||
# FORMATTING
|
||||
###############################################################################
|
||||
|
@ -488,66 +487,13 @@ class textEditView(QTextEdit):
|
|||
|
||||
def applyFormat(self, _format):
|
||||
|
||||
if self._textFormat == "html":
|
||||
if self._textFormat == "md":
|
||||
|
||||
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 = QTextBlockFormat()
|
||||
bf.setAlignment(
|
||||
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)
|
||||
MDFormatSelection(self, 0)
|
||||
elif _format == "Italic":
|
||||
t2tFormatSelection(self, 1)
|
||||
elif _format == "Underline":
|
||||
t2tFormatSelection(self, 2)
|
||||
MDFormatSelection(self, 1)
|
||||
elif _format == "Code":
|
||||
MDFormatSelection(self, 2)
|
||||
elif _format == "Clear":
|
||||
t2tClearFormat(self)
|
||||
MDFormatSelection(self)
|
||||
|
|
|
@ -105,7 +105,7 @@ class treeTitleDelegate(QStyledItemDelegate):
|
|||
if extraText:
|
||||
extraText = " ({}%)".format(extraText)
|
||||
elif settings.viewSettings["Tree"]["InfoFolder"] == "Summary":
|
||||
extraText = item.data(Outline.summarySentance.value)
|
||||
extraText = item.data(Outline.summarySentence.value)
|
||||
if extraText:
|
||||
extraText = " - {}".format(extraText)
|
||||
|
||||
|
@ -118,7 +118,7 @@ class treeTitleDelegate(QStyledItemDelegate):
|
|||
if extraText:
|
||||
extraText = " ({}%)".format(extraText)
|
||||
elif settings.viewSettings["Tree"]["InfoText"] == "Summary":
|
||||
extraText = item.data(Outline.summarySentance.value)
|
||||
extraText = item.data(Outline.summarySentence.value)
|
||||
if extraText:
|
||||
extraText = " - {}".format(extraText)
|
||||
|
||||
|
|
|
@ -7,14 +7,15 @@ import os
|
|||
|
||||
from PyQt5.QtCore import QSettings, QRegExp, Qt, QDir
|
||||
from PyQt5.QtGui import QIcon, QBrush, QColor, QStandardItemModel, QStandardItem
|
||||
from PyQt5.QtWidgets import QWidget, QAction, QFileDialog, QSpinBox, QLineEdit, QLabel, QPushButton, QTreeWidgetItem
|
||||
from PyQt5.QtWidgets import QWidget, QAction, QFileDialog, QSpinBox, QLineEdit, QLabel, QPushButton, QTreeWidgetItem, \
|
||||
qApp
|
||||
|
||||
from manuskript import settings
|
||||
from manuskript.enums import Outline
|
||||
from manuskript.functions import mainWindow, iconFromColor, appPath
|
||||
from manuskript.models.characterModel import characterModel
|
||||
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.models.worldModel import worldModel
|
||||
from manuskript.ui.welcome_ui import Ui_welcome
|
||||
|
@ -65,7 +66,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
def getAutoLoadValues(self):
|
||||
sttgns = QSettings()
|
||||
if sttgns.contains("autoLoad"):
|
||||
autoLoad = True if sttgns.value("autoLoad") == "true" else False
|
||||
autoLoad = True if sttgns.value("autoLoad") in ["true", True] else False
|
||||
else:
|
||||
autoLoad = False
|
||||
if autoLoad and sttgns.contains("lastProject"):
|
||||
|
@ -88,7 +89,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
if sttgns.contains("recentFiles"):
|
||||
lst = sttgns.value("recentFiles")
|
||||
self.mw.menuRecents.clear()
|
||||
for f in lst:
|
||||
for f in [f for f in lst if os.path.exists(f)]:
|
||||
name = os.path.split(f)[1]
|
||||
a = QAction(name, self)
|
||||
a.setData(f)
|
||||
|
@ -114,6 +115,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
def loadRecentFile(self):
|
||||
act = self.sender()
|
||||
self.appendToRecentFiles(act.data())
|
||||
self.mw.closeProject()
|
||||
self.mw.loadProject(act.data())
|
||||
|
||||
###############################################################################
|
||||
|
@ -151,7 +153,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
self.tr("Manuskript project (*.msk)"))[0]
|
||||
|
||||
if filename:
|
||||
if filename[:-4] != ".msk":
|
||||
if filename[-4:] != ".msk":
|
||||
filename += ".msk"
|
||||
self.appendToRecentFiles(filename)
|
||||
self.loadDefaultDatas()
|
||||
|
@ -163,51 +165,49 @@ class welcome(QWidget, Ui_welcome):
|
|||
|
||||
def templates(self):
|
||||
return [
|
||||
(self.tr("Empty"), []),
|
||||
(self.tr("Empty fiction"), [], "Fiction"),
|
||||
(self.tr("Novel"), [
|
||||
(20, self.tr("Chapter")),
|
||||
(5, self.tr("Scene")),
|
||||
(500, None) # A line with None is word count
|
||||
]),
|
||||
], "Fiction"),
|
||||
(self.tr("Novella"), [
|
||||
(10, self.tr("Chapter")),
|
||||
(5, self.tr("Scene")),
|
||||
(500, None)
|
||||
]),
|
||||
], "Fiction"),
|
||||
(self.tr("Short Story"), [
|
||||
(10, self.tr("Scene")),
|
||||
(1000, None)
|
||||
]),
|
||||
], "Fiction"),
|
||||
(self.tr("Trilogy"), [
|
||||
(3, self.tr("Book")),
|
||||
(3, self.tr("Section")),
|
||||
(10, self.tr("Chapter")),
|
||||
(5, self.tr("Scene")),
|
||||
(500, None)
|
||||
]),
|
||||
], "Fiction"),
|
||||
(self.tr("Empty non-fiction"), [], "Non-fiction"),
|
||||
(self.tr("Research paper"), [
|
||||
(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"),
|
||||
], "Non-fiction")
|
||||
]
|
||||
|
||||
def changeTemplate(self, item, column):
|
||||
template = [i for i in self.templates() if i[0] == item.text(0)]
|
||||
self.btnCreate.setText(self.btnCreateText)
|
||||
|
||||
# Selected item is a template
|
||||
if len(template):
|
||||
self.template = template[0][1]
|
||||
self.template = template[0]
|
||||
self.updateTemplate()
|
||||
|
||||
# Selected item is a sample project
|
||||
elif item.data(0, Qt.UserRole):
|
||||
name = item.data(0, Qt.UserRole)
|
||||
# Clear templates
|
||||
self.template = self.templates()[0][1]
|
||||
self.template = self.templates()[0]
|
||||
self.updateTemplate()
|
||||
# Change button text
|
||||
self.btnCreate.setText("Open {}".format(name))
|
||||
|
@ -232,7 +232,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
|
||||
k = 0
|
||||
hasWC = False
|
||||
for d in self.template:
|
||||
for d in self.template[1]:
|
||||
spin = QSpinBox(self)
|
||||
spin.setRange(0, 999999)
|
||||
spin.setValue(d[0])
|
||||
|
@ -261,29 +261,29 @@ class welcome(QWidget, Ui_welcome):
|
|||
self.lytTemplate.addWidget(txt, k, 2)
|
||||
k += 1
|
||||
|
||||
self.btnAddWC.setEnabled(not hasWC and len(self.template) > 0)
|
||||
self.btnAddWC.setEnabled(not hasWC and len(self.template[1]) > 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:
|
||||
if len(self.template[1]) > 0 and \
|
||||
self.template[1][len(self.template[1]) - 1][1] == None:
|
||||
# has word cound, so insert before
|
||||
self.template.insert(len(self.template) - 1, (10, self.tr("Text")))
|
||||
self.template[1].insert(len(self.template[1]) - 1, (10, self.tr("Text")))
|
||||
else:
|
||||
# No word count, so insert at end
|
||||
self.template.append((10, self.tr("Something")))
|
||||
self.template[1].append((10, self.tr("Something")))
|
||||
self.updateTemplate()
|
||||
|
||||
def templateAddWordCount(self):
|
||||
self.template.append((500, None))
|
||||
self.template[1].append((500, None))
|
||||
self.updateTemplate()
|
||||
|
||||
def deleteTemplateRow(self):
|
||||
btn = self.sender()
|
||||
row = btn.property("deleteRow")
|
||||
self.template.pop(row)
|
||||
self.template[1].pop(row)
|
||||
self.updateTemplate()
|
||||
|
||||
def updateWordCount(self):
|
||||
|
@ -316,11 +316,18 @@ class welcome(QWidget, Ui_welcome):
|
|||
self.tree.setIndentation(0)
|
||||
|
||||
# Add templates
|
||||
item = self.addTopLevelItem(self.tr("Templates"))
|
||||
templates = self.templates()
|
||||
item = self.addTopLevelItem(self.tr("Fiction"))
|
||||
templates = [i for i in self.templates() if i[2] == "Fiction"]
|
||||
for t in templates:
|
||||
sub = QTreeWidgetItem(item, [t[0]])
|
||||
|
||||
# Add templates: non-fiction
|
||||
item = self.addTopLevelItem(self.tr("Non-fiction"))
|
||||
templates = [i for i in self.templates() if i[2] == "Non-fiction"]
|
||||
for t in templates:
|
||||
sub = QTreeWidgetItem(item, [t[0]])
|
||||
|
||||
|
||||
# Add Demo project
|
||||
item = self.addTopLevelItem(self.tr("Demo projects"))
|
||||
dir = QDir(appPath("sample-projects"))
|
||||
|
@ -328,24 +335,21 @@ class welcome(QWidget, Ui_welcome):
|
|||
sub = QTreeWidgetItem(item, [f[:-4]])
|
||||
sub.setData(0, Qt.UserRole, f)
|
||||
|
||||
# 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)
|
||||
t = [i for i in self.templates() if i[0] == self.template[0]]
|
||||
if t and t[0][2] == "Non-fiction": settings.viewMode = "simple"
|
||||
|
||||
# Données
|
||||
self.mw.mdlFlatData = QStandardItemModel(2, 8, self.mw)
|
||||
|
||||
# Persos
|
||||
# self.mw.mdlPersos = QStandardItemModel(0, 0, self.mw)
|
||||
self.mw.mdlPersos = persosModel(self.mw)
|
||||
self.mw.mdlCharacter = characterModel(self.mw)
|
||||
# self.mdlPersosProxy = None # persosProxyModel() # None
|
||||
# self.mw.mdlPersosProxy = persosProxyModel(self.mw)
|
||||
|
||||
|
@ -386,8 +390,7 @@ class welcome(QWidget, Ui_welcome):
|
|||
self.mw.mdlWorld = worldModel(self.mw)
|
||||
|
||||
root = self.mw.mdlOutline.rootItem
|
||||
_type = self.cmbDefaultType.currentData()
|
||||
settings.defaultTextType = _type
|
||||
_type = "md"
|
||||
|
||||
def addElement(parent, datas):
|
||||
if len(datas) == 2 and datas[1][1] == None or \
|
||||
|
@ -416,5 +419,5 @@ class welcome(QWidget, Ui_welcome):
|
|||
# parent.appendChild(item)
|
||||
addElement(item, datas[1:])
|
||||
|
||||
if self.template:
|
||||
addElement(root, self.template)
|
||||
if self.template[1]:
|
||||
addElement(root, self.template[1])
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/welcome_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!
|
||||
|
||||
|
@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_welcome(object):
|
||||
def setupUi(self, welcome):
|
||||
welcome.setObjectName("welcome")
|
||||
welcome.resize(705, 422)
|
||||
welcome.resize(728, 459)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(welcome)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.frame_2 = QtWidgets.QFrame(welcome)
|
||||
|
@ -78,15 +78,6 @@ class Ui_welcome(object):
|
|||
self.btnAddWC.setObjectName("btnAddWC")
|
||||
self.horizontalLayout_2.addWidget(self.btnAddWC)
|
||||
self.templateLayout.addLayout(self.horizontalLayout_2)
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.lblTotal_2 = QtWidgets.QLabel(self.frame_2)
|
||||
self.lblTotal_2.setObjectName("lblTotal_2")
|
||||
self.horizontalLayout_3.addWidget(self.lblTotal_2)
|
||||
self.cmbDefaultType = QtWidgets.QComboBox(self.frame_2)
|
||||
self.cmbDefaultType.setObjectName("cmbDefaultType")
|
||||
self.horizontalLayout_3.addWidget(self.cmbDefaultType)
|
||||
self.templateLayout.addLayout(self.horizontalLayout_3)
|
||||
self.horizontalLayout_23.addLayout(self.templateLayout)
|
||||
self.verticalLayout_32.addLayout(self.horizontalLayout_23)
|
||||
self.line_4 = QtWidgets.QFrame(self.frame_2)
|
||||
|
@ -133,7 +124,6 @@ class Ui_welcome(object):
|
|||
self.tree.setSortingEnabled(__sortingEnabled)
|
||||
self.btnAddLevel.setText(_translate("welcome", "Add level"))
|
||||
self.btnAddWC.setText(_translate("welcome", "Add wordcount"))
|
||||
self.lblTotal_2.setText(_translate("welcome", "Default text type:"))
|
||||
self.chkLoadLastProject.setText(_translate("welcome", "Next time, automatically open last project"))
|
||||
self.btnOpen.setText(_translate("welcome", "Open..."))
|
||||
self.btnRecent.setText(_translate("welcome", "Recent"))
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>705</width>
|
||||
<height>422</height>
|
||||
<width>728</width>
|
||||
<height>459</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -190,20 +190,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTotal_2">
|
||||
<property name="text">
|
||||
<string>Default text type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbDefaultType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
Binary file not shown.
1
sample-projects/book-of-acts/MANUSKRIPT
Normal file
1
sample-projects/book-of-acts/MANUSKRIPT
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
4
sample-projects/book-of-acts/characters/0-Peter.txt
Normal file
4
sample-projects/book-of-acts/characters/0-Peter.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Peter
|
||||
ID: 0
|
||||
Importance: 2
|
||||
Color: #ff0000
|
4
sample-projects/book-of-acts/characters/1-Paul.txt
Normal file
4
sample-projects/book-of-acts/characters/1-Paul.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Paul
|
||||
ID: 1
|
||||
Importance: 2
|
||||
Color: #005500
|
4
sample-projects/book-of-acts/characters/2-Philip.txt
Normal file
4
sample-projects/book-of-acts/characters/2-Philip.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Philip
|
||||
ID: 2
|
||||
Importance: 1
|
||||
Color: #ffff00
|
4
sample-projects/book-of-acts/characters/3-Stephen.txt
Normal file
4
sample-projects/book-of-acts/characters/3-Stephen.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Stephen
|
||||
ID: 3
|
||||
Importance: 1
|
||||
Color: #ff5500
|
4
sample-projects/book-of-acts/characters/4-Herod.txt
Normal file
4
sample-projects/book-of-acts/characters/4-Herod.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Herod
|
||||
ID: 4
|
||||
Importance: 0
|
||||
Color: #000000
|
4
sample-projects/book-of-acts/characters/5-Barnabas.txt
Normal file
4
sample-projects/book-of-acts/characters/5-Barnabas.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
Name: Barnabas
|
||||
ID: 5
|
||||
Importance: 1
|
||||
Color: #a9b0b6
|
3
sample-projects/book-of-acts/infos.txt
Normal file
3
sample-projects/book-of-acts/infos.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
Title: The Acts of the Apostles
|
||||
License: Public Domain (World English Bible)
|
||||
Author: Luke
|
5
sample-projects/book-of-acts/labels.txt
Normal file
5
sample-projects/book-of-acts/labels.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
Idea: #ffff00
|
||||
Note: #00ff00
|
||||
Chapter: #0000ff
|
||||
Scene: #ff0000
|
||||
Research: #00ffff
|
|
@ -0,0 +1,7 @@
|
|||
title: Introduction
|
||||
ID: 1
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
1 The first book I wrote, Theophilus, concerned all that Jesus began both to do and to teach, 2 until the day in which he was received up, after he had given commandment through the Holy Spirit to the apostles whom he had chosen. 3 To these he also showed himself alive after he suffered, by many proofs, appearing to them over a period of forty days, and speaking about God’s Kingdom.
|
|
@ -0,0 +1,11 @@
|
|||
title: Jesus taken up into heaven
|
||||
ID: 2
|
||||
type: md
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
||||
|
||||
4 Being assembled together with them, he commanded them, “Don’t depart from Jerusalem, but wait for the promise of the Father, which you heard from me. 5 For John indeed baptized in water, but you will be baptized in the Holy Spirit not many days from now.”
|
||||
6 Therefore when they had come together, they asked him, “Lord, are you now restoring the kingdom to Israel?”
|
||||
7 He said to them, “It isn’t for you to know times or seasons which the Father has set within his own authority. 8 But you will receive power when the Holy Spirit has come upon you. You will be witnesses to me in Jerusalem, in all Judea and Samaria, and to the uttermost parts of the earth.”
|
||||
9 When he had said these things, as they were looking, he was taken up, and a cloud received him out of their sight. 10 While they were looking steadfastly into the sky as he went, behold,* two men stood by them in white clothing, 11 who also said, “You men of Galilee, why do you stand looking into the sky? This Jesus, who was received up from you into the sky, will come back in the same way as you saw him going into the sky.”
|
|
@ -0,0 +1,15 @@
|
|||
title: Matthias chosen to replace Judas
|
||||
ID: 3
|
||||
type: md
|
||||
notes: {C:2:Philip}
|
||||
compile: 2
|
||||
|
||||
|
||||
12 Then they returned to Jerusalem from the mountain called Olivet, which is near Jerusalem, a Sabbath day’s journey away. 13 When they had come in, they went up into the upper room where they were staying; that is Peter, John, James, Andrew, Philip, Thomas, Bartholomew, Matthew, James the son of Alphaeus, Simon the Zealot, and Judas the son of James. 14 All these with one accord continued steadfastly in prayer and supplication, along with the women, and Mary the mother of Jesus, and with his brothers.
|
||||
15 In these days, Peter stood up in the middle of the disciples (and the number of names was about one hundred twenty), and said, 16 “Brothers, it was necessary that this Scripture should be fulfilled, which the Holy Spirit spoke before by the mouth of David concerning Judas, who was guide to those who took Jesus. 17 For he was counted with us, and received his portion in this ministry. 18 Now this man obtained a field with the reward for his wickedness, and falling headlong, his body burst open, and all his intestines gushed out. 19 It became known to everyone who lived in Jerusalem that in their language that field was called ‘Akeldama,’ that is, ‘The field of blood.’ 20 For it is written in the book of Psalms,
|
||||
‘Let his habitation be made desolate.
|
||||
Let no one dwell in it;’
|
||||
and,
|
||||
‘Let another take his office.’
|
||||
21 “Of the men therefore who have accompanied us all the time that the Lord Jesus went in and out among us, 22 beginning from the baptism of John, to the day that he was received up from us, of these one must become a witness with us of his resurrection.”
|
||||
23 They put forward two, Joseph called Barsabbas, who was also called Justus, and Matthias. 24 They prayed and said, “You, Lord, who know the hearts of all men, show which one of these two you have chosen 25 to take part in this ministry and apostleship from which Judas fell away, that he might go to his own place.” 26 They drew lots for them, and the lot fell on Matthias, and he was counted with the eleven apostles.
|
|
@ -0,0 +1,7 @@
|
|||
title: Chapter 1
|
||||
ID: 5
|
||||
type: folder
|
||||
compile: 2
|
||||
setGoal: 1000
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
title: The promised Spirit
|
||||
ID: 4
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
1 Now when the day of Pentecost had come, they were all with one accord in one place. 2 Suddenly there came from the sky a sound like the rushing of a mighty wind, and it filled all the house where they were sitting. 3 Tongues like fire appeared and were distributed to them, and one sat on each of them. 4 They were all filled with the Holy Spirit, and began to speak with other languages, as the Spirit gave them the ability to speak. 5 Now there were dwelling in Jerusalem Jews, devout men, from every nation under the sky. 6 When this sound was heard, the multitude came together and were bewildered, because everyone heard them speaking in his own language. 7 They were all amazed and marveled, saying to one another, “Behold, aren’t all these who speak Galileans? 8 How do we hear, everyone in our own native language? 9 Parthians, Medes, Elamites, and people from Mesopotamia, Judea, Cappadocia, Pontus, Asia, 10 Phrygia, Pamphylia, Egypt, the parts of Libya around Cyrene, visitors from Rome, both Jews and proselytes, 11 Cretans and Arabians: we hear them speaking in our languages the mighty works of God!” 12 They were all amazed, and were perplexed, saying to one another, “What does this mean?” 13 Others, mocking, said, “They are filled with new wine.”
|
|
@ -0,0 +1,39 @@
|
|||
title: Peter adresses the crowd
|
||||
ID: 15
|
||||
type: md
|
||||
POV: 0
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
||||
|
||||
14 But Peter, standing up with the eleven, lifted up his voice, and spoke out to them, “You men of Judea, and all you who dwell at Jerusalem, let this be known to you, and listen to my words. 15 For these aren’t drunken, as you suppose, seeing it is only the third hour of the day. 16 But this is what has been spoken through the prophet Joel:
|
||||
17 ‘It will be in the last days, says God,
|
||||
that I will pour out my Spirit on all flesh.
|
||||
Your sons and your daughters will prophesy.
|
||||
Your young men will see visions.
|
||||
Your old men will dream dreams.
|
||||
18 Yes, and on my servants and on my handmaidens in those days,
|
||||
I will pour out my Spirit, and they will prophesy.
|
||||
19 I will show wonders in the sky above,
|
||||
and signs on the earth beneath;
|
||||
blood, and fire, and billows of smoke.
|
||||
20 The sun will be turned into darkness,
|
||||
and the moon into blood,
|
||||
before the great and glorious day of the Lord comes.
|
||||
21 It will be that whoever will call on the name of the Lord will be saved.’
|
||||
22 “Men of Israel, hear these words! Jesus of Nazareth, a man approved by God to you by mighty works and wonders and signs which God did by him among you, even as you yourselves know, 23 him, being delivered up by the determined counsel and foreknowledge of God, you have taken by the hand of lawless men, crucified and killed; 24 whom God raised up, having freed him from the agony of death, because it was not possible that he should be held by it. 25 For David says concerning him,
|
||||
‘I saw the Lord always before my face,
|
||||
for he is on my right hand, that I should not be moved.
|
||||
26 Therefore my heart was glad, and my tongue rejoiced.
|
||||
Moreover my flesh also will dwell in hope;
|
||||
27 because you will not leave my soul in Hades,†
|
||||
neither will you allow your Holy One to see decay.
|
||||
28 You made known to me the ways of life.
|
||||
You will make me full of gladness with your presence.’
|
||||
29 “Brothers, I may tell you freely of the patriarch David, that he both died and was buried, and his tomb is with us to this day. 30 Therefore, being a prophet, and knowing that God had sworn with an oath to him that of the fruit of his body, according to the flesh, he would raise up the Christ to sit on his throne, 31 he foreseeing this spoke about the resurrection of the Christ, that his soul wasn’t left in Hades,‡ and his flesh didn’t see decay. 32 This Jesus God raised up, to which we all are witnesses. 33 Being therefore exalted by the right hand of God, and having received from the Father the promise of the Holy Spirit, he has poured out this, which you now see and hear. 34 For David didn’t ascend into the heavens, but he says himself,
|
||||
‘The Lord said to my Lord, “Sit by my right hand
|
||||
35 until I make your enemies a footstool for your feet.” ’
|
||||
36 “Let all the house of Israel therefore know certainly that God has made him both Lord and Christ, this Jesus whom you crucified.”
|
||||
37 Now when they heard this, they were cut to the heart, and said to Peter and the rest of the apostles, “Brothers, what shall we do?”
|
||||
38 Peter said to them, “Repent, and be baptized, every one of you, in the name of Jesus Christ for the forgiveness of sins, and you will receive the gift of the Holy Spirit. 39 For the promise is to you, and to your children, and to all who are far off, even as many as the Lord our God will call to himself.” 40 With many other words he testified, and exhorted them, saying, “Save yourselves from this crooked generation!”
|
||||
41 Then those who gladly received his word were baptized. There were added that day about three thousand souls.
|
|
@ -0,0 +1,7 @@
|
|||
title: The life of the first believers
|
||||
ID: 14
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
42 They continued steadfastly in the apostles’ teaching and fellowship, in the breaking of bread, and prayer. 43 Fear came on every soul, and many wonders and signs were done through the apostles. 44 All who believed were together, and had all things in common. 45 They sold their possessions and goods, and distributed them to all, according as anyone had need. 46 Day by day, continuing steadfastly with one accord in the temple, and breaking bread at home, they took their food with gladness and singleness of heart, 47 praising God, and having favor with all the people. The Lord added to the assembly day by day those who were being saved.
|
|
@ -0,0 +1,7 @@
|
|||
title: Chapter 2
|
||||
ID: 6
|
||||
type: folder
|
||||
compile: 2
|
||||
setGoal: 1000
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
title: Peter heals a beggar
|
||||
ID: 13
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
||||
1 Peter and John were going up into the temple at the hour of prayer, the ninth hour.* 2 A certain man who was lame from his mother’s womb was being carried, whom they laid daily at the door of the temple which is called Beautiful, to ask gifts for the needy of those who entered into the temple. 3 Seeing Peter and John about to go into the temple, he asked to receive gifts for the needy. 4 Peter, fastening his eyes on him, with John, said, “Look at us.” 5 He listened to them, expecting to receive something from them. 6 But Peter said, “I have no silver or gold, but what I have, that I give you. In the name of Jesus Christ of Nazareth, get up and walk!” 7 He took him by the right hand and raised him up. Immediately his feet and his ankle bones received strength. 8 Leaping up, he stood and began to walk. He entered with them into the temple, walking, leaping, and praising God. 9 All the people saw him walking and praising God. 10 They recognized him, that it was he who used to sit begging for gifts for the needy at the Beautiful Gate of the temple. They were filled with wonder and amazement at what had happened to him.
|
|
@ -0,0 +1,11 @@
|
|||
title: Peter preaches
|
||||
ID: 12
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
||||
11 As the lame man who was healed held on to Peter and John, all the people ran together to them in the porch that is called Solomon’s, greatly wondering.
|
||||
12 When Peter saw it, he responded to the people, “You men of Israel, why do you marvel at this man? Why do you fasten your eyes on us, as though by our own power or godliness we had made him walk? 13 The God of Abraham, Isaac, and Jacob, the God of our fathers, has glorified his Servant Jesus, whom you delivered up, and denied in the presence of Pilate, when he had determined to release him. 14 But you denied the Holy and Righteous One and asked for a murderer to be granted to you, 15 and killed the Prince of life, whom God raised from the dead, to which we are witnesses. 16 By faith in his name, his name has made this man strong, whom you see and know. Yes, the faith which is through him has given him this perfect soundness in the presence of you all.
|
||||
17 “Now, brothers,† I know that you did this in ignorance, as did also your rulers. 18 But the things which God announced by the mouth of all his prophets, that Christ should suffer, he thus fulfilled.
|
||||
19 “Repent therefore, and turn again, that your sins may be blotted out, so that there may come times of refreshing from the presence of the Lord, 20 and that he may send Christ Jesus, who was ordained for you before, 21 whom heaven must receive until the times of restoration of all things, which God spoke long ago by the mouth of his holy prophets. 22 For Moses indeed said to the fathers, ‘The Lord God will raise up a prophet for you from among your brothers, like me. You shall listen to him in all things whatever he says to you. 23 It will be that every soul that will not listen to that prophet will be utterly destroyed from among the people.’✡ 24 Yes, and all the prophets from Samuel and those who followed after, as many as have spoken, they also told of these days. 25 You are the children of the prophets, and of the covenant which God made with our fathers, saying to Abraham, ‘All the families of the earth will be blessed through your offspring.‡ .’✡ 26 God, having raised up his servant Jesus, sent him to you first to bless you, in turning away every one of you from your wickedness.”
|
|
@ -0,0 +1,7 @@
|
|||
title: Chapter 3
|
||||
ID: 7
|
||||
type: folder
|
||||
compile: 2
|
||||
setGoal: 1000
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
title: Peter and John in front of the Sanhedrin
|
||||
ID: 16
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
||||
1 As they spoke to the people, the priests and the captain of the temple and the Sadducees came to them, 2 being upset because they taught the people and proclaimed in Jesus the resurrection from the dead. 3 They laid hands on them, and put them in custody until the next day, for it was now evening. 4 But many of those who heard the word believed, and the number of the men came to be about five thousand.
|
||||
5 In the morning, their rulers, elders, and scribes were gathered together in Jerusalem. 6 Annas the high priest was there, with Caiaphas, John, Alexander, and as many as were relatives of the high priest. 7 When they had stood Peter and John in the middle of them, they inquired, “By what power, or in what name, have you done this?”
|
||||
8 Then Peter, filled with the Holy Spirit, said to them, “You rulers of the people, and elders of Israel, 9 if we are examined today concerning a good deed done to a crippled man, by what means this man has been healed, 10 may it be known to you all, and to all the people of Israel, that in the name of Jesus Christ of Nazareth, whom you crucified, whom God raised from the dead, in him does this man stand here before you whole. 11 He is ‘the stone which was regarded as worthless by you, the builders, which has become the head of the corner.’✡ 12 There is salvation in no one else, for there is no other name under heaven that is given among men, by which we must be saved!”
|
||||
13 Now when they saw the boldness of Peter and John, and had perceived that they were unlearned and ignorant men, they marveled. They recognized that they had been with Jesus. 14 Seeing the man who was healed standing with them, they could say nothing against it. 15 But when they had commanded them to go aside out of the council, they conferred among themselves, 16 saying, “What shall we do to these men? Because indeed a notable miracle has been done through them, as can be plainly seen by all who dwell in Jerusalem, and we can’t deny it. 17 But so that this spreads no further among the people, let’s threaten them, that from now on they don’t speak to anyone in this name.” 18 They called them, and commanded them not to speak at all nor teach in the name of Jesus.
|
||||
19 But Peter and John answered them, “Whether it is right in the sight of God to listen to you rather than to God, judge for yourselves, 20 for we can’t help telling the things which we saw and heard.”
|
||||
21 When they had further threatened them, they let them go, finding no way to punish them, because of the people; for everyone glorified God for that which was done. 22 For the man on whom this miracle of healing was performed was more than forty years old.
|
|
@ -0,0 +1,15 @@
|
|||
title: The believers pray
|
||||
ID: 17
|
||||
type: md
|
||||
notes: Mention: {C:4:Herod}
|
||||
compile: 2
|
||||
|
||||
|
||||
23 Being let go, they came to their own company and reported all that the chief priests and the elders had said to them. 24 When they heard it, they lifted up their voice to God with one accord, and said, “O Lord, you are God, who made the heaven, the earth, the sea, and all that is in them; 25 who by the mouth of your servant, David, said,
|
||||
‘Why do the nations rage,
|
||||
and the peoples plot a vain thing?
|
||||
26 The kings of the earth take a stand,
|
||||
and the rulers take council together,
|
||||
against the Lord, and against his Christ.’*✡
|
||||
27 “For truly, in this city against your holy servant, Jesus, whom you anointed, both Herod and Pontius Pilate, with the Gentiles and the people of Israel, were gathered together 28 to do whatever your hand and your council foreordained to happen. 29 Now, Lord, look at their threats, and grant to your servants to speak your word with all boldness, 30 while you stretch out your hand to heal; and that signs and wonders may be done through the name of your holy Servant Jesus.”
|
||||
31 When they had prayed, the place was shaken where they were gathered together. They were all filled with the Holy Spirit, and they spoke the word of God with boldness.
|
|
@ -0,0 +1,8 @@
|
|||
title: The believers share
|
||||
ID: 18
|
||||
type: md
|
||||
notes: {C:5:Barnabas}
|
||||
compile: 2
|
||||
|
||||
|
||||
32 The multitude of those who believed were of one heart and soul. Not one of them claimed that anything of the things which he possessed was his own, but they had all things in common. 33 With great power, the apostles gave their testimony of the resurrection of the Lord Jesus. Great grace was on them all. 34 For neither was there among them any who lacked, for as many as were owners of lands or houses sold them, and brought the proceeds of the things that were sold, 35 and laid them at the apostles’ feet, and distribution was made to each, according as anyone had need. 36 Joses, who by the apostles was also called Barnabas (which is, being interpreted, Son of Encouragement), a Levite, a man of Cyprus by race, 37 having a field, sold it and brought the money and laid it at the apostles’ feet.
|
|
@ -0,0 +1,7 @@
|
|||
title: Chapter 4
|
||||
ID: 8
|
||||
type: folder
|
||||
compile: 2
|
||||
setGoal: 1000
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue