diff --git a/manuskript/ui/search.py b/manuskript/ui/search.py
index 06441aeb..f177c12d 100644
--- a/manuskript/ui/search.py
+++ b/manuskript/ui/search.py
@@ -1,147 +1,151 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
-from PyQt5.QtCore import Qt, QRect
-from PyQt5.QtGui import QPalette, QFontMetrics
-from PyQt5.QtWidgets import QWidget, QMenu, QAction, qApp, QListWidgetItem, QStyledItemDelegate, QStyle
+from PyQt5.QtCore import Qt, QRect, QEvent, QCoreApplication
+from PyQt5.QtGui import QPalette, QFontMetrics, QKeySequence
+from PyQt5.QtWidgets import QWidget, qApp, QListWidgetItem, QStyledItemDelegate, QStyle, QLabel, QToolTip, QShortcut
+
-from manuskript.enums import Outline
from manuskript.functions import mainWindow
from manuskript.ui import style
from manuskript.ui.search_ui import Ui_search
-from manuskript.models import references as Ref
+from manuskript.enums import Model
+
+from manuskript.models.flatDataModelWrapper import flatDataModelWrapper
+from manuskript.ui.searchMenu import searchMenu
+from manuskript.ui.highlighters.searchResultHighlighters.searchResultHighlighter import searchResultHighlighter
class search(QWidget, Ui_search):
def __init__(self, parent=None):
+ _translate = QCoreApplication.translate
+
QWidget.__init__(self, parent)
self.setupUi(self)
- self.options = {
- "All": True,
- "Title": True,
- "Text": True,
- "Summary": False,
- "Notes": False,
- "POV": False,
- "Status": False,
- "Label": False,
- "CS": True
- }
+ self.searchTextInput.returnPressed.connect(self.search)
- self.text.returnPressed.connect(self.search)
- self.generateOptionMenu()
+ self.searchMenu = searchMenu()
+ self.btnOptions.setMenu(self.searchMenu)
self.delegate = listResultDelegate(self)
self.result.setItemDelegate(self.delegate)
+ self.result.setMouseTracking(True)
self.result.itemClicked.connect(self.openItem)
self.result.setStyleSheet(style.searchResultSS())
- self.text.setStyleSheet(style.lineEditSS())
+ self.searchTextInput.setStyleSheet(style.lineEditSS())
- def generateOptionMenu(self):
- self.menu = QMenu(self)
- a = QAction(self.tr("Search in:"), self.menu)
- a.setEnabled(False)
- self.menu.addAction(a)
- for i, d in [
- (self.tr("All"), "All"),
- (self.tr("Title"), "Title"),
- (self.tr("Text"), "Text"),
- (self.tr("Summary"), "Summary"),
- (self.tr("Notes"), "Notes"),
- (self.tr("POV"), "POV"),
- (self.tr("Status"), "Status"),
- (self.tr("Label"), "Label"),
- ]:
- a = QAction(i, self.menu)
- a.setCheckable(True)
- a.setChecked(self.options[d])
- a.setData(d)
- a.triggered.connect(self.updateOptions)
- self.menu.addAction(a)
- self.menu.addSeparator()
+ self.searchResultHighlighter = searchResultHighlighter()
- a = QAction(self.tr("Options:"), self.menu)
- a.setEnabled(False)
- self.menu.addAction(a)
- for i, d in [
- (self.tr("Case sensitive"), "CS"),
- ]:
- a = QAction(i, self.menu)
- a.setCheckable(True)
- a.setChecked(self.options[d])
- a.setData(d)
- a.triggered.connect(self.updateOptions)
- self.menu.addAction(a)
- self.menu.addSeparator()
+ self.noResultsLabel = QLabel(_translate("Search", "No results found"), self.result)
+ self.noResultsLabel.setVisible(False)
+ self.noResultsLabel.setStyleSheet("QLabel {color: gray;}")
- self.btnOptions.setMenu(self.menu)
+ # Add shortcuts for navigating through search results
+ QShortcut(QKeySequence(_translate("MainWindow", "F3")), self.searchTextInput, self.nextSearchResult)
+ QShortcut(QKeySequence(_translate("MainWindow", "Shift+F3")), self.searchTextInput, self.previousSearchResult)
- def updateOptions(self):
- a = self.sender()
- self.options[a.data()] = a.isChecked()
+ # These texts are already included in translation files but including ":" at the end. We force here the
+ # translation for them without ":"
+ _translate("MainWindow", "Situation")
+ _translate("MainWindow", "Status")
+
+ def nextSearchResult(self):
+ if self.result.currentRow() < self.result.count() - 1:
+ self.result.setCurrentRow(self.result.currentRow() + 1)
+ else:
+ self.result.setCurrentRow(0)
+
+ if 0 < self.result.currentRow() < self.result.count():
+ self.openItem(self.result.currentItem())
+
+ def previousSearchResult(self):
+ if self.result.currentRow() > 0:
+ self.result.setCurrentRow(self.result.currentRow() - 1)
+ else:
+ self.result.setCurrentRow(self.result.count() - 1)
+
+ if 0 < self.result.currentRow() < self.result.count():
+ self.openItem(self.result.currentItem())
+
+ def prepareRegex(self, searchText):
+ import re
+
+ flags = re.UNICODE
+
+ if self.searchMenu.caseSensitive() is False:
+ flags |= re.IGNORECASE
+
+ if self.searchMenu.regex() is False:
+ searchText = re.escape(searchText)
+
+ if self.searchMenu.matchWords() is True:
+ # Source: https://stackoverflow.com/a/15863102
+ searchText = r'\b' + searchText + r'\b'
+
+ return re.compile(searchText, flags)
def search(self):
- text = self.text.text()
-
- # Choosing the right columns
- lstColumns = [
- ("Title", Outline.title),
- ("Text", Outline.text),
- ("Summary", Outline.summarySentence),
- ("Summary", Outline.summaryFull),
- ("Notes", Outline.notes),
- ("POV", Outline.POV),
- ("Status", Outline.status),
- ("Label", Outline.label),
- ]
- columns = [c[1] for c in lstColumns if self.options[c[0]] or self.options["All"]]
-
- # Setting override cursor
- qApp.setOverrideCursor(Qt.WaitCursor)
-
- # Searching
- model = mainWindow().mdlOutline
- results = model.findItemsContaining(text, columns, self.options["CS"])
-
- # Showing results
self.result.clear()
- for r in results:
- index = model.getIndexByID(r)
- if not index.isValid():
- continue
- item = index.internalPointer()
- i = QListWidgetItem(item.title(), self.result)
- i.setData(Qt.UserRole, r)
- i.setData(Qt.UserRole + 1, item.path())
- self.result.addItem(i)
+ self.result.setCurrentRow(0)
- # Removing override cursor
- qApp.restoreOverrideCursor()
+ searchText = self.searchTextInput.text()
+ if len(searchText) > 0:
+ searchRegex = self.prepareRegex(searchText)
+ results = []
+
+ # Set override cursor
+ qApp.setOverrideCursor(Qt.WaitCursor)
+
+ for model, modelName in [
+ (mainWindow().mdlOutline, Model.Outline),
+ (mainWindow().mdlCharacter, Model.Character),
+ (flatDataModelWrapper(mainWindow().mdlFlatData), Model.FlatData),
+ (mainWindow().mdlWorld, Model.World),
+ (mainWindow().mdlPlots, Model.Plot)
+ ]:
+ filteredColumns = self.searchMenu.columns(modelName)
+
+ # Searching
+ if len(filteredColumns):
+ results += model.searchOccurrences(searchRegex, filteredColumns)
+
+ # Showing results
+ self.generateResultsLists(results)
+
+ # Remove override cursor
+ qApp.restoreOverrideCursor()
+
+ def generateResultsLists(self, results):
+ self.noResultsLabel.setVisible(len(results) == 0)
+ for result in results:
+ item = QListWidgetItem(result.title(), self.result)
+ item.setData(Qt.UserRole, result)
+ item.setData(Qt.UserRole + 1, ' > '.join(result.path()))
+ item.setData(Qt.UserRole + 2, result.context())
+ self.result.addItem(item)
def openItem(self, item):
- r = Ref.textReference(item.data(Qt.UserRole))
- Ref.open(r)
- # mw = mainWindow()
- # index = mw.mdlOutline.getIndexByID(item.data(Qt.UserRole))
- # mw.mainEditor.setCurrentModelIndex(index, newTab=True)
+ self.searchResultHighlighter.highlightSearchResult(item.data(Qt.UserRole))
+ def leaveEvent(self, event):
+ self.delegate.mouseLeave()
class listResultDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
+ self._tooltipRowIndex = -1
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole + 1)
+
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
-
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Highlight))
title = index.data()
- extra = " - {}".format(extra)
painter.drawText(option.rect.adjusted(2, 1, 0, 0), Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
@@ -153,5 +157,18 @@ class listResultDelegate(QStyledItemDelegate):
painter.setPen(Qt.white)
else:
painter.setPen(Qt.gray)
- painter.drawText(r.adjusted(2, 1, 0, 0), Qt.AlignLeft, extra)
+ painter.drawText(r.adjusted(2, 1, 0, 0), Qt.AlignLeft, " - {}".format(extra))
painter.restore()
+
+ def editorEvent(self, event, model, option, index):
+ if event.type() == QEvent.MouseMove and self._tooltipRowIndex != index.row():
+ self._tooltipRowIndex = index.row()
+ context = index.data(Qt.UserRole + 2)
+ extra = index.data(Qt.UserRole + 1)
+ QToolTip.showText(event.globalPos(),
+ "#" + str(index.row()) + " - " + extra + "
" + context + "
")
+ return True
+ return False
+
+ def mouseLeave(self):
+ self._tooltipRowIndex = -1
diff --git a/manuskript/ui/searchMenu.py b/manuskript/ui/searchMenu.py
new file mode 100644
index 00000000..59468f84
--- /dev/null
+++ b/manuskript/ui/searchMenu.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# --!-- coding: utf8 --!--
+from PyQt5.QtWidgets import QMenu, QAction
+from PyQt5.QtCore import QCoreApplication
+from PyQt5 import QtCore
+
+from manuskript.searchLabels import OutlineSearchLabels, CharacterSearchLabels, FlatDataSearchLabels, WorldSearchLabels, PlotSearchLabels
+from manuskript.models.searchFilter import searchFilter
+from manuskript.enums import Model
+
+
+def filterKey(modelPreffix, column):
+ return modelPreffix + str(column)
+
+
+class searchMenu(QMenu):
+ def __init__(self, parent=None):
+ QMenu.__init__(self, parent)
+
+ _translate = QCoreApplication.translate
+ # Model keys must match the ones used in search widget class
+ self.filters = {
+ Model.Outline: searchFilter(_translate("MainWindow", "Outline"), True, list(OutlineSearchLabels.keys())),
+ Model.Character: searchFilter(_translate("MainWindow", "Characters"), True, list(CharacterSearchLabels.keys())),
+ Model.FlatData: searchFilter(_translate("MainWindow", "FlatData"), True, list(FlatDataSearchLabels.keys())),
+ Model.World: searchFilter(_translate("MainWindow", "World"), True, list(WorldSearchLabels.keys())),
+ Model.Plot: searchFilter(_translate("MainWindow", "Plot"), True, list(PlotSearchLabels.keys()))
+ }
+
+ self.options = {
+ "CS": [self.tr("Case sensitive"), True],
+ "MatchWords": [self.tr("Match words"), False],
+ "Regex": [self.tr("Regex"), False]
+ }
+
+ self._generateOptions()
+
+ def _generateOptions(self):
+ a = QAction(self.tr("Search in:"), self)
+ a.setEnabled(False)
+ self.addAction(a)
+ for filterKey in self.filters:
+ a = QAction(self.tr(self.filters[filterKey].label()), self)
+ a.setCheckable(True)
+ a.setChecked(self.filters[filterKey].enabled())
+ a.setData(filterKey)
+ a.triggered.connect(self._updateFilters)
+ self.addAction(a)
+ self.addSeparator()
+
+ a = QAction(self.tr("Options:"), self)
+ a.setEnabled(False)
+ self.addAction(a)
+ for optionKey in self.options:
+ a = QAction(self.options[optionKey][0], self)
+ a.setCheckable(True)
+ a.setChecked(self.options[optionKey][1])
+ a.setData(optionKey)
+ a.triggered.connect(self._updateOptions)
+ self.addAction(a)
+ self.addSeparator()
+
+ def _updateFilters(self):
+ a = self.sender()
+ self.filters[a.data()].setEnabled(a.isChecked())
+
+ def _updateOptions(self):
+ a = self.sender()
+ self.options[a.data()][1] = a.isChecked()
+
+ def columns(self, modelName):
+ if self.filters[modelName].enabled():
+ return self.filters[modelName].modelColumns()
+ else:
+ return []
+
+ def caseSensitive(self):
+ return self.options["CS"][1]
+
+ def matchWords(self):
+ return self.options["MatchWords"][1]
+
+ def regex(self):
+ return self.options["Regex"][1]
+
+ def mouseReleaseEvent(self, event):
+ # Workaround for enabling / disabling actions without closing the menu.
+ # Source: https://stackoverflow.com/a/14967212
+ action = self.activeAction()
+ if action:
+ action.setEnabled(False)
+ QMenu.mouseReleaseEvent(self, event)
+ action.setEnabled(True)
+ action.trigger()
+ else:
+ QMenu.mouseReleaseEvent(self, event)
+
+ def keyPressEvent(self, event):
+ # Workaround for enabling / disabling actions without closing the menu.
+ # Source: https://stackoverflow.com/a/14967212
+ action = self.activeAction()
+ if action and event.key() == QtCore.Qt.Key_Return:
+ action.setEnabled(False)
+ QMenu.keyPressEvent(self, event)
+ action.setEnabled(True)
+ action.trigger()
+ else:
+ QMenu.keyPressEvent(self, event)
diff --git a/manuskript/ui/search_ui.py b/manuskript/ui/search_ui.py
index d9f5c31b..5052977e 100644
--- a/manuskript/ui/search_ui.py
+++ b/manuskript/ui/search_ui.py
@@ -19,12 +19,12 @@ class Ui_search(object):
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
- self.text = QtWidgets.QLineEdit(search)
- self.text.setInputMask("")
- self.text.setFrame(False)
- self.text.setClearButtonEnabled(True)
- self.text.setObjectName("text")
- self.horizontalLayout.addWidget(self.text)
+ self.searchTextInput = QtWidgets.QLineEdit(search)
+ self.searchTextInput.setInputMask("")
+ self.searchTextInput.setFrame(False)
+ self.searchTextInput.setClearButtonEnabled(True)
+ self.searchTextInput.setObjectName("searchTextInput")
+ self.horizontalLayout.addWidget(self.searchTextInput)
self.btnOptions = QtWidgets.QPushButton(search)
self.btnOptions.setText("")
icon = QtGui.QIcon.fromTheme("edit-find")
@@ -45,5 +45,5 @@ class Ui_search(object):
def retranslateUi(self, search):
_translate = QtCore.QCoreApplication.translate
search.setWindowTitle(_translate("search", "Form"))
- self.text.setPlaceholderText(_translate("search", "Search for..."))
+ self.searchTextInput.setPlaceholderText(_translate("search", "Search for..."))
diff --git a/manuskript/ui/search_ui.ui b/manuskript/ui/search_ui.ui
index 1b63fdcf..89eb0a09 100644
--- a/manuskript/ui/search_ui.ui
+++ b/manuskript/ui/search_ui.ui
@@ -35,7 +35,7 @@
0
-
-
+
diff --git a/manuskript/ui/settings_ui.py b/manuskript/ui/settings_ui.py
index 0cd39f5b..b34d9823 100644
--- a/manuskript/ui/settings_ui.py
+++ b/manuskript/ui/settings_ui.py
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file 'manuskript/ui/settings_ui.ui'
+# Form implementation generated from reading ui file 'settings_ui.ui'
#
-# Created by: PyQt5 UI code generator 5.13.0
+# Created by: PyQt5 UI code generator 5.15.0
#
-# WARNING! All changes made in this file will be lost!
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
@@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Settings(object):
def setupUi(self, Settings):
Settings.setObjectName("Settings")
- Settings.resize(658, 598)
+ Settings.resize(681, 598)
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(Settings)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.lstMenu = QtWidgets.QListWidget(Settings)
@@ -55,50 +56,9 @@ class Ui_Settings(object):
self.groupBox_2.setFont(font)
self.groupBox_2.setObjectName("groupBox_2")
self.formLayout_13 = QtWidgets.QFormLayout(self.groupBox_2)
- self.formLayout_13.setFieldGrowthPolicy(QtWidgets.QFormLayout.FieldsStayAtSizeHint)
self.formLayout_13.setObjectName("formLayout_13")
- self.label_56 = QtWidgets.QLabel(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.label_56.setFont(font)
- self.label_56.setObjectName("label_56")
- self.formLayout_13.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_56)
- self.cmbStyle = QtWidgets.QComboBox(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.cmbStyle.setFont(font)
- self.cmbStyle.setObjectName("cmbStyle")
- self.formLayout_13.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.cmbStyle)
- self.label_57 = QtWidgets.QLabel(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.label_57.setFont(font)
- self.label_57.setObjectName("label_57")
- self.formLayout_13.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_57)
- self.cmbTranslation = QtWidgets.QComboBox(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.cmbTranslation.setFont(font)
- self.cmbTranslation.setObjectName("cmbTranslation")
- self.formLayout_13.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.cmbTranslation)
- self.label_58 = QtWidgets.QLabel(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.label_58.setFont(font)
- self.label_58.setObjectName("label_58")
- self.formLayout_13.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_58)
- self.spnGeneralFontSize = QtWidgets.QSpinBox(self.groupBox_2)
- font = QtGui.QFont()
- font.setBold(False)
- font.setWeight(50)
- self.spnGeneralFontSize.setFont(font)
- self.spnGeneralFontSize.setObjectName("spnGeneralFontSize")
- self.formLayout_13.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.spnGeneralFontSize)
+ self.gridLayout_4 = QtWidgets.QGridLayout()
+ self.gridLayout_4.setObjectName("gridLayout_4")
self.label_2 = QtWidgets.QLabel(self.groupBox_2)
font = QtGui.QFont()
font.setBold(False)
@@ -106,7 +66,70 @@ class Ui_Settings(object):
self.label_2.setFont(font)
self.label_2.setWordWrap(True)
self.label_2.setObjectName("label_2")
- self.formLayout_13.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.label_2)
+ self.gridLayout_4.addWidget(self.label_2, 0, 0, 1, 1)
+ self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_12.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+ self.horizontalLayout_12.setObjectName("horizontalLayout_12")
+ self.formLayout_14 = QtWidgets.QFormLayout()
+ self.formLayout_14.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
+ self.formLayout_14.setObjectName("formLayout_14")
+ self.label_56 = QtWidgets.QLabel(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.label_56.setFont(font)
+ self.label_56.setObjectName("label_56")
+ self.formLayout_14.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_56)
+ self.cmbStyle = QtWidgets.QComboBox(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.cmbStyle.setFont(font)
+ self.cmbStyle.setObjectName("cmbStyle")
+ self.formLayout_14.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cmbStyle)
+ self.label_57 = QtWidgets.QLabel(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.label_57.setFont(font)
+ self.label_57.setObjectName("label_57")
+ self.formLayout_14.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_57)
+ self.cmbTranslation = QtWidgets.QComboBox(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.cmbTranslation.setFont(font)
+ self.cmbTranslation.setObjectName("cmbTranslation")
+ self.formLayout_14.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.cmbTranslation)
+ self.label_58 = QtWidgets.QLabel(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.label_58.setFont(font)
+ self.label_58.setObjectName("label_58")
+ self.formLayout_14.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_58)
+ self.spnGeneralFontSize = QtWidgets.QSpinBox(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.spnGeneralFontSize.setFont(font)
+ self.spnGeneralFontSize.setObjectName("spnGeneralFontSize")
+ self.formLayout_14.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.spnGeneralFontSize)
+ self.horizontalLayout_12.addLayout(self.formLayout_14)
+ self.formLayout_15 = QtWidgets.QFormLayout()
+ self.formLayout_15.setObjectName("formLayout_15")
+ self.chkProgressChars = QtWidgets.QCheckBox(self.groupBox_2)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.chkProgressChars.setFont(font)
+ self.chkProgressChars.setObjectName("chkProgressChars")
+ self.formLayout_15.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.chkProgressChars)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.formLayout_15.setItem(0, QtWidgets.QFormLayout.LabelRole, spacerItem)
+ self.horizontalLayout_12.addLayout(self.formLayout_15)
+ self.gridLayout_4.addLayout(self.horizontalLayout_12, 1, 0, 1, 1)
+ self.formLayout_13.setLayout(0, QtWidgets.QFormLayout.SpanningRole, self.gridLayout_4)
self.verticalLayout_7.addWidget(self.groupBox_2)
self.groupBox_10 = QtWidgets.QGroupBox(self.stackedWidgetPage1)
font = QtGui.QFont()
@@ -166,8 +189,8 @@ class Ui_Settings(object):
self.label.setFont(font)
self.label.setObjectName("label")
self.horizontalLayout_5.addWidget(self.label)
- spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout_5.addItem(spacerItem)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_5.addItem(spacerItem1)
self.verticalLayout_6.addLayout(self.horizontalLayout_5)
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
@@ -202,8 +225,8 @@ class Ui_Settings(object):
self.label_14.setFont(font)
self.label_14.setObjectName("label_14")
self.horizontalLayout_7.addWidget(self.label_14)
- spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout_7.addItem(spacerItem1)
+ spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_7.addItem(spacerItem2)
self.verticalLayout_6.addLayout(self.horizontalLayout_7)
self.chkSaveOnQuit = QtWidgets.QCheckBox(self.groupBox)
font = QtGui.QFont()
@@ -223,8 +246,8 @@ class Ui_Settings(object):
self.chkSaveToZip.setObjectName("chkSaveToZip")
self.verticalLayout_6.addWidget(self.chkSaveToZip)
self.verticalLayout_7.addWidget(self.groupBox)
- spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_7.addItem(spacerItem2)
+ spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_7.addItem(spacerItem3)
self.stack.addWidget(self.stackedWidgetPage1)
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
@@ -388,8 +411,8 @@ class Ui_Settings(object):
self.label_51.setObjectName("label_51")
self.gridLayout_2.addWidget(self.label_51, 6, 1, 1, 1)
self.verticalLayout.addWidget(self.chkRevisionRemove)
- spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout.addItem(spacerItem3)
+ spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout.addItem(spacerItem4)
self.label_revisionDeprecation = QtWidgets.QLabel(self.page_3)
self.label_revisionDeprecation.setWordWrap(True)
self.label_revisionDeprecation.setOpenExternalLinks(True)
@@ -524,6 +547,25 @@ class Ui_Settings(object):
self.sldTreeIconSize.setObjectName("sldTreeIconSize")
self.horizontalLayout_11.addWidget(self.sldTreeIconSize)
self.verticalLayout_17.addWidget(self.groupBox_16)
+ self.horizontalGroupBox = QtWidgets.QGroupBox(self.tab)
+ font = QtGui.QFont()
+ font.setBold(True)
+ font.setWeight(75)
+ self.horizontalGroupBox.setFont(font)
+ self.horizontalGroupBox.setObjectName("horizontalGroupBox")
+ self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.horizontalGroupBox)
+ self.horizontalLayout_13.setContentsMargins(9, 9, 9, 9)
+ self.horizontalLayout_13.setObjectName("horizontalLayout_13")
+ self.chkCountSpaces = QtWidgets.QCheckBox(self.horizontalGroupBox)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.chkCountSpaces.setFont(font)
+ self.chkCountSpaces.setObjectName("chkCountSpaces")
+ self.horizontalLayout_13.addWidget(self.chkCountSpaces)
+ spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_13.addItem(spacerItem5)
+ self.verticalLayout_17.addWidget(self.horizontalGroupBox)
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.groupBox_8 = QtWidgets.QGroupBox(self.tab)
@@ -548,6 +590,13 @@ class Ui_Settings(object):
self.rdoTreeWC.setFont(font)
self.rdoTreeWC.setObjectName("rdoTreeWC")
self.verticalLayout_15.addWidget(self.rdoTreeWC)
+ self.rdoTreeCC = QtWidgets.QRadioButton(self.groupBox_8)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.rdoTreeCC.setFont(font)
+ self.rdoTreeCC.setObjectName("rdoTreeCC")
+ self.verticalLayout_15.addWidget(self.rdoTreeCC)
self.rdoTreeProgress = QtWidgets.QRadioButton(self.groupBox_8)
font = QtGui.QFont()
font.setBold(False)
@@ -586,6 +635,13 @@ class Ui_Settings(object):
self.rdoTreeTextWC.setFont(font)
self.rdoTreeTextWC.setObjectName("rdoTreeTextWC")
self.verticalLayout_16.addWidget(self.rdoTreeTextWC)
+ self.rdoTreeTextCC = QtWidgets.QRadioButton(self.groupBox_9)
+ font = QtGui.QFont()
+ font.setBold(False)
+ font.setWeight(50)
+ self.rdoTreeTextCC.setFont(font)
+ self.rdoTreeTextCC.setObjectName("rdoTreeTextCC")
+ self.verticalLayout_16.addWidget(self.rdoTreeTextCC)
self.rdoTreeTextProgress = QtWidgets.QRadioButton(self.groupBox_9)
font = QtGui.QFont()
font.setBold(False)
@@ -607,12 +663,17 @@ class Ui_Settings(object):
self.rdoTreeTextNothing.setFont(font)
self.rdoTreeTextNothing.setObjectName("rdoTreeTextNothing")
self.verticalLayout_16.addWidget(self.rdoTreeTextNothing)
- spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_16.addItem(spacerItem4)
+ spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_16.addItem(spacerItem6)
+ self.rdoTreeTextCC.raise_()
+ self.rdoTreeTextWC.raise_()
+ self.rdoTreeTextProgress.raise_()
+ self.rdoTreeTextSummary.raise_()
+ self.rdoTreeTextNothing.raise_()
self.horizontalLayout_9.addWidget(self.groupBox_9)
self.verticalLayout_17.addLayout(self.horizontalLayout_9)
- spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_17.addItem(spacerItem5)
+ spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_17.addItem(spacerItem7)
icon = QtGui.QIcon.fromTheme("view-list-tree")
self.tabViews.addTab(self.tab, icon, "")
self.tab_2 = QtWidgets.QWidget()
@@ -774,8 +835,8 @@ class Ui_Settings(object):
self.chkOutlineTitle.setObjectName("chkOutlineTitle")
self.gridLayout.addWidget(self.chkOutlineTitle, 3, 0, 1, 1)
self.verticalLayout_11.addWidget(self.groupBox_6)
- spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_11.addItem(spacerItem6)
+ spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_11.addItem(spacerItem8)
icon = QtGui.QIcon.fromTheme("view-outline")
self.tabViews.addTab(self.tab_2, icon, "")
self.tab_3 = QtWidgets.QWidget()
@@ -821,8 +882,8 @@ class Ui_Settings(object):
self.cmbCorkImage.setFont(font)
self.cmbCorkImage.setObjectName("cmbCorkImage")
self.verticalLayout_8.addWidget(self.cmbCorkImage)
- spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_8.addItem(spacerItem7)
+ spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_8.addItem(spacerItem9)
self.gridLayout_3.addWidget(self.groupBox_7, 1, 1, 1, 1)
self.groupBox_11 = QtWidgets.QGroupBox(self.tab_3)
font = QtGui.QFont()
@@ -1380,8 +1441,8 @@ class Ui_Settings(object):
self.btnLabelColor.setIconSize(QtCore.QSize(64, 64))
self.btnLabelColor.setObjectName("btnLabelColor")
self.verticalLayout_2.addWidget(self.btnLabelColor)
- spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout_2.addItem(spacerItem8)
+ spacerItem10 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_2.addItem(spacerItem10)
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
self.verticalLayout_3.addLayout(self.horizontalLayout_2)
self.horizontalLayout = QtWidgets.QHBoxLayout()
@@ -1398,8 +1459,8 @@ class Ui_Settings(object):
self.btnLabelRemove.setIcon(icon)
self.btnLabelRemove.setObjectName("btnLabelRemove")
self.horizontalLayout.addWidget(self.btnLabelRemove)
- spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout.addItem(spacerItem9)
+ spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem11)
self.verticalLayout_3.addLayout(self.horizontalLayout)
self.stack.addWidget(self.stackedWidgetPage3)
self.stackedWidgetPage4 = QtWidgets.QWidget()
@@ -1433,8 +1494,8 @@ class Ui_Settings(object):
self.btnStatusRemove.setIcon(icon)
self.btnStatusRemove.setObjectName("btnStatusRemove")
self.horizontalLayout_3.addWidget(self.btnStatusRemove)
- spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout_3.addItem(spacerItem10)
+ spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_3.addItem(spacerItem12)
self.verticalLayout_4.addLayout(self.horizontalLayout_3)
self.stack.addWidget(self.stackedWidgetPage4)
self.page = QtWidgets.QWidget()
@@ -1482,8 +1543,8 @@ class Ui_Settings(object):
self.btnThemeRemove.setIcon(icon)
self.btnThemeRemove.setObjectName("btnThemeRemove")
self.horizontalLayout_6.addWidget(self.btnThemeRemove)
- spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout_6.addItem(spacerItem11)
+ spacerItem13 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_6.addItem(spacerItem13)
self.verticalLayout_12.addLayout(self.horizontalLayout_6)
self.themeStack.addWidget(self.stackedWidgetPage1_3)
self.stackedWidgetPage2_3 = QtWidgets.QWidget()
@@ -1823,9 +1884,9 @@ class Ui_Settings(object):
self.horizontalLayout_8.addWidget(self.stack)
self.retranslateUi(Settings)
- self.stack.setCurrentIndex(2)
- self.tabViews.setCurrentIndex(3)
- self.themeStack.setCurrentIndex(1)
+ self.stack.setCurrentIndex(0)
+ self.tabViews.setCurrentIndex(0)
+ self.themeStack.setCurrentIndex(0)
self.themeEditStack.setCurrentIndex(3)
self.lstMenu.currentRowChanged['int'].connect(self.stack.setCurrentIndex)
self.chkRevisionsKeep.toggled['bool'].connect(self.chkRevisionRemove.setEnabled)
@@ -1851,10 +1912,12 @@ class Ui_Settings(object):
self.lstMenu.setSortingEnabled(__sortingEnabled)
self.lblTitleGeneral.setText(_translate("Settings", "General settings"))
self.groupBox_2.setTitle(_translate("Settings", "Application settings"))
+ self.label_2.setText(_translate("Settings", "Restarting Manuskript ensures all settings take effect."))
self.label_56.setText(_translate("Settings", "Style:"))
self.label_57.setText(_translate("Settings", "Language:"))
self.label_58.setText(_translate("Settings", "Font size:"))
- self.label_2.setText(_translate("Settings", "Restarting Manuskript ensures all settings take effect."))
+ self.chkProgressChars.setText(_translate("Settings", "Show progress in chars next\n"
+" to words"))
self.groupBox_10.setTitle(_translate("Settings", "Loading"))
self.chkAutoLoad.setText(_translate("Settings", "Automatically load last project on startup"))
self.groupBox.setTitle(_translate("Settings", "Saving"))
@@ -1899,14 +1962,18 @@ class Ui_Settings(object):
self.cmbTreeBackground.setItemText(4, _translate("Settings", "Compile"))
self.groupBox_16.setTitle(_translate("Settings", "Icon Size"))
self.lblTreeIconSize.setText(_translate("Settings", "TextLabel"))
+ self.horizontalGroupBox.setTitle(_translate("Settings", "Char/Word Counter"))
+ self.chkCountSpaces.setText(_translate("Settings", "Count spaces as chars"))
self.groupBox_8.setTitle(_translate("Settings", "Folders"))
self.rdoTreeItemCount.setText(_translate("Settings", "Show ite&m count"))
self.rdoTreeWC.setText(_translate("Settings", "Show &word count"))
+ self.rdoTreeCC.setText(_translate("Settings", "Show char c&ount"))
self.rdoTreeProgress.setText(_translate("Settings", "S&how progress"))
self.rdoTreeSummary.setText(_translate("Settings", "Show summar&y"))
self.rdoTreeNothing.setText(_translate("Settings", "&Nothing"))
self.groupBox_9.setTitle(_translate("Settings", "Text"))
self.rdoTreeTextWC.setText(_translate("Settings", "&Show word count"))
+ self.rdoTreeTextCC.setText(_translate("Settings", "Sho&w char count"))
self.rdoTreeTextProgress.setText(_translate("Settings", "Show p&rogress"))
self.rdoTreeTextSummary.setText(_translate("Settings", "Show summary"))
self.rdoTreeTextNothing.setText(_translate("Settings", "Nothing"))
diff --git a/manuskript/ui/settings_ui.ui b/manuskript/ui/settings_ui.ui
index 6563bcbb..6b1a658d 100644
--- a/manuskript/ui/settings_ui.ui
+++ b/manuskript/ui/settings_ui.ui
@@ -6,7 +6,7 @@
0
0
- 658
+ 681
598
@@ -54,7 +54,7 @@
-
- 2
+ 0
@@ -98,93 +98,139 @@
Application settings
-
- QFormLayout::FieldsStayAtSizeHint
-
-
-
-
-
-
- 50
- false
-
-
-
- Style:
-
-
-
- -
-
-
-
- 50
- false
-
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Language:
-
-
-
- -
-
-
-
- 50
- false
-
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Font size:
-
-
-
- -
-
-
-
- 50
- false
-
-
-
-
- -
-
-
-
- 50
- false
-
-
-
- Restarting Manuskript ensures all settings take effect.
-
-
- true
-
-
+
-
+
+
-
+
+
+
+ 50
+ false
+
+
+
+ Restarting Manuskript ensures all settings take effect.
+
+
+ true
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+
+ 50
+ false
+
+
+
+ Style:
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Language:
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Font size:
+
+
+
+ -
+
+
+
+ 50
+ false
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 50
+ false
+
+
+
+ Show progress in chars next
+ to words
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
@@ -817,7 +863,7 @@
-
- 3
+ 0
@@ -1055,6 +1101,59 @@
+ -
+
+
+
+ 75
+ true
+
+
+
+ Char/Word Counter
+
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
-
+
+
+
+ 50
+ false
+
+
+
+ Count spaces as chars
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
-
-
@@ -1095,6 +1194,19 @@
+ -
+
+
+
+ 50
+ false
+
+
+
+ Show char c&ount
+
+
+
-
@@ -1165,6 +1277,19 @@
+ -
+
+
+
+ 50
+ false
+
+
+
+ Sho&w char count
+
+
+
-
@@ -1224,6 +1349,11 @@
+ rdoTreeTextCC
+ rdoTreeTextWC
+ rdoTreeTextProgress
+ rdoTreeTextSummary
+ rdoTreeTextNothing
@@ -2974,7 +3104,7 @@
-
- 1
+ 0
diff --git a/manuskript/ui/views/MDEditCompleter.py b/manuskript/ui/views/MDEditCompleter.py
index e0db6808..0101238d 100644
--- a/manuskript/ui/views/MDEditCompleter.py
+++ b/manuskript/ui/views/MDEditCompleter.py
@@ -106,13 +106,18 @@ class MDEditCompleter(MDEditView):
self.completer.popup(self.textUnderCursor(select=True))
def mouseMoveEvent(self, event):
+ """
+ When mouse moves, we show tooltip when appropriate.
+ """
+ self.beginTooltipMoveEvent()
MDEditView.mouseMoveEvent(self, event)
+ self.endTooltipMoveEvent()
onRef = [r for r in self.refRects if r.contains(event.pos())]
if not onRef:
qApp.restoreOverrideCursor()
- QToolTip.hideText()
+ self.hideTooltip()
return
cursor = self.cursorForPosition(event.pos())
@@ -120,7 +125,8 @@ class MDEditCompleter(MDEditView):
if ref:
if not qApp.overrideCursor():
qApp.setOverrideCursor(Qt.PointingHandCursor)
- QToolTip.showText(self.mapToGlobal(event.pos()), Ref.tooltip(ref))
+
+ self.showTooltip(self.mapToGlobal(event.pos()), Ref.tooltip(ref))
def mouseReleaseEvent(self, event):
MDEditView.mouseReleaseEvent(self, event)
diff --git a/manuskript/ui/views/MDEditView.py b/manuskript/ui/views/MDEditView.py
index e8eb5644..c5f4c338 100644
--- a/manuskript/ui/views/MDEditView.py
+++ b/manuskript/ui/views/MDEditView.py
@@ -506,13 +506,15 @@ class MDEditView(textEditView):
"""
When mouse moves, we show tooltip when appropriate.
"""
+ self.beginTooltipMoveEvent()
textEditView.mouseMoveEvent(self, event)
+ self.endTooltipMoveEvent()
onRect = [r for r in self.clickRects if r.rect.contains(event.pos())]
if not onRect:
qApp.restoreOverrideCursor()
- QToolTip.hideText()
+ self.hideTooltip()
return
ct = onRect[0]
@@ -534,7 +536,7 @@ class MDEditView(textEditView):
if tooltip:
tooltip = self.tr("{} (CTRL+Click to open)").format(tooltip)
- QToolTip.showText(self.mapToGlobal(event.pos()), tooltip)
+ self.showTooltip(self.mapToGlobal(event.pos()), tooltip)
def mouseReleaseEvent(self, event):
textEditView.mouseReleaseEvent(self, event)
diff --git a/manuskript/ui/views/characterTreeView.py b/manuskript/ui/views/characterTreeView.py
index 6997f903..ea5798ce 100644
--- a/manuskript/ui/views/characterTreeView.py
+++ b/manuskript/ui/views/characterTreeView.py
@@ -29,6 +29,8 @@ class characterTreeView(QTreeWidget):
self._rootItem = QTreeWidgetItem()
self.insertTopLevelItem(0, self._rootItem)
+ self.importanceMap = {self.tr("Main"):2, self.tr("Secondary"):1, self.tr("Minor"):0}
+
def setCharactersModel(self, model):
self._model = model
self._model.dataChanged.connect(self.updateMaybe)
@@ -64,7 +66,7 @@ class characterTreeView(QTreeWidget):
for child in range(item.childCount()):
sub = item.child(child)
ID = sub.data(0, Qt.UserRole)
- if ID is not None:
+ if ID != None:
# Update name
c = self._model.getCharacterByID(ID)
name = c.name()
@@ -86,11 +88,9 @@ class characterTreeView(QTreeWidget):
self.clear()
characters = self._model.getCharactersByImportance()
- h = [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]
-
- for i in range(3):
+ for i, importanceLevel in enumerate(self.importanceMap):
# Create category item
- cat = QTreeWidgetItem(self, [h[i]])
+ cat = QTreeWidgetItem(self, [importanceLevel])
cat.setBackground(0, QBrush(QColor(S.highlightLight)))
cat.setForeground(0, QBrush(QColor(S.highlightedTextDark)))
cat.setTextAlignment(0, Qt.AlignCenter)
@@ -119,6 +119,24 @@ class characterTreeView(QTreeWidget):
self.expandAll()
self._updating = False
+ def addCharacter(self):
+ curr_item = self.currentItem()
+ curr_importance = 0
+
+ # check if an item is selected
+ if curr_item != None:
+ if curr_item.parent() == None:
+ # this is a top-level category, so find its importance
+ # get the current text, then look up the importance level
+ text = curr_item.text(0)
+ curr_importance = self.importanceMap[text]
+ else:
+ # get the importance from the currently-highlighted character
+ curr_character = self.currentCharacter()
+ curr_importance = curr_character.importance()
+
+ self._model.addCharacter(importance=curr_importance)
+
def removeCharacter(self):
"""
Removes selected character.
@@ -130,22 +148,30 @@ class characterTreeView(QTreeWidget):
def choseCharacterColor(self):
ID = self.currentCharacterID()
c = self._model.getCharacterByID(ID)
+
if c:
color = iconColor(c.icon)
else:
color = Qt.white
+
self.colorDialog = QColorDialog(color, mainWindow())
color = self.colorDialog.getColor(color)
+
if color.isValid():
c.setColor(color)
mainWindow().updateCharacterColor(ID)
+ def changeCharacterPOVState(self, state):
+ ID = self.currentCharacterID()
+ c = self._model.getCharacterByID(ID)
+ c.setPOVEnabled(state == Qt.Checked)
+ mainWindow().updateCharacterPOVState(ID)
+
def addCharacterInfo(self):
self._model.addCharacterInfo(self.currentCharacterID())
def removeCharacterInfo(self):
- self._model.removeCharacterInfo(self.currentCharacterID(),
- )
+ self._model.removeCharacterInfo(self.currentCharacterID())
def currentCharacterID(self):
ID = None
diff --git a/manuskript/ui/views/corkDelegate.py b/manuskript/ui/views/corkDelegate.py
index 70ff19e1..bd776c1a 100644
--- a/manuskript/ui/views/corkDelegate.py
+++ b/manuskript/ui/views/corkDelegate.py
@@ -43,11 +43,19 @@ class corkDelegate(QStyledItemDelegate):
return QStyledItemDelegate.editorEvent(self, event, model, option, index)
def createEditor(self, parent, option, index):
+ # When the user performs a global search and selects an Outline result (title or summary), the
+ # associated chapter is selected in cork view, triggering a call to this method with the results
+ # list widget set in self.sender(). In this case we store the searched column so we know which
+ # editor should be created.
+ searchedColumn = None
+ if self.sender() is not None and self.sender().objectName() == 'result' and self.sender().currentItem():
+ searchedColumn = self.sender().currentItem().data(Qt.UserRole).column()
+
self.updateRects(option, index)
bgColor = self.bgColors.get(index, "white")
- if self.mainLineRect.contains(self.lastPos):
+ if searchedColumn == Outline.summarySentence or (self.lastPos is not None and self.mainLineRect.contains(self.lastPos)):
# One line summary
self.editing = Outline.summarySentence
edt = QLineEdit(parent)
@@ -64,7 +72,7 @@ class corkDelegate(QStyledItemDelegate):
edt.setStyleSheet("background: {}; color: black;".format(bgColor))
return edt
- elif self.titleRect.contains(self.lastPos):
+ elif searchedColumn == Outline.title or (self.lastPos is not None and self.titleRect.contains(self.lastPos)):
# Title
self.editing = Outline.title
edt = QLineEdit(parent)
diff --git a/manuskript/ui/views/corkView.py b/manuskript/ui/views/corkView.py
index e77e49db..864a02a0 100644
--- a/manuskript/ui/views/corkView.py
+++ b/manuskript/ui/views/corkView.py
@@ -27,6 +27,8 @@ class corkView(QListView, dndView, outlineBasics):
def updateBackground(self):
if settings.corkBackground["image"] != "":
img = findBackground(settings.corkBackground["image"])
+ if img == None:
+ img = ""
else:
# No background image
img = ""
diff --git a/manuskript/ui/views/lineEditView.py b/manuskript/ui/views/lineEditView.py
index 0366016a..b61042f0 100644
--- a/manuskript/ui/views/lineEditView.py
+++ b/manuskript/ui/views/lineEditView.py
@@ -31,7 +31,7 @@ class lineEditView(QLineEdit):
self._index = index
self._model = index.model()
# self.item = index.internalPointer()
- if self._placeholderText is not None:
+ if self._placeholderText != None:
self.setPlaceholderText(self._placeholderText)
self.textEdited.connect(self.submit)
self.updateText()
diff --git a/manuskript/ui/views/outlineDelegates.py b/manuskript/ui/views/outlineDelegates.py
index 48bba8ee..4fdc0f23 100644
--- a/manuskript/ui/views/outlineDelegates.py
+++ b/manuskript/ui/views/outlineDelegates.py
@@ -313,7 +313,7 @@ class outlineLabelDelegate(QStyledItemDelegate):
idx = self.mdlLabels.indexFromItem(item)
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, idx)
- s = qApp.style().sizeFromContents(QStyle.CT_ItemViewItem, opt, QSize())
+ s = qApp.style().sizeFromContents(QStyle.CT_ItemViewItem, opt, QSize(), None)
if s.width() > 150:
s.setWidth(150)
elif s.width() < 50:
diff --git a/manuskript/ui/views/propertiesView.py b/manuskript/ui/views/propertiesView.py
index 861dc746..2ae088d1 100644
--- a/manuskript/ui/views/propertiesView.py
+++ b/manuskript/ui/views/propertiesView.py
@@ -5,6 +5,7 @@ from PyQt5.QtGui import QIntValidator
from manuskript.enums import Outline
from manuskript.ui.views.propertiesView_ui import Ui_propertiesView
+from manuskript.models.characterPOVModel import characterPOVModel
class propertiesView(QWidget, Ui_propertiesView):
@@ -14,7 +15,7 @@ class propertiesView(QWidget, Ui_propertiesView):
self.txtGoal.setColumn(Outline.setGoal)
def setModels(self, mdlOutline, mdlCharacter, mdlLabels, mdlStatus):
- self.cmbPOV.setModels(mdlCharacter, mdlOutline)
+ self.cmbPOV.setModels(characterPOVModel(mdlCharacter), mdlOutline)
self.cmbLabel.setModels(mdlLabels, mdlOutline)
self.cmbStatus.setModels(mdlStatus, mdlOutline)
self.chkCompile.setModel(mdlOutline)
diff --git a/manuskript/ui/views/textEditView.py b/manuskript/ui/views/textEditView.py
index 41324eb5..b361bdfc 100644
--- a/manuskript/ui/views/textEditView.py
+++ b/manuskript/ui/views/textEditView.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
-import re
+import re, textwrap
from PyQt5.Qt import QApplication
from PyQt5.QtCore import QTimer, QModelIndex, Qt, QEvent, pyqtSignal, QRegExp, QLocale, QPersistentModelIndex, QMutex
from PyQt5.QtGui import QTextBlockFormat, QTextCharFormat, QFont, QColor, QIcon, QMouseEvent, QTextCursor
-from PyQt5.QtWidgets import QWidget, QTextEdit, qApp, QAction, QMenu
+from PyQt5.QtWidgets import QWidget, QTextEdit, qApp, QAction, QMenu, QToolTip
from manuskript import settings
from manuskript.enums import Outline, World, Character, Plot
@@ -14,6 +14,8 @@ from manuskript.models import outlineModel, outlineItem
from manuskript.ui.highlighters import BasicHighlighter
from manuskript.ui import style as S
from manuskript.functions import Spellchecker
+from manuskript.models.characterModel import Character, CharacterInfo
+
class textEditView(QTextEdit):
def __init__(self, parent=None, index=None, html=None, spellcheck=None,
@@ -34,7 +36,7 @@ class textEditView(QTextEdit):
self._themeData = None
self._highlighterClass = BasicHighlighter
- if spellcheck is None:
+ if spellcheck == None:
spellcheck = settings.spellcheck
self.spellcheck = spellcheck
@@ -47,6 +49,8 @@ class textEditView(QTextEdit):
self.highlightWord = ""
self.highligtCS = False
self._dict = None
+ self._tooltip = { 'depth' : 0, 'active' : 0 }
+
# self.document().contentsChanged.connect(self.submit, F.AUC)
# Submit text changed only after 500ms without modifications
@@ -163,9 +167,9 @@ class textEditView(QTextEdit):
def loadFontSettings(self):
if self._fromTheme or \
- not self._index or \
- type(self._index.model()) != outlineModel or \
- self._column != Outline.text:
+ not self._index or \
+ type(self._index.model()) != outlineModel or \
+ self._column != Outline.text:
return
opt = settings.textEditor
@@ -173,7 +177,7 @@ class textEditView(QTextEdit):
f.fromString(opt["font"])
background = (opt["background"] if not opt["backgroundTransparent"]
else "transparent")
- foreground = opt["fontColor"] # if not opt["backgroundTransparent"]
+ foreground = opt["fontColor"] # if not opt["backgroundTransparent"]
# else S.text
# self.setFont(f)
self.setStyleSheet("""QTextEdit{{
@@ -185,15 +189,16 @@ class textEditView(QTextEdit):
{maxWidth}
}}
""".format(
- bg=background,
- foreground=foreground,
- ff=f.family(),
- fs="{}pt".format(str(f.pointSize())),
- mTB = opt["marginsTB"],
- mLR = opt["marginsLR"],
- maxWidth = "max-width: {}px;".format(opt["maxWidth"]) if opt["maxWidth"] else "",
- )
- )
+ bg=background,
+ foreground=foreground,
+ ff=f.family(),
+ fs="{}pt".format(str(f.pointSize())),
+ mTB=opt["marginsTB"],
+ mLR=opt["marginsLR"],
+ maxWidth="max-width: {}px;".format(
+ opt["maxWidth"]) if opt["maxWidth"] else "",
+ )
+ )
self._defaultFontSize = f.pointSize()
# We set the parent background to the editor's background in case
@@ -205,11 +210,11 @@ class textEditView(QTextEdit):
QWidget#{name}{{
background: {bg};
}}""".format(
- # We style by name, otherwise all inheriting widgets get the same
- # colored background, for example context menu.
- name=self.parent().objectName(),
- bg=background,
- ))
+ # We style by name, otherwise all inheriting widgets get the same
+ # colored background, for example context menu.
+ name=self.parent().objectName(),
+ bg=background,
+ ))
cf = QTextCharFormat()
# cf.setFont(f)
@@ -393,6 +398,49 @@ class textEditView(QTextEdit):
Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
QTextEdit.mousePressEvent(self, event)
+ def beginTooltipMoveEvent(self):
+ self._tooltip['depth'] += 1
+
+ def endTooltipMoveEvent(self):
+ self._tooltip['depth'] -= 1
+
+ def showTooltip(self, pos, text):
+ QToolTip.showText(pos, text)
+ self._tooltip['active'] = self._tooltip['depth']
+
+ def hideTooltip(self):
+ if self._tooltip['active'] == self._tooltip['depth']:
+ QToolTip.hideText()
+
+ def mouseMoveEvent(self, event):
+ """
+ When mouse moves, we show tooltip when appropriate.
+ """
+ self.beginTooltipMoveEvent()
+ QTextEdit.mouseMoveEvent(self, event)
+ self.endTooltipMoveEvent()
+
+ match = None
+
+ # Check if the selected word has any suggestions for correction
+ if self.spellcheck and self._dict:
+ cursor = self.cursorForPosition(event.pos())
+
+ # Searches for correlating/overlapping matches
+ suggestions = self._dict.findSuggestions(self.toPlainText(), cursor.selectionStart(), cursor.selectionEnd())
+
+ if len(suggestions) > 0:
+ # I think it should focus on one type of error at a time.
+ match = suggestions[0]
+
+ if match:
+ # Wrap the message into a fitting width
+ msg_lines = textwrap.wrap(match.msg, 48)
+
+ self.showTooltip(event.globalPos(), "\n".join(msg_lines))
+ else:
+ self.hideTooltip()
+
def wheelEvent(self, event):
"""
We catch wheelEvent if key modifier is CTRL to change font size.
@@ -427,58 +475,198 @@ class textEditView(QTextEdit):
QAction.__init__(self, *args)
self.triggered.connect(lambda x: self.correct.emit(
- str(self.text())))
+ str(self.text())))
def contextMenuEvent(self, event):
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
popup_menu = self.createStandardContextMenu()
popup_menu.exec_(event.globalPos())
+ def newCharacter(self):
+ text = self.sender().data()
+ print("new character!", text)
+ # switch to character page
+ mw = F.mainWindow()
+ mw.tabMain.setCurrentIndex(mw.TabPersos)
+ # add character
+ c = mw.mdlCharacter.addCharacter(name=text)
+ # switch to character
+ item = mw.lstCharacters.getItemByID(c.ID())
+ mw.lstCharacters.setCurrentItem(item)
+
+ def newPlotItem(self):
+ text = self.sender().data()
+ print("new plot item!", text)
+ # switch to plot page
+ mw = F.mainWindow()
+ mw.tabMain.setCurrentIndex(mw.TabPlots)
+ # add character
+ p, ID = mw.mdlPlots.addPlot(text)
+ # switch to character
+ plotIndex = mw.mdlPlots.getIndexFromID(ID.text())
+ # segfaults for some reason
+ # mw.lstSubPlots.setCurrentIndex(plotIndex)
+
+ def newWorldItem(self):
+ text = self.sender().data()
+ print("new world item!", text)
+ mw = F.mainWindow()
+ mw.tabMain.setCurrentIndex(mw.TabWorld)
+ item = mw.mdlWorld.addItem(title=text)
+ mw.treeWorld.setCurrentIndex(
+ mw.mdlWorld.indexFromItem(item))
+
+
+ def appendContextMenuEntriesForWord(self, popup_menu, selectedWord):
+ # add "new " buttons at end
+ if selectedWord != None:
+ # new character
+ charAction = QAction(self.tr("&New Character"), popup_menu)
+ charAction.setIcon(F.themeIcon("characters"))
+ charAction.triggered.connect(self.newCharacter)
+ charAction.setData(selectedWord)
+ popup_menu.insertAction(None, charAction)
+
+ # new plot item
+ plotAction = QAction(self.tr("&New Plot Item"), popup_menu)
+ plotAction.setIcon(F.themeIcon("plots"))
+ plotAction.triggered.connect(self.newPlotItem)
+ plotAction.setData(selectedWord)
+ popup_menu.insertAction(None, plotAction)
+
+ # new world item
+ worldAction = QAction(self.tr("&New World Item"), popup_menu)
+ worldAction.setIcon(F.themeIcon("world"))
+ worldAction.triggered.connect(self.newWorldItem)
+ worldAction.setData(selectedWord)
+ popup_menu.insertAction(None, worldAction)
+
+ return popup_menu
+
def createStandardContextMenu(self):
popup_menu = QTextEdit.createStandardContextMenu(self)
- if not self.spellcheck:
- return popup_menu
-
- # Select the word under the cursor.
- # But only if there is no selection (otherwise it's impossible to select more text to copy/cut)
cursor = self.textCursor()
- if not cursor.hasSelection():
- cursor.select(QTextCursor.WordUnderCursor)
- self.setTextCursor(cursor)
+ selectedWord = cursor.selectedText() if cursor.hasSelection() else None
+
+ if not self.spellcheck:
+ return self.appendContextMenuEntriesForWord(popup_menu, selectedWord)
+
+ suggestions = []
+
+ # Check for any suggestions for corrections at the cursors position
+ if self._dict != None:
+ text = self.toPlainText()
+
+ suggestions = self._dict.findSuggestions(text, cursor.selectionStart(), cursor.selectionEnd())
+
+ # Select the word under the cursor if necessary.
+ # But only if there is no selection (otherwise it's impossible to select more text to copy/cut)
+ if not cursor.hasSelection() and len(suggestions) == 0:
+ old_position = cursor.position()
+
+ cursor.select(QTextCursor.WordUnderCursor)
+ self.setTextCursor(cursor)
+
+ if cursor.hasSelection():
+ selectedWord = cursor.selectedText()
+
+ # Check if the selected word is misspelled and offer spelling
+ # suggestions if it is.
+ suggestions = self._dict.findSuggestions(text, cursor.selectionStart(), cursor.selectionEnd())
+
+ if len(suggestions) == 0:
+ cursor.clearSelection()
+ cursor.setPosition(old_position, QTextCursor.MoveAnchor)
+ self.setTextCursor(cursor)
+
+ selectedWord = None
+
+ popup_menu = self.appendContextMenuEntriesForWord(popup_menu, selectedWord)
+
+ if len(suggestions) > 0 or selectedWord != None:
+ valid = len(suggestions) == 0
- # Check if the selected word is misspelled and offer spelling
- # suggestions if it is.
- if self._dict and cursor.hasSelection():
- text = str(cursor.selectedText())
- valid = not self._dict.isMisspelled(text)
- selectedWord = cursor.selectedText()
if not valid:
- spell_menu = QMenu(self.tr('Spelling Suggestions'), self)
- spell_menu.setIcon(F.themeIcon("spelling"))
- for word in self._dict.getSuggestions(text):
- action = self.SpellAction(word, spell_menu)
- action.correct.connect(self.correctWord)
- spell_menu.addAction(action)
+ # I think it should focus on one type of error at a time.
+ match = suggestions[0]
+
popup_menu.insertSeparator(popup_menu.actions()[0])
- # Adds: add to dictionary
- addAction = QAction(self.tr("&Add to dictionary"), popup_menu)
- addAction.setIcon(QIcon.fromTheme("list-add"))
- addAction.triggered.connect(self.addWordToDict)
- addAction.setData(selectedWord)
- popup_menu.insertAction(popup_menu.actions()[0], addAction)
- # Only add the spelling suggests to the menu if there are
- # suggestions.
- if len(spell_menu.actions()) != 0:
- # Adds: suggestions
- popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
- # popup_menu.insertSeparator(popup_menu.actions()[0])
+
+ if match.locqualityissuetype == 'misspelling':
+ spell_menu = QMenu(self.tr('Spelling Suggestions'), self)
+ spell_menu.setIcon(F.themeIcon("spelling"))
+
+ if (match.end > match.start and selectedWord == None):
+ # Select the actual area of the match
+ cursor = self.textCursor()
+ cursor.setPosition(match.start, QTextCursor.MoveAnchor);
+ cursor.setPosition(match.end, QTextCursor.KeepAnchor);
+ self.setTextCursor(cursor)
+
+ selectedWord = cursor.selectedText()
+
+ for word in match.replacements:
+ action = self.SpellAction(word, spell_menu)
+ action.correct.connect(self.correctWord)
+ spell_menu.addAction(action)
+
+ # Adds: add to dictionary
+ addAction = QAction(self.tr("&Add to dictionary"), popup_menu)
+ addAction.setIcon(QIcon.fromTheme("list-add"))
+ addAction.triggered.connect(self.addWordToDict)
+ addAction.setData(selectedWord)
+
+ popup_menu.insertAction(popup_menu.actions()[0], addAction)
+
+ # Only add the spelling suggests to the menu if there are
+ # suggestions.
+ if len(match.replacements) > 0:
+ # Adds: suggestions
+ popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
+ else:
+ correct_menu = None
+ correct_action = None
+
+ if (len(match.replacements) > 0 and match.end > match.start):
+ # Select the actual area of the match
+ cursor = self.textCursor()
+ cursor.setPosition(match.start, QTextCursor.MoveAnchor);
+ cursor.setPosition(match.end, QTextCursor.KeepAnchor);
+ self.setTextCursor(cursor)
+
+ if len(match.replacements) > 0:
+ correct_menu = QMenu(self.tr('&Correction Suggestions'), self)
+ correct_menu.setIcon(F.themeIcon("spelling"))
+
+ for word in match.replacements:
+ action = self.SpellAction(word, correct_menu)
+ action.correct.connect(self.correctWord)
+ correct_menu.addAction(action)
+
+ if correct_menu == None:
+ correct_action = QAction(self.tr('&Correction Suggestion'), popup_menu)
+ correct_action.setIcon(F.themeIcon("spelling"))
+ correct_action.setEnabled(False)
+
+ # Wrap the message into a fitting width
+ msg_lines = textwrap.wrap(match.msg, 48)
+
+ # Insert the lines of the message backwards
+ for i in range(0, len(msg_lines)):
+ popup_menu.insertSection(popup_menu.actions()[0], msg_lines[len(msg_lines) - (i + 1)])
+
+ if correct_menu != None:
+ popup_menu.insertMenu(popup_menu.actions()[0], correct_menu)
+ else:
+ popup_menu.insertAction(popup_menu.actions()[0], correct_action)
# If word was added to custom dict, give the possibility to remove it
- elif valid and self._dict.isCustomWord(selectedWord):
+ elif self._dict.isCustomWord(selectedWord):
popup_menu.insertSeparator(popup_menu.actions()[0])
# Adds: remove from dictionary
- rmAction = QAction(self.tr("&Remove from custom dictionary"), popup_menu)
+ rmAction = QAction(
+ self.tr("&Remove from custom dictionary"), popup_menu)
rmAction.setIcon(QIcon.fromTheme("list-remove"))
rmAction.triggered.connect(self.rmWordFromDict)
rmAction.setData(selectedWord)
diff --git a/manuskript/ui/views/treeDelegates.py b/manuskript/ui/views/treeDelegates.py
index fa59702c..040b4f58 100644
--- a/manuskript/ui/views/treeDelegates.py
+++ b/manuskript/ui/views/treeDelegates.py
@@ -34,8 +34,8 @@ class treeTitleDelegate(QStyledItemDelegate):
opt = QStyleOptionViewItem(option)
self.initStyleOption(opt, index)
- iconRect = style.subElementRect(style.SE_ItemViewItemDecoration, opt)
- textRect = style.subElementRect(style.SE_ItemViewItemText, opt)
+ iconRect = style.subElementRect(style.SE_ItemViewItemDecoration, opt, None)
+ textRect = style.subElementRect(style.SE_ItemViewItemText, opt, None)
# Background
style.drawPrimitive(style.PE_PanelItemViewItem, opt, painter)
@@ -111,6 +111,9 @@ class treeTitleDelegate(QStyledItemDelegate):
elif settings.viewSettings["Tree"]["InfoFolder"] == "WC":
extraText = item.wordCount()
extraText = " ({})".format(extraText)
+ elif settings.viewSettings["Tree"]["InfoFolder"] == "CC":
+ extraText = item.charCount()
+ extraText = " ({})".format(extraText)
elif settings.viewSettings["Tree"]["InfoFolder"] == "Progress":
extraText = int(toFloat(item.data(Outline.goalPercentage)) * 100)
if extraText:
@@ -124,6 +127,9 @@ class treeTitleDelegate(QStyledItemDelegate):
if settings.viewSettings["Tree"]["InfoText"] == "WC":
extraText = item.wordCount()
extraText = " ({})".format(extraText)
+ elif settings.viewSettings["Tree"]["InfoText"] == "CC":
+ extraText = item.charCount()
+ extraText = " ({})".format(extraText)
elif settings.viewSettings["Tree"]["InfoText"] == "Progress":
extraText = int(toFloat(item.data(Outline.goalPercentage)) * 100)
if extraText:
diff --git a/manuskript/ui/views/treeView.py b/manuskript/ui/views/treeView.py
index 3fa7271d..2655808c 100644
--- a/manuskript/ui/views/treeView.py
+++ b/manuskript/ui/views/treeView.py
@@ -69,7 +69,7 @@ class treeView(QTreeView, dndView, outlineBasics):
return menu
def expandCurrentIndex(self, index=None):
- if index is None or type(index) == bool:
+ if index == None or type(index) == bool:
index = self._indexesToOpen[0] # self.currentIndex()
self.expand(index)
@@ -78,7 +78,7 @@ class treeView(QTreeView, dndView, outlineBasics):
self.expandCurrentIndex(index=idx)
def collapseCurrentIndex(self, index=None):
- if index is None or type(index) == bool:
+ if index == None or type(index) == bool:
index = self._indexesToOpen[0] # self.currentIndex()
self.collapse(index)
diff --git a/manuskript/ui/welcome.py b/manuskript/ui/welcome.py
index 8055c3a8..ba2ef53b 100644
--- a/manuskript/ui/welcome.py
+++ b/manuskript/ui/welcome.py
@@ -371,7 +371,7 @@ class welcome(QWidget, Ui_welcome):
Qt.FindChildrenRecursively):
# Update self.template to reflect the changed name values
templateIndex = t.property("templateIndex")
- if templateIndex is not None :
+ if templateIndex != None :
self.template[1][templateIndex] = (
self.template[1][templateIndex][0],
t.text())