1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2009 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing a dialog to enter lexer associations for the project.
8"""
9
10import os
11
12from PyQt5.QtCore import Qt, pyqtSlot
13from PyQt5.QtWidgets import QHeaderView, QTreeWidgetItem, QDialog
14
15from .Ui_LexerAssociationDialog import Ui_LexerAssociationDialog
16
17
18class LexerAssociationDialog(QDialog, Ui_LexerAssociationDialog):
19    """
20    Class implementing a dialog to enter lexer associations for the project.
21    """
22    def __init__(self, project, parent=None):
23        """
24        Constructor
25
26        @param project reference to the project object
27        @param parent reference to the parent widget (QWidget)
28        """
29        super().__init__(parent)
30        self.setupUi(self)
31
32        self.editorLexerList.headerItem().setText(
33            self.editorLexerList.columnCount(), "")
34        header = self.editorLexerList.header()
35        header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
36        header.setSortIndicator(0, Qt.SortOrder.AscendingOrder)
37
38        try:
39            self.extsep = os.extsep
40        except AttributeError:
41            self.extsep = "."
42
43        self.extras = ["-----------", self.tr("Alternative")]
44
45        import QScintilla.Lexers
46        languages = (
47            [''] +
48            sorted(QScintilla.Lexers.getSupportedLanguages().keys()) +
49            self.extras
50        )
51        for lang in languages:
52            self.editorLexerCombo.addItem(
53                QScintilla.Lexers.getLanguageIcon(lang, False),
54                lang)
55
56        from pygments.lexers import get_all_lexers
57        pygmentsLexers = [''] + sorted(lex[0] for lex in get_all_lexers())
58        self.pygmentsLexerCombo.addItems(pygmentsLexers)
59
60        # set initial values
61        self.project = project
62        for ext, lexer in list(self.project.pdata["LEXERASSOCS"].items()):
63            QTreeWidgetItem(self.editorLexerList, [ext, lexer])
64        self.editorLexerList.sortByColumn(0, Qt.SortOrder.AscendingOrder)
65
66    @pyqtSlot()
67    def on_addLexerButton_clicked(self):
68        """
69        Private slot to add the lexer association displayed to the list.
70        """
71        ext = self.editorFileExtEdit.text()
72        if ext.startswith(self.extsep):
73            ext.replace(self.extsep, "")
74        lexer = self.editorLexerCombo.currentText()
75        if lexer in self.extras:
76            pygmentsLexer = self.pygmentsLexerCombo.currentText()
77            if not pygmentsLexer:
78                lexer = pygmentsLexer
79            else:
80                lexer = "Pygments|{0}".format(pygmentsLexer)
81        if ext and lexer:
82            itmList = self.editorLexerList.findItems(
83                ext, Qt.MatchFlags(Qt.MatchFlag.MatchExactly), 0)
84            if itmList:
85                index = self.editorLexerList.indexOfTopLevelItem(itmList[0])
86                itm = self.editorLexerList.takeTopLevelItem(index)
87                # __IGNORE_WARNING__
88                del itm
89            QTreeWidgetItem(self.editorLexerList, [ext, lexer])
90            self.editorFileExtEdit.clear()
91            self.editorLexerCombo.setCurrentIndex(0)
92            self.pygmentsLexerCombo.setCurrentIndex(0)
93            self.editorLexerList.sortItems(
94                self.editorLexerList.sortColumn(),
95                self.editorLexerList.header().sortIndicatorOrder())
96
97    @pyqtSlot()
98    def on_deleteLexerButton_clicked(self):
99        """
100        Private slot to delete the currently selected lexer association of the
101        list.
102        """
103        itmList = self.editorLexerList.selectedItems()
104        if itmList:
105            index = self.editorLexerList.indexOfTopLevelItem(itmList[0])
106            itm = self.editorLexerList.takeTopLevelItem(index)
107            # __IGNORE_WARNING__
108            del itm
109
110            self.editorLexerList.clearSelection()
111            self.editorFileExtEdit.clear()
112            self.editorLexerCombo.setCurrentIndex(0)
113
114    def on_editorLexerList_itemClicked(self, itm, column):
115        """
116        Private slot to handle the clicked signal of the lexer association
117        list.
118
119        @param itm reference to the selecte item (QTreeWidgetItem)
120        @param column column the item was clicked or activated (integer)
121            (ignored)
122        """
123        if itm is None:
124            self.editorFileExtEdit.clear()
125            self.editorLexerCombo.setCurrentIndex(0)
126            self.pygmentsLexerCombo.setCurrentIndex(0)
127        else:
128            self.editorFileExtEdit.setText(itm.text(0))
129            lexer = itm.text(1)
130            if lexer.startswith("Pygments|"):
131                pygmentsLexer = lexer.split("|")[1]
132                pygmentsIndex = self.pygmentsLexerCombo.findText(pygmentsLexer)
133                lexer = self.tr("Alternative")
134            else:
135                pygmentsIndex = 0
136            index = self.editorLexerCombo.findText(lexer)
137            self.editorLexerCombo.setCurrentIndex(index)
138            self.pygmentsLexerCombo.setCurrentIndex(pygmentsIndex)
139
140    def on_editorLexerList_itemActivated(self, itm, column):
141        """
142        Private slot to handle the activated signal of the lexer association
143        list.
144
145        @param itm reference to the selecte item (QTreeWidgetItem)
146        @param column column the item was clicked or activated (integer)
147            (ignored)
148        """
149        self.on_editorLexerList_itemClicked(itm, column)
150
151    @pyqtSlot(int)
152    def on_editorLexerCombo_currentIndexChanged(self, index):
153        """
154        Private slot to handle the selection of a lexer.
155
156        @param index index of the current item
157        @type int
158        """
159        text = self.editorLexerCombo.itemText(index)
160        if text in self.extras:
161            self.pygmentsLexerCombo.setEnabled(True)
162            self.pygmentsLabel.setEnabled(True)
163        else:
164            self.pygmentsLexerCombo.setEnabled(False)
165            self.pygmentsLabel.setEnabled(False)
166
167    def transferData(self):
168        """
169        Public slot to transfer the associations into the projects data
170        structure.
171        """
172        self.project.pdata["LEXERASSOCS"] = {}
173        for index in range(self.editorLexerList.topLevelItemCount()):
174            itm = self.editorLexerList.topLevelItem(index)
175            pattern = itm.text(0)
176            self.project.pdata["LEXERASSOCS"][pattern] = itm.text(1)
177