manuskript/manuskript/ui/exporters/manuskript/plainTextSettings.py
TheJackiMonster 41e59d71c1
Fix newline changes to read universally
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
2023-12-12 16:18:43 +01:00

422 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# --!-- coding: utf8 --!--
import json
import os
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon, QFontMetrics, QFont
from PyQt5.QtWidgets import QWidget, QTableWidgetItem, QListWidgetItem, QTreeView
from manuskript.functions import mainWindow, writablePath
from manuskript.ui.exporters.manuskript.plainTextSettings_ui import Ui_exporterSettings
from manuskript.ui import style as S
class exporterSettings(QWidget, Ui_exporterSettings):
def __init__(self, _format, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.toolBox.setStyleSheet(S.toolBoxSS())
self.mw = mainWindow()
self._format = _format
self.settings = {}
#################################################################
# Content
self.grpContentFilters.button.setChecked(False)
h = self.tblContent.horizontalHeader()
h.setSectionResizeMode(h.ResizeToContents)
h.setSectionResizeMode(0, h.Stretch)
self.contentUpdateTable()
self.chkContentMore.toggled.connect(self.contentTableToggle)
self.contentTableToggle(False)
# Labels
self.lstContentLabels.clear()
h = QFontMetrics(self.font()).height()
for i in range(0, self.mw.mdlLabels.rowCount()):
item = self.mw.mdlLabels.item(i, 0)
if item:
item = QListWidgetItem(item.icon(), item.text())
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
item.setCheckState(Qt.Checked)
item.setSizeHint(QSize(100, h))
self.lstContentLabels.addItem(item)
self.chkContentLabels.toggled.connect(self.lstContentLabels.setVisible)
self.chkContentLabels.toggled.connect(lambda: self.listWidgetAdjustToContent(self.lstContentLabels))
self.lstContentLabels.setVisible(False)
# Status
self.lstContentStatus.clear()
h = QFontMetrics(self.font()).height()
for i in range(0, self.mw.mdlStatus.rowCount()):
item = self.mw.mdlStatus.item(i, 0)
if item:
item = QListWidgetItem(item.icon(), item.text())
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
item.setCheckState(Qt.Checked)
item.setSizeHint(QSize(100, h))
self.lstContentStatus.addItem(item)
self.chkContentStatus.toggled.connect(self.lstContentStatus.setVisible)
self.chkContentStatus.toggled.connect(lambda: self.listWidgetAdjustToContent(self.lstContentStatus))
self.lstContentStatus.setVisible(False)
# Root item
self.cmbContentParent.setModel(self.mw.mdlOutline)
v = QTreeView()
self.cmbContentParent.setView(v)
v.setHeaderHidden(True)
for i in range(1, self.mw.mdlOutline.columnCount()):
v.hideColumn(i)
self.chkContentParent.toggled.connect(self.cmbContentParent.setVisible)
self.cmbContentParent.hide()
#################################################################
# Separations
for cmb in [self.cmbSepFF, self.cmbSepTT, self.cmbSepFT, self.cmbSepTF]:
cmb.clear()
cmb.addItem(self.tr("Empty line"), "empty")
cmb.addItem(self.tr("Custom"), "custom")
cmb.currentIndexChanged.connect(self.sepCmbChanged)
#################################################################
# Transformations
h = self.tblReplacements.horizontalHeader()
h.setSectionResizeMode(h.ResizeToContents)
h.setSectionResizeMode(1, h.Stretch)
h.setSectionResizeMode(2, h.Stretch)
# Cf. https://en.wikipedia.org/wiki/Quotation_mark
self.cmbTransDoubleQuotes.clear()
self.cmbTransDoubleQuotes.addItems(["”___“", "“___”", "«___»"])
self.cmbTransSingleQuote.clear()
self.cmbTransSingleQuote.addItems(["___", "___"])
for cmb in [self.cmbTransDoubleQuotes, self.cmbTransSingleQuote]:
cmb.addItem(self.tr("Custom"), "custom")
cmb.currentIndexChanged.connect(self.transCmbChanged)
cmb.currentIndexChanged.emit(0)
self.btnTransAdd.clicked.connect(lambda: self.transAddTableRow(checked=True))
self.btnTransRemove.clicked.connect(self.transRemoveTableRow)
self.tableWidgetAdjustToContent(self.tblReplacements)
#################################################################
# Preview
self.cmbPreviewFont.setCurrentFont(self.font())
self.spnPreviewSize.setValue(self.font().pointSize())
#################################################################
# Final stuff
self.toolBox.setCurrentIndex(0)
###################################################################################################################
# SETTINGS
###################################################################################################################
def loadSettings(self):
filename = self.getSettingsPath()
if os.path.exists(filename):
with open(filename, 'r', encoding="utf-8") as f:
self.settings = json.load(f)
self.updateFromSettings()
# Default values
else:
self.getSettings()
def writeSettings(self):
self.getSettings()
with open(self.getSettingsPath(), 'w', encoding="utf-8", newline="\n") as f:
# json.dumps(json.loads(json.dumps(allSettings)), indent=4, sort_keys=True)
json.dump(self.settings, f, indent=4, sort_keys=True)
def getSettingsPath(self):
return os.path.join(writablePath(), "exporter.ini")
def updateFromSettings(self):
settings = self.settings
# Content
s = settings["Content"]
self.chkContentMore.setChecked(s["More"])
if not s["More"]:
self.tblContent.item(0, 1).setCheckState(Qt.Checked if s["FolderTitle"] else Qt.Unchecked)
self.tblContent.item(1, 1).setCheckState(Qt.Checked if s["TextTitle"] else Qt.Unchecked)
self.tblContent.item(1, 2).setCheckState(Qt.Checked if s["TextText"] else Qt.Unchecked)
else:
nLevel = len(s["FolderTitle"])
for i in range(nLevel):
item = self.tblContent.item(i + 2, 1)
if item:
item.setCheckState(Qt.Checked if s["FolderTitle"][i] else Qt.Unchecked)
item = self.tblContent.item(i + 2 + nLevel, 1)
if item:
item.setCheckState(Qt.Checked if s["TextTitle"][i] else Qt.Unchecked)
item = self.tblContent.item(i + 2 + nLevel, 2)
if item:
item.setCheckState(Qt.Checked if s["TextText"][i] else Qt.Unchecked)
self.chkContentIgnoreCompile.setChecked(s["IgnoreCompile"])
self.chkContentParent.setChecked(s["Parent"])
self.chkContentLabels.setChecked(s["Labels"])
self.chkContentStatus.setChecked(s["Status"])
# FIXME: parent, labels, status
# Separations
s = settings["Separator"]
for val, cmb, txt in [
("FF", self.cmbSepFF, self.txtSepFF),
("TT", self.cmbSepTT, self.txtSepTT),
("FT", self.cmbSepFT, self.txtSepFT),
("TF", self.cmbSepTF, self.txtSepTF),
]:
if s[val] == "\n":
cmb.setCurrentIndex(0)
else:
cmb.setCurrentIndex(1)
txt.setText(self._format.escapes(s[val]))
# Transformations
s = settings["Transform"]
self.chkTransEllipse.setChecked(s["Ellipse"])
self.chkTransDash.setChecked(s["Dash"])
for val, chk, cmb, txtA, txtB in [
("DoubleQuotes", self.chkTransDoubleQuotes, self.cmbTransDoubleQuotes, self.txtTransDoubleQuotesA, self.txtTransDoubleQuotesB),
("SingleQuote", self.chkTransSingleQuote, self.cmbTransSingleQuote, self.txtTransSingleQuoteA, self.txtTransSingleQuoteB),
]:
chk.setChecked(s[val] != False)
if s[val]:
if cmb.findText(s[val]) != -1:
cmb.setCurrentText(s[val])
else:
cmb.setCurrentIndex(cmb.count() - 1)
txtA.setText(s[val].split("___")[0])
txtB.setText(s[val].split("___")[1])
self.chkTransSpaces.setChecked(s["Spaces"])
for i in s["Custom"]:
self.transAddTableRow(i[0], i[1], i[2], i[3])
# Preview
s = settings["Preview"]
f = QFont()
f.fromString(s["PreviewFont"])
self.cmbPreviewFont.setCurrentFont(f)
self.spnPreviewSize.setValue(f.pointSize())
def getSettings(self):
"""Updates settings from ui, and return."""
# Content
s = self.settings.get("Content", {})
s["More"] = self.chkContentMore.isChecked()
if not s["More"]:
s["FolderTitle"] = self.tblContent.item(0, 1).checkState() == Qt.Checked
s["TextTitle"] = self.tblContent.item(1, 1).checkState() == Qt.Checked
s["TextText"] = self.tblContent.item(1, 2).checkState() == Qt.Checked
else:
s["FolderTitle"] = []
s["TextTitle"] = []
s["TextText"] = []
nLevel = int((self.tblContent.rowCount() - 2) / 2)
for row in range(nLevel):
s["FolderTitle"].append(self.tblContent.item(2 + row, 1).checkState() == Qt.Checked)
s["TextTitle"].append(self.tblContent.item(2 + row + nLevel, 1).checkState() == Qt.Checked)
s["TextText"].append(self.tblContent.item(2 + row + nLevel, 2).checkState() == Qt.Checked)
s["IgnoreCompile"] = self.chkContentIgnoreCompile.isChecked()
s["Parent"] = self.chkContentParent.isChecked()
s["Labels"] = self.chkContentLabels.isChecked()
s["Status"] = self.chkContentStatus.isChecked()
self.settings["Content"] = s
# FIXME: parent, labels, status
# Separations
s = self.settings.get("Separator", {})
for val, cmb, txt in [
("FF", self.cmbSepFF, self.txtSepFF),
("TT", self.cmbSepTT, self.txtSepTT),
("FT", self.cmbSepFT, self.txtSepFT),
("TF", self.cmbSepTF, self.txtSepTF),
]:
if cmb.currentIndex() == 0:
s[val] = "\n"
else:
s[val] = self._format.descapes(txt.text())
self.settings["Separator"] = s
# Transformations
s = self.settings.get("Transform", {})
s["Ellipse"] = self.chkTransEllipse.isChecked()
s["Dash"] = self.chkTransDash.isChecked()
for val, chk, cmb, txtA, txtB in [
("DoubleQuotes", self.chkTransDoubleQuotes, self.cmbTransDoubleQuotes, self.txtTransDoubleQuotesA, self.txtTransDoubleQuotesB),
("SingleQuote", self.chkTransSingleQuote, self.cmbTransSingleQuote, self.txtTransSingleQuoteA, self.txtTransSingleQuoteB),
]:
if not chk.isChecked():
s[val] = False
else:
if cmb.currentData() == "custom":
s[val] = txtA.text() + "___" + txtB.text()
else:
s[val] = cmb.currentText()
s["Spaces"] = self.chkTransSpaces.isChecked()
s["Custom"] = []
for i in range(self.tblReplacements.rowCount()):
s["Custom"].append(self.getTableRowValues(self.tblReplacements, i))
self.settings["Transform"] = s
# Preview
s = self.settings.get("Preview", {})
f = self.cmbPreviewFont.currentFont()
f.setPointSize(self.spnPreviewSize.value())
s["PreviewFont"] = f.toString()
self.settings["Preview"] = s
return self.settings
def sepCmbChanged(self, index):
cmb = self.sender()
map = {
self.cmbSepFF: self.txtSepFF,
self.cmbSepTT: self.txtSepTT,
self.cmbSepFT: self.txtSepFT,
self.cmbSepTF: self.txtSepTF
}
map[cmb].setEnabled(cmb.currentData() == "custom")
def transCmbChanged(self, index):
cmb = self.sender()
map = {
self.cmbTransDoubleQuotes: (self.txtTransDoubleQuotesA, self.lblTransDoubleQuotes, self.txtTransDoubleQuotesB),
self.cmbTransSingleQuote: (self.txtTransSingleQuoteA, self.lblTransSingleQuote, self.txtTransSingleQuoteB),
}
for txt in map[cmb]:
txt.setVisible(cmb.currentData() == "custom")
def contentUpdateTable(self):
def addFolderRow(text=self.tr("Folder")):
self.tableWidgetAddRow(self.tblContent, [
self.tableWidgetMakeItem(text, "folder"),
self.tableWidgetMakeItem("", "", True, True),
])
def addTextRow(text=self.tr("Text")):
self.tableWidgetAddRow(self.tblContent, [
self.tableWidgetMakeItem(text, "text-x-generic"),
self.tableWidgetMakeItem("", "", True, False),
self.tableWidgetMakeItem("", "", True, True),
])
self.tblContent.setRowCount(0)
# Basic
addFolderRow()
addTextRow()
# Detailed
level = self.mw.mdlOutline.maxLevel()
for i in range(level):
addFolderRow(self.tr("{}Level {} folder").format(" " * i, i + 1))
for i in range(level):
addTextRow(self.tr("{}Level {} text").format(" " * i, i + 1))
self.tableWidgetAdjustToContent(self.tblContent)
def contentTableToggle(self, detailed):
for i in range(self.tblContent.rowCount()):
self.tblContent.setRowHidden(i, i in [0, 1] and detailed or (not i in [0, 1] and not detailed))
self.tableWidgetAdjustToContent(self.tblContent)
def getTableRowValues(self, table, row):
r = []
for col in range(table.columnCount()):
item = table.item(row, col)
if not item:
r.append(None)
elif item.flags() & Qt.ItemIsUserCheckable == Qt.ItemIsUserCheckable:
r.append(item.checkState() == Qt.Checked)
else:
r.append(item.text())
return r
def transAddTableRow(self, checked=True, A="", B="", regexp=False):
self.tableWidgetAddRow(self.tblReplacements, [
self.tableWidgetMakeItem("", "", True, checked),
self.tableWidgetMakeItem(A, "", False, False),
self.tableWidgetMakeItem(B, "", False, False),
self.tableWidgetMakeItem("", "", True, regexp),
])
self.tableWidgetAdjustToContent(self.tblReplacements)
def transRemoveTableRow(self):
self.tblReplacements.removeRow(self.tblReplacements.currentRow())
self.tableWidgetAdjustToContent(self.tblReplacements)
def tableWidgetMakeItem(self, text="", icon="", checkable=False, checked=False):
"""Creates a QTableWidgetItem with the given attributes."""
item = QTableWidgetItem(QIcon.fromTheme(icon), text)
if checkable:
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
item.setCheckState(Qt.Checked if checked else Qt.Unchecked)
else:
item.setFlags(item.flags() & ~Qt.ItemIsUserCheckable)
return item
def tableWidgetAddRow(self, table, items):
"""Appends the given items (list of QTableWidgetItems) to table."""
table.setRowCount(table.rowCount() + 1)
k = 0
for i in items:
table.setItem(table.rowCount() - 1, k, i)
k += 1
def tableWidgetAdjustToContent(self, table):
"""Set sizehint of QTableWidget table so that it matches content vertically."""
h = 0
h += table.horizontalHeader().height()
for i in range(table.rowCount()):
h += table.rowHeight(i)
table.setMinimumSize(QSize(0, h + 2))
table.setMaximumSize(QSize(16777215, h + 2))
def listWidgetAdjustToContent(self, lst):
"""Adjust listWidget to content."""
h = 0
for i in range(lst.count()):
h += lst.item(i).sizeHint().height()
lst.setMinimumSize(QSize(0, h+2))
lst.setMaximumSize(QSize(16777215, h+2))