1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing the editor highlighter keywords configuration page.
8"""
9
10from PyQt5.QtCore import pyqtSlot
11
12from E5Gui import E5MessageBox
13
14from .ConfigurationPageBase import ConfigurationPageBase
15from .Ui_EditorKeywordsPage import Ui_EditorKeywordsPage
16
17import Preferences
18
19
20class EditorKeywordsPage(ConfigurationPageBase, Ui_EditorKeywordsPage):
21    """
22    Class implementing the editor highlighter keywords configuration page.
23    """
24    MaxKeywordSets = 8          # max. 8 sets are allowed
25
26    def __init__(self):
27        """
28        Constructor
29        """
30        super().__init__()
31        self.setupUi(self)
32        self.setObjectName("EditorKeywordsPage")
33
34        # set initial values
35        import QScintilla.Lexers
36        from QScintilla.Lexers.LexerContainer import LexerContainer
37
38        self.__keywords = {
39            "": {
40                "Sets": [""] * (self.MaxKeywordSets + 1),
41                "Descriptions": [""] * (self.MaxKeywordSets + 1),
42                "MaxSets": 0,
43            }
44        }
45
46        languages = sorted(
47            [''] + list(QScintilla.Lexers.getSupportedLanguages().keys()))
48        for lang in languages:
49            if lang:
50                lex = QScintilla.Lexers.getLexer(lang)
51                if isinstance(lex, LexerContainer):
52                    continue
53                keywords = Preferences.getEditorKeywords(lang)[:]
54                if keywords:
55                    # set empty entries to default values
56                    for kwSet in range(1, self.MaxKeywordSets + 1):
57                        if not keywords[kwSet]:
58                            kw = lex.defaultKeywords(kwSet)
59                            if kw is None:
60                                kw = ""
61                            keywords[kwSet] = kw
62                else:
63                    keywords = [""]
64                    descriptions = [""]
65                    for kwSet in range(1, self.MaxKeywordSets + 1):
66                        kw = lex.keywords(kwSet)
67                        if kw is None:
68                            kw = ""
69                        keywords.append(kw)
70                descriptions = [""]
71                for kwSet in range(1, self.MaxKeywordSets + 1):
72                    desc = lex.keywordsDescription(kwSet)
73                    descriptions.append(desc)
74                defaults = [""]
75                for kwSet in range(1, self.MaxKeywordSets + 1):
76                    dkw = lex.defaultKeywords(kwSet)
77                    if dkw is None:
78                        dkw = ""
79                    defaults.append(dkw)
80                self.__keywords[lang] = {
81                    "Sets": keywords,
82                    "Descriptions": descriptions,
83                    "DefaultSets": defaults,
84                    "MaxSets": lex.maximumKeywordSet(),
85                }
86            self.languageCombo.addItem(
87                QScintilla.Lexers.getLanguageIcon(lang, False),
88                lang)
89
90        self.currentLanguage = ''
91        self.currentSet = 1
92        self.on_languageCombo_activated(0)
93
94    def save(self):
95        """
96        Public slot to save the editor highlighter keywords configuration.
97        """
98        lang = self.languageCombo.currentText()
99        kwSet = self.setSpinBox.value()
100        self.__keywords[lang]["Sets"][kwSet] = self.keywordsEdit.toPlainText()
101
102        for lang, keywords in self.__keywords.items():
103            Preferences.setEditorKeywords(lang, keywords["Sets"])
104
105    @pyqtSlot(int)
106    def on_languageCombo_activated(self, index):
107        """
108        Private slot to fill the keywords edit.
109
110        @param index index of the selected entry
111        @type int
112        """
113        language = self.languageCombo.itemText(index)
114
115        self.defaultButton.setEnabled(bool(language))
116        self.allDefaultButton.setEnabled(bool(language))
117
118        if self.currentLanguage == language:
119            return
120
121        if self.setSpinBox.value() == 1:
122            self.on_setSpinBox_valueChanged(1)
123        if self.__keywords[language]["MaxSets"]:
124            first = 1
125            last = self.__keywords[language]["MaxSets"]
126        else:
127            first, last = self.MaxKeywordSets + 1, 0
128            for kwSet in range(1, self.MaxKeywordSets + 1):
129                if self.__keywords[language]["Descriptions"][kwSet] != "":
130                    first = min(first, kwSet)
131                    last = max(last, kwSet)
132        self.setSpinBox.setEnabled(language != "" and
133                                   first <= self.MaxKeywordSets)
134        self.keywordsEdit.setEnabled(language != "" and
135                                     first <= self.MaxKeywordSets)
136        if first <= self.MaxKeywordSets:
137            self.setSpinBox.setMinimum(first)
138            self.setSpinBox.setMaximum(last)
139            self.setSpinBox.setValue(first)
140        else:
141            self.setSpinBox.setMinimum(0)
142            self.setSpinBox.setMaximum(0)
143            self.setSpinBox.setValue(0)
144
145    @pyqtSlot(int)
146    def on_setSpinBox_valueChanged(self, kwSet):
147        """
148        Private slot to fill the keywords edit.
149
150        @param kwSet number of the selected keyword set
151        @type int
152        """
153        language = self.languageCombo.currentText()
154        if self.currentLanguage == language and self.currentSet == kwSet:
155            return
156
157        self.__keywords[self.currentLanguage]["Sets"][self.currentSet] = (
158            self.keywordsEdit.toPlainText()
159        )
160
161        self.currentLanguage = language
162        self.currentSet = kwSet
163        self.setDescriptionLabel.setText("<b>{0}</b>".format(
164            self.__keywords[language]["Descriptions"][kwSet]))
165        self.keywordsEdit.setPlainText(
166            self.__keywords[language]["Sets"][kwSet])
167
168    @pyqtSlot()
169    def on_defaultButton_clicked(self):
170        """
171        Private slot to set the current keyword set to default values.
172        """
173        ok = (
174            E5MessageBox.yesNo(
175                self,
176                self.tr("Reset to Default"),
177                self.tr("Shall the current keyword set really be reset to"
178                        " default values?"))
179            if bool(self.keywordsEdit.toPlainText()) else
180            True
181        )
182        if ok:
183            language = self.languageCombo.currentText()
184            kwSet = self.setSpinBox.value()
185            self.__keywords[language]["Sets"][kwSet] = (
186                self.__keywords[language]["DefaultSets"][kwSet]
187            )
188            self.keywordsEdit.setPlainText(
189                self.__keywords[language]["Sets"][kwSet])
190
191    @pyqtSlot()
192    def on_allDefaultButton_clicked(self):
193        """
194        Private slot to set all keyword sets of the current language to default
195        values.
196        """
197        ok = E5MessageBox.yesNo(
198            self,
199            self.tr("Reset All to Default"),
200            self.tr("Shall all keyword sets of the current language really be"
201                    " reset to default values?"))
202        if ok:
203            language = self.languageCombo.currentText()
204            kwSet = self.setSpinBox.value()
205            self.__keywords[language]["Sets"] = (
206                self.__keywords[language]["DefaultSets"][:]
207            )
208            self.keywordsEdit.setPlainText(
209                self.__keywords[language]["Sets"][kwSet])
210
211
212def create(dlg):
213    """
214    Module function to create the configuration page.
215
216    @param dlg reference to the configuration dialog
217    @type ConfigurationWidget
218    @return reference to the instantiated page
219    @rtype ConfigurationPageBase
220    """
221    page = EditorKeywordsPage()
222    return page
223