diff --git a/src/mainWindow.py b/src/mainWindow.py
index c1482cd2..3cf98dae 100644
--- a/src/mainWindow.py
+++ b/src/mainWindow.py
@@ -15,7 +15,16 @@ from models.outlineModel import *
from models.persosProxyModel import *
from functions import *
+# Spell checker support
+try:
+ import enchant
+except ImportError:
+ enchant = None
+
class MainWindow(QMainWindow, Ui_MainWindow):
+
+ dictChanged = pyqtSignal(unicode)
+
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
@@ -186,7 +195,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.mprOutline = QDataWidgetMapper()
self.mprOutline.setModel(self.mdlOutline)
mapping = [
- (self.redacEditor.txtRedacText, Outline.text.value),
(self.txtRedacSummarySentance, Outline.summarySentance.value),
(self.txtRedacSummaryFull, Outline.summaryFull.value),
(self.txtRedacNotes, Outline.notes.value),
@@ -202,6 +210,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.treeRedacOutline.selectionModel().currentChanged.connect(self.cmbRedacStatus.setCurrentModelIndex)
self.treeRedacOutline.selectionModel().currentChanged.connect(self.chkRedacCompile.setCurrentModelIndex)
self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.setCurrentModelIndex)
+ self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.txtRedacText.setCurrentModelIndex)
+
self.tabMain.currentChanged.connect(self.mprOutline.submit)
self.treeRedacOutline.selectionModel().currentChanged.connect(self.outlineSelectionChanged)
@@ -425,7 +435,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.splitterRedac.setStretchFactor(2, 20)
# Help box
-
references = [
(self.lytTabOverview,
"Entrez toutes les informations relatives au livre, ainsi qu'à vous."),
@@ -448,4 +457,40 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.actShowHelp.toggled.connect(label.setVisible)
widget.layout().insertWidget(0, label)
- self.actShowHelp.setChecked(False)
\ No newline at end of file
+ self.actShowHelp.setChecked(False)
+
+ # Spellcheck
+ if enchant:
+ self.menuDict = QMenu("Dictionary")
+ self.menuDictGroup = QActionGroup(self)
+
+ for i in enchant.list_dicts():
+ a = QAction(unicode(i[0]), self)
+ a.setCheckable(True)
+ a.triggered.connect(self.setDictionary)
+ if unicode(i[0]) == enchant.get_default_language(): # "fr_CH"
+ a.setChecked(True)
+ self.menuDictGroup.addAction(a)
+ self.menuDict.addAction(a)
+
+ self.menuTools.addMenu(self.menuDict)
+
+ self.actSpellcheck.toggled.connect(self.redacEditor.toggleSpellcheck)
+ self.dictChanged.connect(self.redacEditor.setDict)
+
+
+ else:
+ # No Spell check support
+ self.actSpellcheck.setVisible(False)
+ a = QAction("Install PyEnchant to use spellcheck", self)
+ a.setIcon(self.style().standardIcon(QStyle.SP_MessageBoxWarning))
+ a.triggered.connect(self.openPyEnchantWebPage)
+ self.menuTools.addAction(a)
+
+ def setDictionary(self):
+ for i in self.menuDictGroup.actions():
+ if i.isChecked():
+ self.dictChanged.emit(i.text().replace("&", ""))
+
+ def openPyEnchantWebPage(self):
+ QDesktopServices.openUrl(QUrl("http://pythonhosted.org/pyenchant/"))
\ No newline at end of file
diff --git a/src/models/outlineModel.py b/src/models/outlineModel.py
index 5195d3bf..f198e275 100644
--- a/src/models/outlineModel.py
+++ b/src/models/outlineModel.py
@@ -411,10 +411,6 @@ class outlineItem():
if column == Outline.text.value and self.isFolder():
# Folder have no text
return
-
- if column == Outline.text.value:
- wc = wordCount(data)
- self.setData(Outline.wordCount.value, wc)
if column == Outline.goal.value:
self._data[Outline.setGoal] = toInt(data) if toInt(data) > 0 else ""
@@ -425,6 +421,10 @@ class outlineItem():
self._data[Outline(column)] = data
+ if column == Outline.text.value:
+ wc = wordCount(data)
+ self.setData(Outline.wordCount.value, wc)
+
if updateWordCount:
self.updateWordCount()
diff --git a/src/ui/editors/customTextEdit.py b/src/ui/editors/customTextEdit.py
index 13b529ee..550f8698 100644
--- a/src/ui/editors/customTextEdit.py
+++ b/src/ui/editors/customTextEdit.py
@@ -14,18 +14,141 @@ except ImportError:
class customTextEdit(QTextEdit):
- def __init__(self, parent=None):
+ def __init__(self, parent=None, index=None, html=None, spellcheck=True, dict=""):
QTextEdit.__init__(self, parent)
+ self.document().contentsChanged.connect(self.sizeChange)
- self.defaultFontPointSize = 9
- self.highlightWord = ""
- self.highligtCS = False
-
- self.highlighter = t2tHighlighter(self)
+ self.currentIndex = None
- # Spellchecking
- if enchant:
- self.dict = enchant.Dict("fr_CH")
- self.spellcheck = True
- else:
- self.spellcheck = False
\ No newline at end of file
+ self.heightMin = 0
+ self.heightMax = 65000
+ self.sizeChange()
+ self.item = None
+ self.spellcheck = spellcheck
+ self.currentDict = dict
+
+ if index:
+ self.setCurrentModelIndex(index)
+
+ elif html:
+ self.document().setHtml(html)
+ self.setReadOnly(True)
+
+ def setCurrentModelIndex(self, index):
+ if index.isValid():
+ self.currentIndex = index
+ self.item = index.internalPointer()
+ self._model = index.model()
+ self.document().contentsChanged.connect(self.submit)
+ self._model.dataChanged.connect(self.update)
+ self.updateText()
+
+ self.defaultFontPointSize = qApp.font().pointSize()
+ self.highlightWord = ""
+ self.highligtCS = False
+
+ self.highlighter = t2tHighlighter(self)
+
+ # Spellchecking
+ if enchant and self.spellcheck:
+ self.dict = enchant.Dict(self.currentDict if self.currentDict else enchant.get_default_language())
+
+ def submit(self):
+ if self.toPlainText() <> self.item.data(Outline.text.value):
+ #self._model.setData(self.item.index(), self.toPlainText(), Outline.text.value)
+ self.item.setData(Outline.text.value, self.toPlainText())
+
+ def update(self, topLeft, bottomRight):
+ if topLeft.row() <= self.currentIndex.row() <= bottomRight.row():
+ self.updateText()
+
+ def updateText(self):
+ if self.item:
+ if self.toPlainText() <> self.item.data(Outline.text.value):
+ self.document().setPlainText(self.item.data(Outline.text.value))
+
+ def resizeEvent(self, e):
+ QTextEdit.resizeEvent(self, e)
+ self.sizeChange()
+
+ def sizeChange(self):
+ docHeight = self.document().size().height()
+ if self.heightMin <= docHeight <= self.heightMax:
+ self.setMinimumHeight(docHeight)
+
+
+ # -----------------------------------------------------------------------------------------------------
+ # Spellchecking based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
+
+ def setDict(self, d):
+ self.dict = enchant.Dict(d)
+ self.highlighter.rehighlight()
+
+ def toggleSpellcheck(self, v):
+ self.spellcheck = v
+ self.highlighter.rehighlight()
+
+ def mousePressEvent(self, event):
+ if event.button() == Qt.RightButton:
+ # Rewrite the mouse event to a left button event so the cursor is
+ # moved to the location of the pointer.
+ event = QMouseEvent(QEvent.MouseButtonPress, event.pos(),
+ Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
+ QTextEdit.mousePressEvent(self, event)
+
+ class SpellAction(QAction):
+ "A special QAction that returns the text in a signal. Used for spellckech."
+
+ correct = pyqtSignal(unicode)
+
+ def __init__(self, *args):
+ QAction.__init__(self, *args)
+
+ self.triggered.connect(lambda x: self.correct.emit(
+ unicode(self.text())))
+
+ def contextMenuEvent(self, event):
+ # Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
+
+ if not self.spellcheck:
+ QTextEdit.contextMenuEvent(self, event)
+ return
+
+ popup_menu = self.createStandardContextMenu()
+
+ # Select the word under the cursor.
+ cursor = self.textCursor()
+ cursor.select(QTextCursor.WordUnderCursor)
+ self.setTextCursor(cursor)
+
+ # Check if the selected word is misspelled and offer spelling
+ # suggestions if it is.
+ if self.textCursor().hasSelection():
+ text = unicode(self.textCursor().selectedText())
+ if not self.dict.check(text):
+ spell_menu = QMenu('Spelling Suggestions')
+ for word in self.dict.suggest(text):
+ action = self.SpellAction(word, spell_menu)
+ action.correct.connect(self.correctWord)
+ spell_menu.addAction(action)
+ # Only add the spelling suggests to the menu if there are
+ # suggestions.
+ if len(spell_menu.actions()) != 0:
+ popup_menu.insertSeparator(popup_menu.actions()[0])
+ popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
+
+ popup_menu.exec_(event.globalPos())
+
+ def correctWord(self, word):
+ '''
+ Replaces the selected text with word.
+ '''
+ cursor = self.textCursor()
+ cursor.beginEditBlock()
+
+ cursor.removeSelectedText()
+ cursor.insertText(word)
+
+ cursor.endEditBlock()
+
+ # -----------------------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/src/ui/editors/editorWidget.py b/src/ui/editors/editorWidget.py
index 55defd02..fd6574ca 100644
--- a/src/ui/editors/editorWidget.py
+++ b/src/ui/editors/editorWidget.py
@@ -7,61 +7,24 @@ from __future__ import unicode_literals
from qt import *
from enums import *
from ui.editors.editorWidget_ui import *
-
-class GrowingTextEdit(QTextEdit):
-
- def __init__(self, index=None, html=None, parent=None):
- QTextEdit.__init__(self, parent)
- self.document().contentsChanged.connect(self.sizeChange)
-
- self.heightMin = 0
- self.heightMax = 65000
- self.sizeChange()
- self.item = None
-
- if index:
- self.currentIndex = index
- self.item = index.internalPointer()
- self._model = index.model()
-
- self._model.dataChanged.connect(self.update)
- self.document().contentsChanged.connect(self.submit)
-
- else:
- self.document().setHtml(html)
- self.setReadOnly(True)
-
- self.updateText()
-
- def submit(self):
- self.item.setData(Outline.text.value, self.toPlainText())
-
- def update(self, topLeft, bottomRight):
- if topLeft.row() <= self.currentIndex.row() <= bottomRight.row():
- self.updateText()
-
- def updateText(self):
- if self.item:
- self.document().setPlainText(self.item.data(Outline.text.value))
-
- def resizeEvent(self, e):
- QTextEdit.resizeEvent(self, e)
- self.sizeChange()
-
- def sizeChange(self):
- docHeight = self.document().size().height()
- if self.heightMin <= docHeight <= self.heightMax:
- self.setMinimumHeight(docHeight)
+from ui.editors.customTextEdit import *
class editorWidget(QWidget, Ui_editorWidget_ui):
+ toggledSpellcheck = pyqtSignal(bool)
+ dictChanged = pyqtSignal(str)
+
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.currentIndex = None
self.txtEdits = []
self.scroll.setBackgroundRole(QPalette.Base)
+ self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck)
+ self.dictChanged.connect(self.txtRedacText.setDict)
+ self.currentDict = ""
+ self.spellcheck = True
def setCurrentModelIndex(self, index):
@@ -82,7 +45,7 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
self.txtEdits = []
def addTitle(itm):
- edt = GrowingTextEdit(html="{t}".format(l=min(itm.level()+1, 5), t=itm.title()))
+ edt = customTextEdit(self, html="{t}".format(l=min(itm.level()+1, 5), t=itm.title()))
edt.setFrameShape(QFrame.NoFrame)
self.txtEdits.append(edt)
l.addWidget(edt)
@@ -94,9 +57,11 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
l.addWidget(line)
def addScene(itm):
- edt = GrowingTextEdit(index=itm.index())
+ edt = customTextEdit(self, index=itm.index(), spellcheck=self.spellcheck, dict=self.currentDict)
edt.setFrameShape(QFrame.NoFrame)
edt.setStatusTip(itm.path())
+ self.toggledSpellcheck.connect(edt.toggleSpellcheck)
+ self.dictChanged.connect(edt.setDict)
#edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
self.txtEdits.append(edt)
l.addWidget(edt)
@@ -125,4 +90,11 @@ class editorWidget(QWidget, Ui_editorWidget_ui):
else:
self.currentIndex = None
-
\ No newline at end of file
+
+ def toggleSpellcheck(self, v):
+ self.spellcheck = v
+ self.toggledSpellcheck.emit(v)
+
+ def setDict(self, dct):
+ self.currentDict = dct
+ self.dictChanged.emit(dct)
\ No newline at end of file
diff --git a/src/ui/editors/t2tHighlighter.py b/src/ui/editors/t2tHighlighter.py
index 50471677..113740e9 100644
--- a/src/ui/editors/t2tHighlighter.py
+++ b/src/ui/editors/t2tHighlighter.py
@@ -343,13 +343,14 @@ class t2tHighlighter (QSyntaxHighlighter):
data = blockUserData.getUserData(block)
# Header Lines
- 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
+ # 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
diff --git a/src/ui/editors/t2tHighlighterStyle.py b/src/ui/editors/t2tHighlighterStyle.py
index 3b3c4eab..df6e334f 100644
--- a/src/ui/editors/t2tHighlighterStyle.py
+++ b/src/ui/editors/t2tHighlighterStyle.py
@@ -21,11 +21,11 @@ class t2tHighlighterStyle ():
# Defaults
self.defaultFontPointSize = self.editor.defaultFontPointSize
- self.defaultFontFamily = ""
+ self.defaultFontFamily = qApp.font().family()
self.tabStopWidth = 40
self.setupEditor()
-
+
if self.name == "Default":
self.initDefaults()
#Temporary other theme
@@ -126,7 +126,7 @@ class t2tHighlighterStyle ():
blockFormat.setBackground(QColor("#EEEEFA"))
n = blockUserData.getUserData(block).leadingSpaces() + 1
f = QFontMetrics(QFont(self.defaultFontFamily,
- self.defaultFontPointSize))
+ self.defaultFontPointSize))
fm = f.width(" " * n +
blockUserData.getUserData(block).listSymbol())
blockFormat.setTextIndent(-fm)
@@ -170,7 +170,7 @@ class t2tHighlighterStyle ():
if preset in [State.HEADER_LINE]:
size = size * 2
- print size
+ #print size
if preset in [State.RAW_AREA, State.RAW_LINE, "raw"]:
color = "blue"
diff --git a/src/ui/mainWindow.py b/src/ui/mainWindow.py
index 34460344..054f6be4 100644
--- a/src/ui/mainWindow.py
+++ b/src/ui/mainWindow.py
@@ -1051,6 +1051,8 @@ class Ui_MainWindow(object):
self.menuMode.setObjectName("menuMode")
self.menu_Aide = QtWidgets.QMenu(self.menubar)
self.menu_Aide.setObjectName("menu_Aide")
+ self.menuTools = QtWidgets.QMenu(self.menubar)
+ self.menuTools.setObjectName("menuTools")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
@@ -1089,6 +1091,14 @@ class Ui_MainWindow(object):
icon = QtGui.QIcon.fromTheme("system-help")
self.actShowHelp.setIcon(icon)
self.actShowHelp.setObjectName("actShowHelp")
+ self.actSpellcheck = QtWidgets.QAction(MainWindow)
+ self.actSpellcheck.setCheckable(True)
+ self.actSpellcheck.setChecked(True)
+ icon = QtGui.QIcon.fromTheme("tools-check-spelling")
+ self.actSpellcheck.setIcon(icon)
+ self.actSpellcheck.setObjectName("actSpellcheck")
+ self.actSpellcheckDict = QtWidgets.QAction(MainWindow)
+ self.actSpellcheckDict.setObjectName("actSpellcheckDict")
self.menu_Fichier.addAction(self.actionNouveau)
self.menu_Fichier.addAction(self.actionOuvrir)
self.menu_Fichier.addAction(self.action_R_cents)
@@ -1098,9 +1108,11 @@ class Ui_MainWindow(object):
self.menu_Fichier.addAction(self.actionQuitter)
self.menuMode.addAction(self.actionSnowflakeMode)
self.menu_Aide.addAction(self.actShowHelp)
+ self.menuTools.addAction(self.actSpellcheck)
self.menubar.addAction(self.menu_Fichier.menuAction())
self.menubar.addAction(self.menuMode.menuAction())
self.menubar.addAction(self.menu_Aide.menuAction())
+ self.menubar.addAction(self.menuTools.menuAction())
self.retranslateUi(MainWindow)
self.tabMain.setCurrentIndex(6)
@@ -1257,6 +1269,7 @@ class Ui_MainWindow(object):
self.menu_Fichier.setTitle(_translate("MainWindow", "&Fichier"))
self.menuMode.setTitle(_translate("MainWindow", "Mo&de"))
self.menu_Aide.setTitle(_translate("MainWindow", "&Aide"))
+ self.menuTools.setTitle(_translate("MainWindow", "&Outlis"))
self.actionOuvrir.setText(_translate("MainWindow", "&Ouvrir"))
self.actionOuvrir.setShortcut(_translate("MainWindow", "Ctrl+O"))
self.action_R_cents.setText(_translate("MainWindow", "&Récents"))
@@ -1272,10 +1285,13 @@ class Ui_MainWindow(object):
self.actionNouveau.setShortcut(_translate("MainWindow", "Ctrl+N"))
self.actShowHelp.setText(_translate("MainWindow", "Afficher les &bulles d\'aide"))
self.actShowHelp.setShortcut(_translate("MainWindow", "Ctrl+Shift+B"))
+ self.actSpellcheck.setText(_translate("MainWindow", "Correcteur ortographique"))
+ self.actSpellcheck.setShortcut(_translate("MainWindow", "F8"))
+ self.actSpellcheckDict.setText(_translate("MainWindow", "Dictionnaire"))
from ui.cmbOutlineStatusChoser import cmbOutlineStatusChoser
-from ui.cmbOutlinePersoChoser import cmbOutlinePersoChoser
-from ui.collapsibleGroupBox2 import collapsibleGroupBox2
-from ui.chkOutlineCompile import chkOutlineCompile
from ui.sldImportance import sldImportance
from ui.editors.editorWidget import editorWidget
+from ui.cmbOutlinePersoChoser import cmbOutlinePersoChoser
+from ui.chkOutlineCompile import chkOutlineCompile
+from ui.collapsibleGroupBox2 import collapsibleGroupBox2
diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui
index b328e988..de7424fe 100644
--- a/src/ui/mainWindow.ui
+++ b/src/ui/mainWindow.ui
@@ -2046,9 +2046,16 @@
+
+
@@ -2159,6 +2166,28 @@
Ctrl+Shift+B
+
+
+ true
+
+
+ true
+
+
+
+
+
+ Correcteur ortographique
+
+
+ F8
+
+
+
+
+ Dictionnaire
+
+
diff --git a/test_project/outline.xml b/test_project/outline.xml
index fb53a2da..c8883260 100644
--- a/test_project/outline.xml
+++ b/test_project/outline.xml
@@ -1,25 +1,25 @@
-
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
+