eric6/Plugins/WizardPlugins/PyRegExpWizard/PyRegExpWizardCharactersDialog.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2004 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog for entering character classes.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import QRegExp
13 from PyQt5.QtGui import QRegExpValidator
14 from PyQt5.QtWidgets import QSizePolicy, QSpacerItem, QWidget, QHBoxLayout, \
15 QLineEdit, QPushButton, QDialog, QScrollArea, QComboBox, QVBoxLayout, \
16 QLabel
17
18 from .Ui_PyRegExpWizardCharactersDialog import \
19 Ui_PyRegExpWizardCharactersDialog
20
21
22 class PyRegExpWizardCharactersDialog(
23 QDialog, Ui_PyRegExpWizardCharactersDialog):
24 """
25 Class implementing a dialog for entering character classes.
26 """
27 specialChars = {
28 4: "\\a",
29 5: "\\f",
30 6: "\\n",
31 7: "\\r",
32 8: "\\t",
33 9: "\\v"
34 }
35
36 predefinedClasses = ["\\s", "\\S", "\\w", "\\W", "\\d", "\\D"]
37
38 def __init__(self, parent=None):
39 """
40 Constructor
41
42 @param parent parent widget (QWidget)
43 """
44 super(PyRegExpWizardCharactersDialog, self).__init__(parent)
45 self.setupUi(self)
46
47 self.comboItems = []
48 self.singleComboItems = [] # these are in addition to the above
49 self.comboItems.append(self.tr("Normal character"))
50 self.comboItems.append(
51 self.tr("Unicode character in hexadecimal notation"))
52 self.comboItems.append(
53 self.tr("Unicode character in octal notation"))
54 self.singleComboItems.append(self.tr("---"))
55 self.singleComboItems.append(self.tr("Bell character (\\a)"))
56 self.singleComboItems.append(self.tr("Page break (\\f)"))
57 self.singleComboItems.append(self.tr("Line feed (\\n)"))
58 self.singleComboItems.append(self.tr("Carriage return (\\r)"))
59 self.singleComboItems.append(self.tr("Horizontal tabulator (\\t)"))
60 self.singleComboItems.append(self.tr("Vertical tabulator (\\v)"))
61
62 self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
63 self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
64 self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
65
66 # generate dialog part for single characters
67 self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
68 self.singlesBoxLayout.setObjectName("singlesBoxLayout")
69 self.singlesBoxLayout.setSpacing(6)
70 self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
71 self.singlesBox.setLayout(self.singlesBoxLayout)
72 self.singlesView = QScrollArea(self.singlesBox)
73 self.singlesView.setObjectName("singlesView")
74 self.singlesBoxLayout.addWidget(self.singlesView)
75
76 self.singlesItemsBox = QWidget(self)
77 self.singlesView.setWidget(self.singlesItemsBox)
78 self.singlesItemsBox.setObjectName("singlesItemsBox")
79 self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
80 self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
81 self.singlesItemsBoxLayout.setSpacing(6)
82 self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
83 self.singlesEntries = []
84 self.__addSinglesLine()
85
86 hlayout0 = QHBoxLayout()
87 hlayout0.setContentsMargins(0, 0, 0, 0)
88 hlayout0.setSpacing(6)
89 hlayout0.setObjectName("hlayout0")
90 self.moreSinglesButton = QPushButton(
91 self.tr("Additional Entries"), self.singlesBox)
92 self.moreSinglesButton.setObjectName("moreSinglesButton")
93 hlayout0.addWidget(self.moreSinglesButton)
94 hspacer0 = QSpacerItem(
95 30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
96 hlayout0.addItem(hspacer0)
97 self.singlesBoxLayout.addLayout(hlayout0)
98 self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
99
100 # generate dialog part for character ranges
101 self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
102 self.rangesBoxLayout.setObjectName("rangesBoxLayout")
103 self.rangesBoxLayout.setSpacing(6)
104 self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
105 self.rangesBox.setLayout(self.rangesBoxLayout)
106 self.rangesView = QScrollArea(self.rangesBox)
107 self.rangesView.setObjectName("rangesView")
108 self.rangesBoxLayout.addWidget(self.rangesView)
109
110 self.rangesItemsBox = QWidget(self)
111 self.rangesView.setWidget(self.rangesItemsBox)
112 self.rangesItemsBox.setObjectName("rangesItemsBox")
113 self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
114 self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
115 self.rangesItemsBoxLayout.setSpacing(6)
116 self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
117 self.rangesEntries = []
118 self.__addRangesLine()
119
120 hlayout1 = QHBoxLayout()
121 hlayout1.setContentsMargins(0, 0, 0, 0)
122 hlayout1.setSpacing(6)
123 hlayout1.setObjectName("hlayout1")
124 self.moreRangesButton = QPushButton(
125 self.tr("Additional Entries"), self.rangesBox)
126 self.moreSinglesButton.setObjectName("moreRangesButton")
127 hlayout1.addWidget(self.moreRangesButton)
128 hspacer1 = QSpacerItem(
129 30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
130 hlayout1.addItem(hspacer1)
131 self.rangesBoxLayout.addLayout(hlayout1)
132 self.moreRangesButton.clicked.connect(self.__addRangesLine)
133
134 def __addSinglesLine(self):
135 """
136 Private slot to add a line of entry widgets for single characters.
137 """
138 hbox = QWidget(self.singlesItemsBox)
139 hboxLayout = QHBoxLayout(hbox)
140 hboxLayout.setContentsMargins(0, 0, 0, 0)
141 hboxLayout.setSpacing(6)
142 hbox.setLayout(hboxLayout)
143 cb1 = QComboBox(hbox)
144 cb1.setEditable(False)
145 cb1.addItems(self.comboItems)
146 cb1.addItems(self.singleComboItems)
147 hboxLayout.addWidget(cb1)
148 le1 = QLineEdit(hbox)
149 le1.setValidator(self.charValidator)
150 hboxLayout.addWidget(le1)
151 cb2 = QComboBox(hbox)
152 cb2.setEditable(False)
153 cb2.addItems(self.comboItems)
154 cb2.addItems(self.singleComboItems)
155 hboxLayout.addWidget(cb2)
156 le2 = QLineEdit(hbox)
157 le2.setValidator(self.charValidator)
158 hboxLayout.addWidget(le2)
159 self.singlesItemsBoxLayout.addWidget(hbox)
160
161 cb1.activated[int].connect(
162 lambda i: self.__singlesCharTypeSelected(i, cb1))
163 cb2.activated[int].connect(
164 lambda i: self.__singlesCharTypeSelected(i, cb2))
165 hbox.show()
166
167 self.singlesItemsBox.adjustSize()
168
169 self.singlesEntries.append([cb1, le1])
170 self.singlesEntries.append([cb2, le2])
171
172 def __addRangesLine(self):
173 """
174 Private slot to add a line of entry widgets for character ranges.
175 """
176 hbox = QWidget(self.rangesItemsBox)
177 hboxLayout = QHBoxLayout(hbox)
178 hboxLayout.setContentsMargins(0, 0, 0, 0)
179 hboxLayout.setSpacing(6)
180 hbox.setLayout(hboxLayout)
181 cb1 = QComboBox(hbox)
182 cb1.setEditable(False)
183 cb1.addItems(self.comboItems)
184 hboxLayout.addWidget(cb1)
185 l1 = QLabel(self.tr("Between:"), hbox)
186 hboxLayout.addWidget(l1)
187 le1 = QLineEdit(hbox)
188 le1.setValidator(self.charValidator)
189 hboxLayout.addWidget(le1)
190 l2 = QLabel(self.tr("And:"), hbox)
191 hboxLayout.addWidget(l2)
192 le2 = QLineEdit(hbox)
193 le2.setValidator(self.charValidator)
194 hboxLayout.addWidget(le2)
195 self.rangesItemsBoxLayout.addWidget(hbox)
196
197 cb1.activated[int].connect(
198 lambda i: self.__rangesCharTypeSelected(i, cb1))
199
200 hbox.show()
201
202 self.rangesItemsBox.adjustSize()
203
204 self.rangesEntries.append([cb1, le1, le2])
205
206 def __performSelectedAction(self, index, lineedit):
207 """
208 Private method performing some actions depending on the input.
209
210 @param index selected list index (integer)
211 @param lineedit line edit widget to act on (QLineEdit)
212 """
213 if index < 3:
214 lineedit.setEnabled(True)
215 if index == 0:
216 lineedit.setValidator(self.charValidator)
217 elif index == 1:
218 lineedit.setValidator(self.hexValidator)
219 elif index == 2:
220 lineedit.setValidator(self.octValidator)
221 elif index > 3:
222 lineedit.setEnabled(False)
223 lineedit.clear()
224
225 def __singlesCharTypeSelected(self, index, combo):
226 """
227 Private slot to handle the activated(int) signal of the single chars
228 combo boxes.
229
230 @param index selected list index
231 @type int
232 @param combo reference to the combo box
233 @type QComboBox
234 """
235 for entriesList in self.singlesEntries:
236 if combo == entriesList[0]:
237 self.__performSelectedAction(index, entriesList[1])
238 break
239
240 def __rangesCharTypeSelected(self, index, combo):
241 """
242 Private slot to handle the activated(int) signal of the char ranges
243 combo boxes.
244
245 @param index selected list index
246 @type int
247 @param combo reference to the combo box
248 @type QComboBox
249 """
250 for entriesList in self.rangesEntries:
251 if combo == entriesList[0]:
252 self.__performSelectedAction(index, entriesList[1])
253 self.__performSelectedAction(index, entriesList[2])
254 break
255
256 def __formatCharacter(self, index, char):
257 """
258 Private method to format the characters entered into the dialog.
259
260 @param index selected list index (integer)
261 @param char character string enetered into the dialog (string)
262 @return formated character string (string)
263 """
264 if index == 0:
265 return char
266 elif index == 1:
267 return "\\x{0}".format(char.lower())
268 elif index == 2:
269 return "\\0{0}".format(char)
270 else:
271 try:
272 return self.specialChars[index]
273 except KeyError:
274 return ""
275
276 def getCharacters(self):
277 """
278 Public method to return the character string assembled via the dialog.
279
280 @return formatted string for character classes (string)
281 """
282 regexp = ""
283
284 # negative character range
285 if self.negativeCheckBox.isChecked():
286 regexp += "^"
287
288 # predefined character ranges
289 if self.wordCharCheckBox.isChecked():
290 regexp += "\\w"
291 if self.nonWordCharCheckBox.isChecked():
292 regexp += "\\W"
293 if self.digitsCheckBox.isChecked():
294 regexp += "\\d"
295 if self.nonDigitsCheckBox.isChecked():
296 regexp += "\\D"
297 if self.whitespaceCheckBox.isChecked():
298 regexp += "\\s"
299 if self.nonWhitespaceCheckBox.isChecked():
300 regexp += "\\S"
301
302 # single characters
303 for entrieslist in self.singlesEntries:
304 index = entrieslist[0].currentIndex()
305 char = entrieslist[1].text()
306 regexp += self.__formatCharacter(index, char)
307
308 # character ranges
309 for entrieslist in self.rangesEntries:
310 if entrieslist[1].text() == "" or \
311 entrieslist[2].text() == "":
312 continue
313 index = entrieslist[0].currentIndex()
314 char1 = entrieslist[1].text()
315 char2 = entrieslist[2].text()
316 regexp += "{0}-{1}".format(
317 self.__formatCharacter(index, char1),
318 self.__formatCharacter(index, char2))
319
320 if regexp:
321 if (len(regexp) == 2 and
322 (regexp in self.predefinedClasses or
323 regexp in self.specialChars)) or \
324 len(regexp) == 1:
325 return regexp
326 else:
327 return "[{0}]".format(regexp)
328 else:
329 return ""

eric ide

mercurial