mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-06-11 15:34:33 +12:00
Simplification: removes multiple file formats (txt2tags, rich text / html) and keep only markdown. There.
This commit is contained in:
commit
38aa0a66e0
|
@ -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())
|
||||
|
|
|
@ -18,7 +18,7 @@ from PyQt5.QtGui import QColor, QStandardItem
|
|||
|
||||
from manuskript import settings
|
||||
from manuskript.enums import Character, World, Plot, PlotStep, Outline
|
||||
from manuskript.functions import mainWindow, iconColor, iconFromColorString
|
||||
from manuskript.functions import mainWindow, iconColor, iconFromColorString, HTML2PlainText
|
||||
from lxml import etree as ET
|
||||
|
||||
from manuskript.load_save.version_0 import loadFilesFromZip
|
||||
|
@ -529,12 +529,7 @@ def exportOutlineItem(root):
|
|||
content = outlineToMMD(child)
|
||||
files.append((fpath, content))
|
||||
|
||||
elif child.type() in ["txt", "t2t", "md"]:
|
||||
content = outlineToMMD(child)
|
||||
files.append((spath, content))
|
||||
|
||||
elif child.type() in ["html"]:
|
||||
# Save as html. Not the most beautiful, but hey.
|
||||
elif child.type() == "md":
|
||||
content = outlineToMMD(child)
|
||||
files.append((spath, content))
|
||||
|
||||
|
@ -565,7 +560,7 @@ def outlineItemPath(item):
|
|||
name = "{ID}-{name}{ext}".format(
|
||||
ID=str(item.row()).zfill(len(str(siblings))),
|
||||
name=slugify(item.title()),
|
||||
ext="" if item.type() == "folder" else ".md" # ".{}".format(item.type()) # To have .txt, .t2t, .html, ...
|
||||
ext="" if item.type() == "folder" else ".md"
|
||||
)
|
||||
return outlineItemPath(item.parent()) + [name]
|
||||
|
||||
|
@ -912,6 +907,14 @@ def outlineFromMMD(text, parent):
|
|||
# Store body
|
||||
item.setData(Outline.text.value, str(body))
|
||||
|
||||
# Set file format to "md"
|
||||
# (Old version of manuskript had different file formats: text, t2t, html and md)
|
||||
# If file format is html, convert to plain text:
|
||||
if item.type() == "html":
|
||||
item.setData(Outline.text.value, HTML2PlainText(body))
|
||||
if item.type() in ["txt", "t2t", "html"]:
|
||||
item.setData(Outline.type.value, "md")
|
||||
|
||||
return item
|
||||
|
||||
|
||||
|
|
|
@ -481,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() or self.isMD():
|
||||
return QIcon.fromTheme("text-x-script")
|
||||
elif self.isHTML():
|
||||
return QIcon.fromTheme("text-html")
|
||||
|
||||
# elif role == Qt.ForegroundRole:
|
||||
# if self.isCompile() in [0, "0"]:
|
||||
|
@ -527,15 +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", "md"]:
|
||||
# Resource inneficient way to convert HTML to plain text
|
||||
self._data[Outline.text] = HTML2PlainText(self._data[Outline.text])
|
||||
elif oldType in ["txt", "t2t", "md"] 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
|
||||
|
@ -658,8 +646,8 @@ class outlineItem():
|
|||
def isFolder(self):
|
||||
return self._data[Outline.type] == "folder"
|
||||
|
||||
def isT2T(self):
|
||||
return self._data[Outline.type] == "t2t"
|
||||
def isText(self):
|
||||
return self._data[Outline.type] == "md"
|
||||
|
||||
def isMD(self):
|
||||
return self._data[Outline.type] == "md"
|
||||
|
@ -667,12 +655,6 @@ class outlineItem():
|
|||
def isMMD(self):
|
||||
return self._data[Outline.type] == "md"
|
||||
|
||||
def isHTML(self):
|
||||
return self._data[Outline.type] == "html"
|
||||
|
||||
def isText(self):
|
||||
return self._data[Outline.type] == "txt"
|
||||
|
||||
def text(self):
|
||||
return self.data(Outline.text.value)
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ 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)
|
||||
)
|
||||
|
||||
|
@ -582,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 ""
|
||||
|
|
|
@ -79,15 +79,6 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
self.chkAutoLoad.setChecked(autoLoad)
|
||||
self.chkAutoLoad.stateChanged.connect(self.saveSettingsChanged)
|
||||
|
||||
dtt = welcome.defaultTextType()
|
||||
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"])
|
||||
|
@ -253,7 +244,6 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
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 #
|
||||
|
|
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
|
|
@ -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)
|
||||
|
|
|
@ -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,10 +61,6 @@ class textFormat(QWidget, Ui_textFormat):
|
|||
|
||||
elif item.isText():
|
||||
self.align.setVisible(False)
|
||||
self.format.setVisible(False)
|
||||
|
||||
elif item.isT2T() or item.isMD():
|
||||
self.align.setVisible(False)
|
||||
|
||||
def setFormat(self):
|
||||
act = self.sender()
|
||||
|
|
|
@ -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 == "+ ":
|
||||
|
|
|
@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_Settings(object):
|
||||
def setupUi(self, Settings):
|
||||
Settings.setObjectName("Settings")
|
||||
Settings.resize(658, 585)
|
||||
Settings.resize(658, 507)
|
||||
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(Settings)
|
||||
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
|
||||
self.lstMenu = QtWidgets.QListWidget(Settings)
|
||||
|
@ -215,30 +215,6 @@ class Ui_Settings(object):
|
|||
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)
|
||||
|
@ -1673,8 +1649,6 @@ class Ui_Settings(object):
|
|||
self.chkSaveOnQuit.setText(_translate("Settings", "Save on quit"))
|
||||
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.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.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"))
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<height>585</height>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -424,47 +424,6 @@ text-align:center;</string>
|
|||
</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">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</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>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<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>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,143 +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
|
||||
from manuskript.ui.welcome import welcome
|
||||
|
||||
|
||||
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 = welcome.defaultTextType()
|
||||
|
||||
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", "md"])
|
||||
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", "md"]:
|
||||
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
|
|
@ -16,7 +16,6 @@ class propertiesView(QWidget, Ui_propertiesView):
|
|||
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)
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'manuskript/ui/views/propertiesView_ui.ui'
|
||||
#
|
||||
# Created: Thu Mar 3 17:26:11 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!
|
||||
|
||||
|
@ -12,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")
|
||||
|
@ -72,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)
|
||||
|
@ -90,26 +89,14 @@ 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()
|
||||
self.page_2.setObjectName("page_2")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.page_2)
|
||||
self.verticalLayout_3.setSpacing(0)
|
||||
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_3.setSpacing(0)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.formLayout_2 = QtWidgets.QFormLayout()
|
||||
self.formLayout_2.setObjectName("formLayout_2")
|
||||
|
@ -187,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,9 +181,8 @@ class Ui_propertiesView(object):
|
|||
self.label_36.setText(_translate("propertiesView", "Goal"))
|
||||
self.txtGoalMulti.setPlaceholderText(_translate("propertiesView", "Word count"))
|
||||
|
||||
from manuskript.ui.views.lineEditView import lineEditView
|
||||
from manuskript.ui.views.cmbOutlineCharacterChoser import cmbOutlineCharacterChoser
|
||||
from manuskript.ui.views.cmbOutlineTypeChoser import cmbOutlineTypeChoser
|
||||
from manuskript.ui.views.chkOutlineCompile import chkOutlineCompile
|
||||
from manuskript.ui.views.cmbOutlineStatusChoser import cmbOutlineStatusChoser
|
||||
from manuskript.ui.views.cmbOutlineCharacterChoser import cmbOutlineCharacterChoser
|
||||
from manuskript.ui.views.cmbOutlineLabelChoser import cmbOutlineLabelChoser
|
||||
from manuskript.ui.views.cmbOutlineStatusChoser import cmbOutlineStatusChoser
|
||||
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>
|
||||
|
@ -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>
|
||||
|
@ -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/>
|
||||
|
|
|
@ -11,11 +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:
|
||||
|
@ -151,40 +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"
|
||||
elif item.isMD():
|
||||
self._textFormat = "md"
|
||||
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() or item.isMD()):
|
||||
self.highlighter = basicHighlighter(self)
|
||||
elif item.isT2T():
|
||||
self.highlighter = t2tHighlighter(self)
|
||||
elif item.isMD():
|
||||
if self._column in [Outline.text.value, Outline.notes.value]:
|
||||
self.highlighter = MMDHighlighter(self)
|
||||
else:
|
||||
self.highlighter = basicHighlighter(self)
|
||||
|
||||
self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat)
|
||||
|
||||
|
@ -244,15 +227,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:
|
||||
|
@ -288,15 +263,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:
|
||||
|
@ -313,7 +282,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("")
|
||||
|
@ -332,26 +300,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
|
||||
|
@ -503,70 +456,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)
|
||||
|
||||
elif self._textFormat == "md":
|
||||
# FIXME
|
||||
print("Not implemented yet.")
|
||||
MDFormatSelection(self)
|
||||
|
|
|
@ -89,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)
|
||||
|
@ -193,15 +193,6 @@ class welcome(QWidget, Ui_welcome):
|
|||
], "Non-fiction")
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def defaultTextType(cls):
|
||||
return [
|
||||
("t2t", qApp.translate("Welcome", "Txt2Tags"), "text-x-generic"),
|
||||
("html", qApp.translate("Welcome", "Rich Text (html)"), "text-html"),
|
||||
("txt", qApp.translate("Welcome", "Plain Text"), "text-x-generic"),
|
||||
("md", qApp.translate("Welcome", "Multi-Markdown"), "text-x-generic"),
|
||||
]
|
||||
|
||||
def changeTemplate(self, item, column):
|
||||
template = [i for i in self.templates() if i[0] == item.text(0)]
|
||||
self.btnCreate.setText(self.btnCreateText)
|
||||
|
@ -343,11 +334,6 @@ 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):
|
||||
|
@ -403,8 +389,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 \
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Introduction
|
||||
ID: 1
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Jesus taken up into heaven
|
||||
ID: 2
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Matthias chosen to replace Judas
|
||||
ID: 3
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:2:Philip}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The promised Spirit
|
||||
ID: 4
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter adresses the crowd
|
||||
ID: 15
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The life of the first believers
|
||||
ID: 14
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter heals a beggar
|
||||
ID: 13
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter preaches
|
||||
ID: 12
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter and John in front of the Sanhedrin
|
||||
ID: 16
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The believers pray
|
||||
ID: 17
|
||||
type: txt
|
||||
type: md
|
||||
notes: Mention: {C:4:Herod}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The believers share
|
||||
ID: 18
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:5:Barnabas}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Ananias and Sapphira
|
||||
ID: 19
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Many healings done by the aposles
|
||||
ID: 20
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The persecutions
|
||||
ID: 21
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The choosing of seven
|
||||
ID: 22
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:2:Philip}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Stephen is taken
|
||||
ID: 23
|
||||
type: txt
|
||||
type: md
|
||||
POV: 3
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Stephen preaches
|
||||
ID: 24
|
||||
type: txt
|
||||
type: md
|
||||
POV: 3
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Stephen is killed
|
||||
ID: 25
|
||||
type: txt
|
||||
type: md
|
||||
POV: 3
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The church scattered
|
||||
ID: 26
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Philip in Samaria
|
||||
ID: 32
|
||||
type: txt
|
||||
type: md
|
||||
POV: 2
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Simon the Sorcerer
|
||||
ID: 33
|
||||
type: txt
|
||||
type: md
|
||||
POV: 2
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Philip and the Ethiopian
|
||||
ID: 36
|
||||
type: txt
|
||||
type: md
|
||||
POV: 2
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Saul's conversion
|
||||
ID: 37
|
||||
type: txt
|
||||
type: md
|
||||
POV: 1
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Saul in Damascus and Jerusalem
|
||||
ID: 38
|
||||
type: txt
|
||||
type: md
|
||||
POV: 1
|
||||
notes: {P:2:Paul and Barnabas fight}
|
||||
{C:5:Barnabas}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter visits the church in Judea
|
||||
ID: 39
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Cornelius calls for Peter
|
||||
ID: 40
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
notes: {P:1}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter's vision
|
||||
ID: 41
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The conversion of Peter
|
||||
ID: 42
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter explains his actions
|
||||
ID: 43
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
notes: {P:1:Peter needs to broaden his understanding of the Gospel}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The Church in Antioch
|
||||
ID: 44
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:2:Paul and Barnabas fight}
|
||||
{C:5:Barnabas}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Peter escapes from prison
|
||||
ID: 45
|
||||
type: txt
|
||||
type: md
|
||||
POV: 0
|
||||
notes: Mention: {C:4:Herod}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Herod dies
|
||||
ID: 46
|
||||
type: txt
|
||||
type: md
|
||||
POV: 4
|
||||
notes: Present:
|
||||
- {C:1:Paul}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Saul and Barnabas are sent
|
||||
ID: 51
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:2:Paul and Barnabas fight}
|
||||
{C:5:Barnabas}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Cyprus
|
||||
ID: 52
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:0:The good news spreads from Jerusalem to Rome}
|
||||
{C:5:Barnabas}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Psidian Antioch
|
||||
ID: 53
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:5:Barnabas}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Iconium
|
||||
ID: 54
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Lystra and Derbe
|
||||
ID: 55
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:5:Barnabas}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Back to Antioch
|
||||
ID: 56
|
||||
type: txt
|
||||
type: md
|
||||
compile: 2
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The Council at Jerusalem
|
||||
ID: 57
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:1:Peter needs to broaden his understanding of the Gospel}
|
||||
{C:5:Barnabas}
|
||||
compile: 2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: The Council writes to gentile believers
|
||||
ID: 58
|
||||
type: txt
|
||||
type: md
|
||||
notes: {C:5:Barnabas}
|
||||
compile: 2
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
title: Paul and Barnabas fight and split
|
||||
ID: 59
|
||||
type: txt
|
||||
type: md
|
||||
notes: {P:2:Paul and Barnabas fight}
|
||||
{C:5:Barnabas}
|
||||
compile: 2
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -24,7 +24,6 @@
|
|||
],
|
||||
"outlineViewColumns": [
|
||||
0,
|
||||
5,
|
||||
8,
|
||||
9,
|
||||
11,
|
||||
|
@ -44,6 +43,7 @@
|
|||
"smartremove": true
|
||||
},
|
||||
"saveOnQuit": true,
|
||||
"saveToZip": false,
|
||||
"spellcheck": false,
|
||||
"textEditor": {
|
||||
"background": "#fff",
|
||||
|
@ -56,6 +56,7 @@
|
|||
"spacingBelow": 5,
|
||||
"tabWidth": 20
|
||||
},
|
||||
"viewMode": "fiction",
|
||||
"viewSettings": {
|
||||
"Cork": {
|
||||
"Background": "Nothing",
|
||||
|
|
Loading…
Reference in a new issue