mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-05-17 11:22:28 +12:00
Merge branch 'develop' into optional-pov
This commit is contained in:
commit
e8c61e74ba
|
@ -2,7 +2,7 @@ language: generic
|
|||
os:
|
||||
- osx
|
||||
- linux
|
||||
osx_image: xcode10.1
|
||||
osx_image: xcode11
|
||||
sudo: required
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then package/prepare_osx.sh; fi
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/__init__.py" line="15"/>
|
||||
<source>Default exporter, provides basic formats used by other exporters.</source>
|
||||
<translation>Exporteur de base, fournit les formats de base utilisés par les autres exporteurs.</translation>
|
||||
<translation>Exportateur de base, fournit les formats de base utilisés par les autres exportateurs.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/HTML.py" line="18"/>
|
||||
|
@ -28,7 +28,7 @@
|
|||
formats.</p>
|
||||
<p>Website: <a href="http://www.pandoc.org">http://pandoc.org/</a></p>
|
||||
</source>
|
||||
<translation><p>Un convertisseur universel de document. Peut être utilisé pour convertir du Markdown dans un grand nombre de formats.</p>
|
||||
<translation><p>Un convertisseur universel de documents. Peut être utilisé pour convertir du Markdown dans un grand nombre de formats.</p>
|
||||
<p>Site internet : <a href="http://www.pandoc.org">http://pandoc.org/</a></p>
|
||||
</translation>
|
||||
</message>
|
||||
|
@ -36,7 +36,7 @@
|
|||
<location filename="../manuskript/exporter/manuskript/markdown.py" line="14"/>
|
||||
<source>Just like plain text, excepts adds markdown titles.
|
||||
Presupposes that texts are formatted in markdown.</source>
|
||||
<translation>Comme en texte brute, mais rajoute les titres markdown.</translation>
|
||||
<translation>Comme en texte brut, mais ajoute les titres markdown.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/markdown.py" line="60"/>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/plainText.py" line="14"/>
|
||||
<source>Plain text</source>
|
||||
<translation>Texte brute</translation>
|
||||
<translation>Texte brut</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/plainText.py" line="15"/>
|
||||
|
@ -99,7 +99,7 @@ Par exemple <a href='www.fountain.io'>Fountain</a>.</trans
|
|||
<location filename="../manuskript/exporter/pandoc/plainText.py" line="10"/>
|
||||
<source>Export to markdown, using pandoc. Allows more formatting options
|
||||
than the basic manuskript exporter.</source>
|
||||
<translation>Export vers markdown en utilisant pandoc. Permet plus de possibilités que l'exporteur basique intégré à manuskript.</translation>
|
||||
<translation>Export vers markdown en utilisant pandoc. Permet plus de possibilités que l'exportateur basique intégré à manuskript.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/plainText.py" line="22"/>
|
||||
|
@ -110,7 +110,7 @@ Par exemple <a href='www.fountain.io'>Fountain</a>.</trans
|
|||
<location filename="../manuskript/exporter/pandoc/plainText.py" line="33"/>
|
||||
<source>LaTeX is a word processor and document markup language used to create
|
||||
beautiful documents.</source>
|
||||
<translation>LaTeX est une suite d'outil et un format utilisé pour créer des documents magnifiques.</translation>
|
||||
<translation>LaTeX est une suite d'outils et un format utilisé pour créer des documents magnifiques.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/abstractPlainText.py" line="97"/>
|
||||
|
@ -125,7 +125,7 @@ Par exemple <a href='www.fountain.io'>Fountain</a>.</trans
|
|||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/abstractPlainText.py" line="103"/>
|
||||
<source>Number of sections level to include in TOC: </source>
|
||||
<translation>Nombre de niveau à inclure dans la table des matières: </translation>
|
||||
<translation>Nombre de niveaux à inclure dans la table des matières : </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/abstractPlainText.py" line="107"/>
|
||||
|
@ -140,7 +140,7 @@ Par exemple <a href='www.fountain.io'>Fountain</a>.</trans
|
|||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/abstractPlainText.py" line="112"/>
|
||||
<source>Specify the base level for headers: </source>
|
||||
<translation>Spécifier le niveau de base pour les titres: </translation>
|
||||
<translation>Spécifier le niveau de base pour les titres : </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/abstractPlainText.py" line="119"/>
|
||||
|
@ -191,7 +191,7 @@ Par exemple <a href='www.fountain.io'>Fountain</a>.</trans
|
|||
<location filename="../manuskript/exporter/pandoc/PDF.py" line="19"/>
|
||||
<source>a valid LaTeX installation. Pandoc recommendations can be found on:
|
||||
<a href="https://pandoc.org/installing.html">pandoc.org/installing.html</a>. If you want Unicode support, you need XeLaTeX.</source>
|
||||
<translation type="unfinished">nécessite une installation latex valide. Voir les recommendations de pandoc sur <a href="http://pandoc.org/installing.html">http://pandoc.org/installing.html</a>. Pour le support unicode, il vous faut xelatex.</translation>
|
||||
<translation type="unfinished">nécessite une installation LaTeX valide. Voir les recommandations de pandoc sur <a href="http://pandoc.org/installing.html">http://pandoc.org/installing.html</a>. Pour le support unicode, il vous faut XeLaTeX.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/exporter/pandoc/plainText.py" line="45"/>
|
||||
|
@ -222,7 +222,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/exporter/manuskript/plainText.py" line="70"/>
|
||||
<source>Choose output file…</source>
|
||||
<translation type="unfinished">Choisir le fichier de sortie...</translation>
|
||||
<translation type="unfinished">Choisir le fichier de sortie…</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -230,7 +230,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="14"/>
|
||||
<source>Manage Exporters</source>
|
||||
<translation>Gérer les Exporteurs</translation>
|
||||
<translation>Gérer les Exportateurs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="21"/>
|
||||
|
@ -250,27 +250,27 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="184"/>
|
||||
<source>Status</source>
|
||||
<translation>Status</translation>
|
||||
<translation>Statut</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="190"/>
|
||||
<source>Status:</source>
|
||||
<translation>Status :</translation>
|
||||
<translation>Statut :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="210"/>
|
||||
<source>Version:</source>
|
||||
<translation>Version:</translation>
|
||||
<translation>Version :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="233"/>
|
||||
<source>Path:</source>
|
||||
<translation>Chemin:</translation>
|
||||
<translation>Chemin :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="258"/>
|
||||
<source>...</source>
|
||||
<translation>...</translation>
|
||||
<translation>…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/exporters/exportersManager_ui.ui" line="273"/>
|
||||
|
@ -298,7 +298,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/tools/frequency_ui.ui" line="49"/>
|
||||
<source>Minimum size:</source>
|
||||
<translation>Taille minimum:</translation>
|
||||
<translation>Taille minimum :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/tools/frequency_ui.ui" line="63"/>
|
||||
|
@ -318,7 +318,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/tools/frequency_ui.ui" line="115"/>
|
||||
<source>Number of words: from</source>
|
||||
<translation>Nombre de mots: de</translation>
|
||||
<translation>Nombre de mots : de</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/tools/frequency_ui.ui" line="129"/>
|
||||
|
@ -355,7 +355,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
are added as scene.</p>
|
||||
<p>Only text files are supported (not images, binary or others).</p></source>
|
||||
<translation><p><b>Info:</b> Importe la structure d'un dossier. Les dossiers sont crées comme dossiers, et les documents textes sont ajoutés comme des scènes.</p>
|
||||
<p>Seulement les fichiers textes sont supportés (pas les images, fichiers binaires ou autres).</p></translation>
|
||||
<p>Seuls les fichiers textes sont pris en charge (pas les images, fichiers binaires ou autres).</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/folderImporter.py" line="108"/>
|
||||
|
@ -375,7 +375,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/importer/folderImporter.py" line="117"/>
|
||||
<source>Import folder then files</source>
|
||||
<translation>Importer les dossiers en premier</translation>
|
||||
<translation>Importer les dossiers puis les fichiers/translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/opmlImporter.py" line="65"/>
|
||||
|
@ -385,7 +385,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/importer/opmlImporter.py" line="37"/>
|
||||
<source>File open failed.</source>
|
||||
<translation>Echec de l'ouverture du fichier</translation>
|
||||
<translation>Échec de l'ouverture du fichier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/opmlImporter.py" line="65"/>
|
||||
|
@ -410,12 +410,12 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/importer/pandocImporters.py" line="69"/>
|
||||
<source>Import using:</source>
|
||||
<translation>Importer via:</translation>
|
||||
<translation>Importer via :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/pandocImporters.py" line="73"/>
|
||||
<source>Wrap lines:</source>
|
||||
<translation>Replier les lignes:</translation>
|
||||
<translation>Replier les lignes :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/pandocImporters.py" line="73"/>
|
||||
|
@ -425,8 +425,8 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<b>none</b>: no line wrap.<br>
|
||||
<b>preserve</b>: tries to preserves line wrap from the
|
||||
original document.</p></source>
|
||||
<translation><p>Pandoc doit-il créer des retours à la lignes cosmétiques/non-sémantiques?</p>
|
||||
<p><b>auto</b>: plier les lignes à 72 charactères.<br>
|
||||
<translation><p>Pandoc doit-il créer des retours à la ligne cosmétiques/non-sémantiques?</p>
|
||||
<p><b>auto</b>: retour à la ligne après 72 caractères.<br>
|
||||
<b>none</b>: pas de retours à la lignes.<br>
|
||||
<b>preserve</b>: essaie de préserver les retours à la lignes du document original.</p></translation>
|
||||
</message>
|
||||
|
@ -448,7 +448,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/importer/mindMapImporter.py" line="74"/>
|
||||
<source>Import tip as:</source>
|
||||
<translation>Importer les pointes comme:</translation>
|
||||
<translation>Importer les astuces comme :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/importer/mindMapImporter.py" line="90"/>
|
||||
|
@ -494,7 +494,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="236"/>
|
||||
<source>License</source>
|
||||
<translation>License</translation>
|
||||
<translation>Licence</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="249"/>
|
||||
|
@ -729,17 +729,17 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="322"/>
|
||||
<source>Situation:</source>
|
||||
<translation>Situation:</translation>
|
||||
<translation>Situation :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="1337"/>
|
||||
<source>Summary:</source>
|
||||
<translation>Résumé:</translation>
|
||||
<translation>Résumé :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="676"/>
|
||||
<source>What if...?</source>
|
||||
<translation>Et si... ?</translation>
|
||||
<translation>Et si… ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1476"/>
|
||||
|
@ -839,7 +839,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1215"/>
|
||||
<source>Project tree</source>
|
||||
<translation>Arborescence</translation>
|
||||
<translation>Arborescence du projet</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1216"/>
|
||||
|
@ -854,7 +854,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1295"/>
|
||||
<source>Create your characters.</source>
|
||||
<translation>Créez ici vos personnage.</translation>
|
||||
<translation>Créez ici vos personnages.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1298"/>
|
||||
|
@ -874,7 +874,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1310"/>
|
||||
<source>Debug info. Sometimes useful.</source>
|
||||
<translation>Des informations pour débugger des fois pendant qu'on code c'est utile.</translation>
|
||||
<translation>Des informations pour débugger pendant qu'on code c'est parfois utile.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1324"/>
|
||||
|
@ -889,7 +889,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1468"/>
|
||||
<source>POV</source>
|
||||
<translation>POV</translation>
|
||||
<translation>Pt de vue</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1469"/>
|
||||
|
@ -919,7 +919,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1487"/>
|
||||
<source>Icon</source>
|
||||
<translation>Icone</translation>
|
||||
<translation>Icône</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1488"/>
|
||||
|
@ -1004,7 +1004,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2389"/>
|
||||
<source>&Show help texts</source>
|
||||
<translation>&Afficher les bulles d'aides</translation>
|
||||
<translation>&Afficher les bulles d'aide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2407"/>
|
||||
|
@ -1019,7 +1019,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2428"/>
|
||||
<source>&Status...</source>
|
||||
<translation>&Status…</translation>
|
||||
<translation>&Statut…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2444"/>
|
||||
|
@ -1054,7 +1054,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1217"/>
|
||||
<source>Story line</source>
|
||||
<translation></translation>
|
||||
<translation><Fil narratif/translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1285"/>
|
||||
|
@ -1081,7 +1081,7 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2509"/>
|
||||
<source>&About</source>
|
||||
<translation>&A propos</translation>
|
||||
<translation>&À propos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="2512"/>
|
||||
|
@ -1096,12 +1096,12 @@ Cochez ceci si vous avez des erreurs liées à YAML.</translation>
|
|||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="843"/>
|
||||
<source>WARNING: Project {} not saved.</source>
|
||||
<translation>ATTENTION: Le projet {} n'a pas été enregistré.</translation>
|
||||
<translation>ATTENTION : Le projet {} n'a pas été enregistré.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/mainWindow.py" line="1301"/>
|
||||
<source>Build worlds. Create hierarchy of broad categories down to specific details.</source>
|
||||
<translation>Construire des mondes. Crée une hierarchie en partant des catégories les plus larges jusqu'au détails les plus spécifiques.</translation>
|
||||
<translation>Construire des mondes. Crée une hiérarchie en partant des catégories les plus larges jusqu'aux détails les plus spécifiques.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../manuskript/ui/mainWindow.ui" line="1351"/>
|
||||
|
|
|
@ -61,6 +61,7 @@ class Outline(IntEnum):
|
|||
textFormat = 15
|
||||
revisions = 16
|
||||
customIcon = 17
|
||||
charCount = 18
|
||||
|
||||
class Abstract(IntEnum):
|
||||
title = 0
|
||||
|
|
|
@ -23,6 +23,14 @@ def wordCount(text):
|
|||
t = [l for l in t if l]
|
||||
return len(t)
|
||||
|
||||
def charCount(text, use_spaces = True):
|
||||
t = text.strip()
|
||||
|
||||
if not use_spaces:
|
||||
t = t.replace(" ", "")
|
||||
|
||||
return len(t)
|
||||
|
||||
validate_ok = lambda *args, **kwargs: True
|
||||
def uiParse(input, default, converter, validator=validate_ok):
|
||||
"""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# --!-- coding: utf8 --!--
|
||||
|
||||
import os, gzip, json, glob
|
||||
import os, gzip, json, glob, re
|
||||
from PyQt5.QtCore import QLocale
|
||||
from collections import OrderedDict
|
||||
from manuskript.functions import writablePath
|
||||
|
@ -28,6 +28,11 @@ except ImportError:
|
|||
symspellpy = None
|
||||
|
||||
|
||||
try:
|
||||
import language_check as languagetool
|
||||
except:
|
||||
languagetool = None
|
||||
|
||||
class Spellchecker:
|
||||
dictionaries = {}
|
||||
# In order of priority
|
||||
|
@ -117,6 +122,17 @@ class Spellchecker:
|
|||
pass
|
||||
return None
|
||||
|
||||
class BasicMatch:
|
||||
def __init__(self, startIndex, endIndex):
|
||||
self.start = startIndex
|
||||
self.end = endIndex
|
||||
self.locqualityissuetype = 'misspelling'
|
||||
self.replacements = []
|
||||
self.msg = ''
|
||||
|
||||
def getWord(self, text):
|
||||
return text[self.start:self.end]
|
||||
|
||||
class BasicDictionary:
|
||||
def __init__(self, name):
|
||||
self._lang = name
|
||||
|
@ -162,12 +178,45 @@ class BasicDictionary:
|
|||
def availableDictionaries():
|
||||
raise NotImplemented
|
||||
|
||||
def checkText(self, text):
|
||||
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
|
||||
WORDS = r'(?iu)((?:[^_\W]|\')+)[^A-Za-z0-9\']'
|
||||
# (?iu) means case insensitive and Unicode
|
||||
# ((?:[^_\W]|\')+) means words exclude underscores but include apostrophes
|
||||
# [^A-Za-z0-9\'] used with above hack to prevent spellcheck while typing word
|
||||
#
|
||||
# See also https://stackoverflow.com/questions/2062169/regex-w-in-utf-8
|
||||
|
||||
matches = []
|
||||
|
||||
for word_object in re.finditer(WORDS, text):
|
||||
word = word_object.group(1)
|
||||
|
||||
if (self.isMisspelled(word) and not self.isCustomWord(word)):
|
||||
matches.append(BasicMatch(
|
||||
word_object.start(1), word_object.end(1)
|
||||
))
|
||||
|
||||
return matches
|
||||
|
||||
def isMisspelled(self, word):
|
||||
raise NotImplemented
|
||||
|
||||
def getSuggestions(self, word):
|
||||
raise NotImplemented
|
||||
|
||||
def findSuggestions(self, text, start, end):
|
||||
if start < end:
|
||||
word = text[start:end]
|
||||
|
||||
if (self.isMisspelled(word) and not self.isCustomWord(word)):
|
||||
match = BasicMatch(start, end)
|
||||
match.replacements = self.getSuggestions(word)
|
||||
|
||||
return [ match ]
|
||||
|
||||
return []
|
||||
|
||||
def isCustomWord(self, word):
|
||||
return word.lower() in self._customDict
|
||||
|
||||
|
@ -248,6 +297,9 @@ class EnchantDictionary(BasicDictionary):
|
|||
def getSuggestions(self, word):
|
||||
return self._dict.suggest(word)
|
||||
|
||||
def findSuggestions(self, text, start, end):
|
||||
return []
|
||||
|
||||
def isCustomWord(self, word):
|
||||
return self._dict.is_added(word)
|
||||
|
||||
|
@ -422,8 +474,152 @@ class SymSpellDictionary(BasicDictionary):
|
|||
# Since 6.3.8
|
||||
self._dict.delete_dictionary_entry(word)
|
||||
|
||||
class LanguageToolCache:
|
||||
|
||||
def __init__(self, tool, text):
|
||||
self._length = len(text)
|
||||
self._matches = self._buildMatches(tool, text)
|
||||
|
||||
def getMatches(self):
|
||||
return self._matches
|
||||
|
||||
def _buildMatches(self, tool, text):
|
||||
matches = []
|
||||
|
||||
for match in tool.check(text):
|
||||
start = match.offset
|
||||
end = start + match.errorlength
|
||||
|
||||
basic_match = BasicMatch(start, end)
|
||||
basic_match.locqualityissuetype = match.locqualityissuetype
|
||||
basic_match.replacements = match.replacements
|
||||
basic_match.msg = match.msg
|
||||
|
||||
matches.append(basic_match)
|
||||
|
||||
return matches
|
||||
|
||||
def update(self, tool, text):
|
||||
if len(text) != self._length:
|
||||
self._matches = self._buildMatches(tool, text)
|
||||
|
||||
class LanguageToolDictionary(BasicDictionary):
|
||||
|
||||
def __init__(self, name):
|
||||
BasicDictionary.__init__(self, name)
|
||||
|
||||
if not (self._lang and self._lang in languagetool.get_languages()):
|
||||
self._lang = self.getDefaultDictionary()
|
||||
|
||||
self._tool = languagetool.LanguageTool(self._lang)
|
||||
self._cache = {}
|
||||
|
||||
@staticmethod
|
||||
def getLibraryName():
|
||||
return "LanguageCheck"
|
||||
|
||||
@staticmethod
|
||||
def getLibraryURL():
|
||||
return "https://pypi.org/project/language-check/"
|
||||
|
||||
@staticmethod
|
||||
def isInstalled():
|
||||
if languagetool is not None:
|
||||
|
||||
# This check, if Java is installed, is necessary to
|
||||
# make sure LanguageTool can be run without problems.
|
||||
#
|
||||
return (os.system('java -version') == 0)
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def availableDictionaries():
|
||||
if LanguageToolDictionary.isInstalled():
|
||||
languages = list(languagetool.get_languages())
|
||||
languages.sort()
|
||||
return languages
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def getDefaultDictionary():
|
||||
if not LanguageToolDictionary.isInstalled():
|
||||
return None
|
||||
|
||||
default_locale = languagetool.get_locale_language()
|
||||
if default_locale and not default_locale in languagetool.get_languages():
|
||||
default_locale = None
|
||||
|
||||
if default_locale is None:
|
||||
default_locale = QLocale.system().name()
|
||||
if default_locale is None:
|
||||
default_locale = self.availableDictionaries()[0]
|
||||
|
||||
return default_locale
|
||||
|
||||
def checkText(self, text):
|
||||
matches = []
|
||||
|
||||
if len(text) == 0:
|
||||
return matches
|
||||
|
||||
textId = hash(text)
|
||||
cacheEntry = None
|
||||
|
||||
if not textId in self._cache:
|
||||
cacheEntry = LanguageToolCache(self._tool, text)
|
||||
|
||||
self._cache[textId] = cacheEntry
|
||||
else:
|
||||
cacheEntry = self._cache[textId]
|
||||
cacheEntry.update(self._tool, text)
|
||||
|
||||
for match in cacheEntry.getMatches():
|
||||
word = match.getWord(text)
|
||||
|
||||
if not (match.locqualityissuetype == 'misspelling' and self.isCustomWord(word)):
|
||||
matches.append(match)
|
||||
|
||||
return matches
|
||||
|
||||
def isMisspelled(self, word):
|
||||
if self.isCustomWord(word):
|
||||
return False
|
||||
|
||||
for match in self.checkText(word):
|
||||
if match.locqualityissuetype == 'misspelling':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def getSuggestions(self, word):
|
||||
suggestions = []
|
||||
|
||||
for match in self.checkText(word):
|
||||
suggestions += match.replacements
|
||||
|
||||
return suggestions
|
||||
|
||||
def findSuggestions(self, text, start, end):
|
||||
matches = []
|
||||
checked = self.checkText(text)
|
||||
|
||||
if start == end:
|
||||
# Check for containing area:
|
||||
for match in checked:
|
||||
if (start >= match.start and start <= match.end):
|
||||
matches.append(match)
|
||||
else:
|
||||
# Check for overlapping area:
|
||||
for match in checked:
|
||||
if (match.end > start and match.start < end):
|
||||
matches.append(match)
|
||||
|
||||
return matches
|
||||
|
||||
|
||||
# Register the implementations in order of priority
|
||||
Spellchecker.implementations.append(EnchantDictionary)
|
||||
Spellchecker.registerImplementation(EnchantDictionary)
|
||||
Spellchecker.registerImplementation(SymSpellDictionary)
|
||||
Spellchecker.registerImplementation(PySpellcheckerDictionary)
|
||||
Spellchecker.registerImplementation(LanguageToolDictionary)
|
||||
|
|
|
@ -80,6 +80,9 @@ class outlineItem(abstractItem):
|
|||
def wordCount(self):
|
||||
return self._data.get(self.enum.wordCount, 0)
|
||||
|
||||
def charCount(self):
|
||||
return self._data.get(self.enum.charCount, 0)
|
||||
|
||||
def __str__(self):
|
||||
return "{id}: {folder}{title}{children}".format(
|
||||
id=self.ID(),
|
||||
|
@ -89,6 +92,9 @@ class outlineItem(abstractItem):
|
|||
)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def charCount(self):
|
||||
return self._data.get(self.enum.charCount, 0)
|
||||
|
||||
#######################################################################
|
||||
# Data
|
||||
|
@ -119,7 +125,7 @@ class outlineItem(abstractItem):
|
|||
|
||||
elif role == Qt.FontRole:
|
||||
f = QFont()
|
||||
if column == E.wordCount and self.isFolder():
|
||||
if (column == E.wordCount or column == E.charCount) and self.isFolder():
|
||||
f.setItalic(True)
|
||||
elif column == E.goal and self.isFolder() and not self.data(E.setGoal):
|
||||
f.setItalic(True)
|
||||
|
@ -140,7 +146,7 @@ class outlineItem(abstractItem):
|
|||
|
||||
# Checking if we will have to recount words
|
||||
updateWordCount = False
|
||||
if column in [E.wordCount, E.goal, E.setGoal]:
|
||||
if column in [E.wordCount, E.charCount, E.goal, E.setGoal]:
|
||||
updateWordCount = not column in self._data or self._data[column] != data
|
||||
|
||||
# Stuff to do before
|
||||
|
@ -153,7 +159,9 @@ class outlineItem(abstractItem):
|
|||
# Stuff to do afterwards
|
||||
if column == E.text:
|
||||
wc = F.wordCount(data)
|
||||
cc = F.charCount(data, settings.countSpaces)
|
||||
self.setData(E.wordCount, wc)
|
||||
self.setData(E.charCount, cc)
|
||||
|
||||
if column == E.compile:
|
||||
# Title changes when compile changes
|
||||
|
@ -195,9 +203,12 @@ class outlineItem(abstractItem):
|
|||
|
||||
else:
|
||||
wc = 0
|
||||
cc = 0
|
||||
for c in self.children():
|
||||
wc += F.toInt(c.data(self.enum.wordCount))
|
||||
cc += F.toInt(c.data(self.enum.charCount))
|
||||
self._data[self.enum.wordCount] = wc
|
||||
self._data[self.enum.charCount] = cc
|
||||
|
||||
setGoal = F.toInt(self.data(self.enum.setGoal))
|
||||
goal = F.toInt(self.data(self.enum.goal))
|
||||
|
@ -218,7 +229,8 @@ class outlineItem(abstractItem):
|
|||
self.setData(self.enum.goalPercentage, "")
|
||||
|
||||
self.emitDataChanged([self.enum.goal, self.enum.setGoal,
|
||||
self.enum.wordCount, self.enum.goalPercentage])
|
||||
self.enum.wordCount, self.enum.charCount,
|
||||
self.enum.goalPercentage])
|
||||
|
||||
if self.parent():
|
||||
self.parent().updateWordCount()
|
||||
|
@ -467,6 +479,7 @@ class outlineItem(abstractItem):
|
|||
|
||||
# We don't want to write some datas (computed)
|
||||
XMLExclude = [enums.Outline.wordCount,
|
||||
enums.Outline.charCount,
|
||||
enums.Outline.goal,
|
||||
enums.Outline.goalPercentage,
|
||||
enums.Outline.revisions]
|
||||
|
|
|
@ -47,6 +47,8 @@ corkSizeFactor = 100
|
|||
folderView = "cork"
|
||||
lastTab = 0
|
||||
openIndexes = [""]
|
||||
progressChars = False
|
||||
countSpaces = True
|
||||
autoSave = False
|
||||
autoSaveDelay = 5
|
||||
autoSaveNoChanges = True
|
||||
|
@ -123,7 +125,7 @@ def initDefaultValues():
|
|||
def save(filename=None, protocol=None):
|
||||
|
||||
global spellcheck, dict, corkSliderFactor, viewSettings, corkSizeFactor, folderView, lastTab, openIndexes, \
|
||||
autoSave, autoSaveDelay, saveOnQuit, autoSaveNoChanges, autoSaveNoChangesDelay, outlineViewColumns, \
|
||||
progressChars, autoSave, autoSaveDelay, saveOnQuit, autoSaveNoChanges, autoSaveNoChangesDelay, outlineViewColumns, \
|
||||
corkBackground, corkStyle, fullScreenTheme, defaultTextType, textEditor, revisions, frequencyAnalyzer, viewMode, \
|
||||
saveToZip, dontShowDeleteWarning, fullscreenSettings
|
||||
|
||||
|
@ -136,6 +138,8 @@ def save(filename=None, protocol=None):
|
|||
"folderView": folderView,
|
||||
"lastTab": lastTab,
|
||||
"openIndexes": openIndexes,
|
||||
"progressChars": progressChars,
|
||||
"countSpaces": countSpaces,
|
||||
"autoSave":autoSave,
|
||||
"autoSaveDelay":autoSaveDelay,
|
||||
# TODO: Settings Cleanup Task -- Rename saveOnQuit to saveOnProjectClose -- see PR #615
|
||||
|
@ -235,6 +239,14 @@ def load(string, fromString=False, protocol=None):
|
|||
global openIndexes
|
||||
openIndexes = allSettings["openIndexes"]
|
||||
|
||||
if "progressChars" in allSettings:
|
||||
global progressChars
|
||||
progressChars = allSettings["progressChars"]
|
||||
|
||||
if "countSpaces" in allSettings:
|
||||
global countSpaces
|
||||
countSpaces = allSettings["countSpaces"]
|
||||
|
||||
if "autoSave" in allSettings:
|
||||
global autoSave
|
||||
autoSave = allSettings["autoSave"]
|
||||
|
|
|
@ -111,6 +111,9 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
self.spnGeneralFontSize.setValue(f.pointSize())
|
||||
self.spnGeneralFontSize.valueChanged.connect(self.setAppFontSize)
|
||||
|
||||
self.chkProgressChars.setChecked(settings.progressChars);
|
||||
self.chkProgressChars.stateChanged.connect(self.charSettingsChanged)
|
||||
|
||||
self.txtAutoSave.setValidator(QIntValidator(0, 999, self))
|
||||
self.txtAutoSaveNoChanges.setValidator(QIntValidator(0, 999, self))
|
||||
self.chkAutoSave.setChecked(settings.autoSave)
|
||||
|
@ -164,10 +167,12 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
for item, what, value in [
|
||||
(self.rdoTreeItemCount, "InfoFolder", "Count"),
|
||||
(self.rdoTreeWC, "InfoFolder", "WC"),
|
||||
(self.rdoTreeCC, "InfoFolder", "CC"),
|
||||
(self.rdoTreeProgress, "InfoFolder", "Progress"),
|
||||
(self.rdoTreeSummary, "InfoFolder", "Summary"),
|
||||
(self.rdoTreeNothing, "InfoFolder", "Nothing"),
|
||||
(self.rdoTreeTextWC, "InfoText", "WC"),
|
||||
(self.rdoTreeTextCC, "InfoText", "CC"),
|
||||
(self.rdoTreeTextProgress, "InfoText", "Progress"),
|
||||
(self.rdoTreeTextSummary, "InfoText", "Summary"),
|
||||
(self.rdoTreeTextNothing, "InfoText", "Nothing"),
|
||||
|
@ -180,6 +185,9 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
lambda v: self.lblTreeIconSize.setText("{}x{}".format(v, v)))
|
||||
self.sldTreeIconSize.setValue(settings.viewSettings["Tree"]["iconSize"])
|
||||
|
||||
self.chkCountSpaces.setChecked(settings.countSpaces);
|
||||
self.chkCountSpaces.stateChanged.connect(self.countSpacesChanged)
|
||||
|
||||
self.rdoCorkOldStyle.setChecked(settings.corkStyle == "old")
|
||||
self.rdoCorkNewStyle.setChecked(settings.corkStyle == "new")
|
||||
self.rdoCorkNewStyle.toggled.connect(self.setCorkStyle)
|
||||
|
@ -338,6 +346,11 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
sttgs = QSettings(qApp.organizationName(), qApp.applicationName())
|
||||
sttgs.setValue("appFontSize", val)
|
||||
|
||||
def charSettingsChanged(self):
|
||||
settings.progressChars = True if self.chkProgressChars.checkState() else False
|
||||
|
||||
self.mw.mainEditor.updateStats()
|
||||
|
||||
def saveSettingsChanged(self):
|
||||
if self.txtAutoSave.text() in ["", "0"]:
|
||||
self.txtAutoSave.setText("1")
|
||||
|
@ -427,10 +440,12 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
for item, what, value in [
|
||||
(self.rdoTreeItemCount, "InfoFolder", "Count"),
|
||||
(self.rdoTreeWC, "InfoFolder", "WC"),
|
||||
(self.rdoTreeCC, "InfoFolder", "CC"),
|
||||
(self.rdoTreeProgress, "InfoFolder", "Progress"),
|
||||
(self.rdoTreeSummary, "InfoFolder", "Summary"),
|
||||
(self.rdoTreeNothing, "InfoFolder", "Nothing"),
|
||||
(self.rdoTreeTextWC, "InfoText", "WC"),
|
||||
(self.rdoTreeTextCC, "InfoText", "CC"),
|
||||
(self.rdoTreeTextProgress, "InfoText", "Progress"),
|
||||
(self.rdoTreeTextSummary, "InfoText", "Summary"),
|
||||
(self.rdoTreeTextNothing, "InfoText", "Nothing"),
|
||||
|
@ -445,6 +460,11 @@ class settingsWindow(QWidget, Ui_Settings):
|
|||
|
||||
self.mw.treeRedacOutline.viewport().update()
|
||||
|
||||
def countSpacesChanged(self):
|
||||
settings.countSpaces = True if self.chkCountSpaces.checkState() else False
|
||||
|
||||
self.mw.mainEditor.updateStats()
|
||||
|
||||
def setCorkColor(self):
|
||||
color = QColor(settings.corkBackground["color"])
|
||||
self.colorDialog = QColorDialog(color, self)
|
||||
|
|
|
@ -292,6 +292,7 @@ class mainEditor(QWidget, Ui_mainEditor):
|
|||
return
|
||||
|
||||
index = self.currentEditor().currentIndex
|
||||
|
||||
if index.isValid():
|
||||
item = index.internalPointer()
|
||||
else:
|
||||
|
@ -300,15 +301,21 @@ class mainEditor(QWidget, Ui_mainEditor):
|
|||
if not item:
|
||||
item = self.mw.mdlOutline.rootItem
|
||||
|
||||
cc = item.data(Outline.charCount)
|
||||
wc = item.data(Outline.wordCount)
|
||||
goal = item.data(Outline.goal)
|
||||
chars = item.data(Outline.charCount) # len(item.data(Outline.text))
|
||||
progress = item.data(Outline.goalPercentage)
|
||||
|
||||
goal = uiParse(goal, None, int, lambda x: x>=0)
|
||||
progress = uiParse(progress, 0.0, float)
|
||||
|
||||
if not cc:
|
||||
cc = 0
|
||||
|
||||
if not wc:
|
||||
wc = 0
|
||||
|
||||
if goal:
|
||||
self.lblRedacProgress.show()
|
||||
rect = self.lblRedacProgress.geometry()
|
||||
|
@ -319,13 +326,31 @@ class mainEditor(QWidget, Ui_mainEditor):
|
|||
drawProgress(p, rect, progress, 2)
|
||||
del p
|
||||
self.lblRedacProgress.setPixmap(self.px)
|
||||
self.lblRedacWC.setText(self.tr("{} words / {} ").format(
|
||||
locale.format_string("%d", wc, grouping=True),
|
||||
locale.format_string("%d", goal, grouping=True)))
|
||||
|
||||
if settings.progressChars:
|
||||
self.lblRedacWC.setText(self.tr("({} chars) {} words / {} ").format(
|
||||
locale.format("%d", cc, grouping=True),
|
||||
locale.format("%d", wc, grouping=True),
|
||||
locale.format("%d", goal, grouping=True)))
|
||||
self.lblRedacWC.setToolTip("")
|
||||
else:
|
||||
self.lblRedacWC.setText(self.tr("{} words / {} ").format(
|
||||
locale.format("%d", wc, grouping=True),
|
||||
locale.format("%d", goal, grouping=True)))
|
||||
self.lblRedacWC.setToolTip(self.tr("{} chars").format(
|
||||
locale.format("%d", cc, grouping=True)))
|
||||
else:
|
||||
self.lblRedacProgress.hide()
|
||||
self.lblRedacWC.setText(self.tr("{} words ").format(
|
||||
locale.format_string("%d", wc, grouping=True)))
|
||||
|
||||
if settings.progressChars:
|
||||
self.lblRedacWC.setText(self.tr("{} chars ").format(
|
||||
locale.format("%d", cc, grouping=True)))
|
||||
self.lblRedacWC.setToolTip("")
|
||||
else:
|
||||
self.lblRedacWC.setText(self.tr("{} words ").format(
|
||||
locale.format("%d", wc, grouping=True)))
|
||||
self.lblRedacWC.setToolTip(self.tr("{} chars").format(
|
||||
locale.format("%d", cc, grouping=True)))
|
||||
|
||||
###############################################################################
|
||||
# VIEWS
|
||||
|
|
|
@ -18,7 +18,6 @@ class BasicHighlighter(QSyntaxHighlighter):
|
|||
QSyntaxHighlighter.__init__(self, editor.document())
|
||||
|
||||
self.editor = editor
|
||||
self._misspelledColor = Qt.red
|
||||
self._defaultBlockFormat = QTextBlockFormat()
|
||||
self._defaultCharFormat = QTextCharFormat()
|
||||
self.defaultTextColor = QColor(S.text)
|
||||
|
@ -27,6 +26,40 @@ class BasicHighlighter(QSyntaxHighlighter):
|
|||
self.linkColor = QColor(S.link)
|
||||
self.spellingErrorColor = QColor(Qt.red)
|
||||
|
||||
# Matches during checking can be separated by their type (all of them listed here):
|
||||
# https://languagetool.org/development/api/org/languagetool/rules/ITSIssueType.html
|
||||
#
|
||||
# These are the colors for actual spell-, grammar- and style-checking:
|
||||
self._errorColors = {
|
||||
'addition' : QColor(255, 215, 0), # gold
|
||||
'characters' : QColor(135, 206, 235), # sky blue
|
||||
'duplication' : QColor(0, 255, 255), # cyan / aqua
|
||||
'formatting' : QColor(0, 128, 128), # teal
|
||||
'grammar' : QColor(0, 0, 255), # blue
|
||||
'inconsistency' : QColor(128, 128, 0), # olive
|
||||
'inconsistententities' : QColor(46, 139, 87), # sea green
|
||||
'internationalization' : QColor(255, 165, 0), # orange
|
||||
'legal' : QColor(255, 69, 0), # orange red
|
||||
'length' : QColor(47, 79, 79), # dark slate gray
|
||||
'localespecificcontent' : QColor(188, 143, 143),# rosy brown
|
||||
'localeviolation' : QColor(128, 0, 0), # maroon
|
||||
'markup' : QColor(128, 0, 128), # purple
|
||||
'misspelling' : QColor(255, 0, 0), # red
|
||||
'mistranslation' : QColor(255, 0, 255), # magenta / fuchsia
|
||||
'nonconformance' : QColor(255, 218, 185), # peach puff
|
||||
'numbers' : QColor(65, 105, 225), # royal blue
|
||||
'omission' : QColor(255, 20, 147), # deep pink
|
||||
'other' : QColor(138, 43, 226), # blue violet
|
||||
'patternproblem' : QColor(0, 128, 0), # green
|
||||
'register' : QColor(112,128,144), # slate gray
|
||||
'style' : QColor(0, 255, 0), # lime
|
||||
'terminology' : QColor(0, 0, 128), # navy
|
||||
'typographical' : QColor(255, 255, 0), # yellow
|
||||
'uncategorized' : QColor(128, 128, 128), # gray
|
||||
'untranslated' : QColor(210, 105, 30), # chocolate
|
||||
'whitespace' : QColor(192, 192, 192) # silver
|
||||
}
|
||||
|
||||
def setDefaultBlockFormat(self, bf):
|
||||
self._defaultBlockFormat = bf
|
||||
self.rehighlight()
|
||||
|
@ -36,7 +69,7 @@ class BasicHighlighter(QSyntaxHighlighter):
|
|||
self.rehighlight()
|
||||
|
||||
def setMisspelledColor(self, color):
|
||||
self._misspelledColor = color
|
||||
self._errorColors['misspelled'] = color
|
||||
|
||||
def updateColorScheme(self, rehighlight=True):
|
||||
"""
|
||||
|
@ -134,32 +167,25 @@ class BasicHighlighter(QSyntaxHighlighter):
|
|||
txt.end() - txt.start(),
|
||||
fmt)
|
||||
|
||||
# Spell checking
|
||||
if hasattr(self.editor, "spellcheck") and self.editor.spellcheck and self.editor._dict:
|
||||
# Spell checking
|
||||
|
||||
# Following algorithm would not check words at the end of line.
|
||||
# This hacks adds a space to every line where the text cursor is not
|
||||
# So that it doesn't spellcheck while typing, but still spellchecks at
|
||||
# end of lines. See github's issue #166.
|
||||
textedText = text
|
||||
if self.currentBlock().position() + len(text) != \
|
||||
self.editor.textCursor().position():
|
||||
textedText = text + " "
|
||||
# Following algorithm would not check words at the end of line.
|
||||
# This hacks adds a space to every line where the text cursor is not
|
||||
# So that it doesn't spellcheck while typing, but still spellchecks at
|
||||
# end of lines. See github's issue #166.
|
||||
textedText = text
|
||||
if self.currentBlock().position() + len(text) != \
|
||||
self.editor.textCursor().position():
|
||||
textedText = text + " "
|
||||
|
||||
# Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
|
||||
WORDS = r'(?iu)((?:[^_\W]|\')+)[^A-Za-z0-9\']'
|
||||
# (?iu) means case insensitive and Unicode
|
||||
# ((?:[^_\W]|\')+) means words exclude underscores but include apostrophes
|
||||
# [^A-Za-z0-9\'] used with above hack to prevent spellcheck while typing word
|
||||
#
|
||||
# See also https://stackoverflow.com/questions/2062169/regex-w-in-utf-8
|
||||
if hasattr(self.editor, "spellcheck") and self.editor.spellcheck:
|
||||
for word_object in re.finditer(WORDS, textedText):
|
||||
if (self.editor._dict
|
||||
and self.editor._dict.isMisspelled(word_object.group(1))):
|
||||
format = self.format(word_object.start(1))
|
||||
format.setUnderlineColor(self._misspelledColor)
|
||||
# The text should only be checked once as a whole
|
||||
for match in self.editor._dict.checkText(textedText):
|
||||
if match.locqualityissuetype in self._errorColors:
|
||||
highlight_color = self._errorColors[match.locqualityissuetype]
|
||||
|
||||
format = self.format(match.start)
|
||||
format.setUnderlineColor(highlight_color)
|
||||
# SpellCheckUnderline fails with some fonts
|
||||
format.setUnderlineStyle(QTextCharFormat.WaveUnderline)
|
||||
self.setFormat(word_object.start(1),
|
||||
word_object.end(1) - word_object.start(1),
|
||||
format)
|
||||
self.setFormat(match.start, match.end - match.start, format)
|
||||
|
|
|
@ -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.14.1
|
||||
# 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"))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<width>681</width>
|
||||
<height>598</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -54,7 +54,7 @@
|
|||
<item>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="stackedWidgetPage1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
|
@ -98,93 +98,139 @@
|
|||
<string>Application settings</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_13">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_56">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cmbStyle">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_57">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="cmbTranslation">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_58">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="spnGeneralFontSize">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restarting Manuskript ensures all settings take effect.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restarting Manuskript ensures all settings take effect.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_14">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_56">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cmbStyle">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_57">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cmbTranslation">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_58">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spnGeneralFontSize">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_15">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="chkProgressChars">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show progress in chars next
|
||||
to words</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -817,7 +863,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabViews">
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="icon">
|
||||
|
@ -1055,6 +1101,59 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="horizontalGroupBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Char/Word Counter</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chkCountSpaces">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Count spaces as chars</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
|
@ -1095,6 +1194,19 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rdoTreeCC">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show char c&ount</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rdoTreeProgress">
|
||||
<property name="font">
|
||||
|
@ -1165,6 +1277,19 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rdoTreeTextCC">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sho&w char count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rdoTreeTextProgress">
|
||||
<property name="font">
|
||||
|
@ -1224,6 +1349,11 @@
|
|||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>rdoTreeTextCC</zorder>
|
||||
<zorder>rdoTreeTextWC</zorder>
|
||||
<zorder>rdoTreeTextProgress</zorder>
|
||||
<zorder>rdoTreeTextSummary</zorder>
|
||||
<zorder>rdoTreeTextNothing</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -2974,7 +3104,7 @@
|
|||
<item>
|
||||
<widget class="QStackedWidget" name="themeStack">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="stackedWidgetPage1_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
@ -47,6 +47,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
|
||||
|
@ -393,6 +395,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.
|
||||
|
@ -440,42 +485,108 @@ class textEditView(QTextEdit):
|
|||
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)
|
||||
suggestions = []
|
||||
selectedWord = None
|
||||
|
||||
# Check for any suggestions for corrections at the cursors position
|
||||
if self._dict:
|
||||
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):
|
||||
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 or selectedWord):
|
||||
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 not selectedWord):
|
||||
# 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)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue