|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2010 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a widget to select a symbol in various formats. |
|
8 """ |
|
9 |
|
10 import sys |
|
11 import unicodedata |
|
12 import html.entities |
|
13 |
|
14 from PyQt6.QtCore import ( |
|
15 pyqtSlot, pyqtSignal, QAbstractTableModel, QModelIndex, Qt, |
|
16 QItemSelectionModel, QLocale |
|
17 ) |
|
18 from PyQt6.QtGui import QColor |
|
19 from PyQt6.QtWidgets import QWidget, QHeaderView, QAbstractItemView |
|
20 |
|
21 from EricWidgets.EricApplication import ericApp |
|
22 |
|
23 from .Ui_SymbolsWidget import Ui_SymbolsWidget |
|
24 |
|
25 import UI.PixmapCache |
|
26 import Preferences |
|
27 |
|
28 |
|
29 class SymbolsModel(QAbstractTableModel): |
|
30 """ |
|
31 Class implementing the model for the symbols widget. |
|
32 """ |
|
33 def __init__(self, parent=None): |
|
34 """ |
|
35 Constructor |
|
36 |
|
37 @param parent reference to the parent object (QObject) |
|
38 """ |
|
39 super().__init__(parent) |
|
40 |
|
41 self.__locale = QLocale() |
|
42 |
|
43 self.__headerData = [ |
|
44 self.tr("Code"), |
|
45 self.tr("Char"), |
|
46 self.tr("Hex"), |
|
47 self.tr("HTML"), |
|
48 self.tr("Name"), |
|
49 ] |
|
50 |
|
51 self.__isDark = ericApp().usesDarkPalette() |
|
52 |
|
53 self.__tables = [ |
|
54 # first last display name |
|
55 (0x0, 0x1f, self.tr("Control Characters")), |
|
56 (0x20, 0x7f, self.tr("Basic Latin")), |
|
57 (0x80, 0xff, self.tr("Latin-1 Supplement")), |
|
58 (0x100, 0x17f, self.tr("Latin Extended-A")), |
|
59 (0x180, 0x24f, self.tr("Latin Extended-B")), |
|
60 (0x250, 0x2af, self.tr("IPA Extensions")), |
|
61 (0x2b0, 0x2ff, self.tr("Spacing Modifier Letters")), |
|
62 (0x300, 0x36f, self.tr("Combining Diacritical Marks")), |
|
63 (0x370, 0x3ff, self.tr("Greek and Coptic")), |
|
64 (0x400, 0x4ff, self.tr("Cyrillic")), |
|
65 (0x500, 0x52f, self.tr("Cyrillic Supplement")), |
|
66 (0x530, 0x58f, self.tr("Armenian")), |
|
67 (0x590, 0x5ff, self.tr("Hebrew")), |
|
68 (0x600, 0x6ff, self.tr("Arabic")), |
|
69 (0x700, 0x74f, self.tr("Syriac")), |
|
70 (0x780, 0x7bf, self.tr("Thaana")), |
|
71 (0x7c0, 0x7ff, self.tr("N'Ko")), |
|
72 (0x800, 0x83f, self.tr("Samaritan")), |
|
73 (0x840, 0x85f, self.tr("Mandaic")), |
|
74 (0x8a0, 0x8ff, self.tr("Arabic Extended-A")), |
|
75 (0x900, 0x97f, self.tr("Devanagari")), |
|
76 (0x980, 0x9ff, self.tr("Bengali")), |
|
77 (0xa00, 0xa7f, self.tr("Gurmukhi")), |
|
78 (0xa80, 0xaff, self.tr("Gujarati")), |
|
79 (0xb00, 0xb7f, self.tr("Oriya")), |
|
80 (0xb80, 0xbff, self.tr("Tamil")), |
|
81 (0xc00, 0xc7f, self.tr("Telugu")), |
|
82 (0xc80, 0xcff, self.tr("Kannada")), |
|
83 (0xd00, 0xd7f, self.tr("Malayalam")), |
|
84 (0xd80, 0xdff, self.tr("Sinhala")), |
|
85 (0xe00, 0xe7f, self.tr("Thai")), |
|
86 (0xe80, 0xeff, self.tr("Lao")), |
|
87 (0xf00, 0xfff, self.tr("Tibetan")), |
|
88 (0x1000, 0x109f, self.tr("Myanmar")), |
|
89 (0x10a0, 0x10ff, self.tr("Georgian")), |
|
90 (0x1100, 0x11ff, self.tr("Hangul Jamo")), |
|
91 (0x1200, 0x137f, self.tr("Ethiopic")), |
|
92 (0x1380, 0x139f, self.tr("Ethiopic Supplement")), |
|
93 (0x13a0, 0x13ff, self.tr("Cherokee")), |
|
94 (0x1400, 0x167f, |
|
95 self.tr("Unified Canadian Aboriginal Syllabics")), |
|
96 (0x1680, 0x169f, self.tr("Ogham")), |
|
97 (0x16a0, 0x16ff, self.tr("Runic")), |
|
98 (0x1700, 0x171f, self.tr("Tagalog")), |
|
99 (0x1720, 0x173f, self.tr("Hanunoo")), |
|
100 (0x1740, 0x175f, self.tr("Buhid")), |
|
101 (0x1760, 0x177f, self.tr("Tagbanwa")), |
|
102 (0x1780, 0x17ff, self.tr("Khmer")), |
|
103 (0x1800, 0x18af, self.tr("Mongolian")), |
|
104 (0x18b0, 0x18ff, |
|
105 self.tr("Unified Canadian Aboriginal Syllabics Extended")), |
|
106 (0x1900, 0x194f, self.tr("Limbu")), |
|
107 (0x1950, 0x197f, self.tr("Tai Le")), |
|
108 (0x19e0, 0x19ff, self.tr("Khmer Symbols")), |
|
109 (0x1a00, 0x1a1f, self.tr("Buginese")), |
|
110 (0x1a20, 0x1aaf, self.tr("Tai Tham")), |
|
111 (0x1b00, 0x1b7f, self.tr("Balinese")), |
|
112 (0x1b80, 0x1bbf, self.tr("Sundanese")), |
|
113 (0x1bc0, 0x1bff, self.tr("Batak")), |
|
114 (0x1c00, 0x1c4f, self.tr("Lepcha")), |
|
115 (0x1c50, 0x1c7f, self.tr("Ol Chiki")), |
|
116 (0x1cc0, 0x1ccf, self.tr("Sundanese Supplement")), |
|
117 (0x1cd0, 0x1cff, self.tr("Vedic Extensions")), |
|
118 (0x1d00, 0x1d7f, self.tr("Phonetic Extensions")), |
|
119 (0x1d80, 0x1dbf, self.tr("Phonetic Extensions Supplement")), |
|
120 (0x1dc0, 0x1dff, |
|
121 self.tr("Combining Diacritical Marks Supplement")), |
|
122 (0x1e00, 0x1eff, self.tr("Latin Extended Additional")), |
|
123 (0x1f00, 0x1fff, self.tr("Greek Extended")), |
|
124 (0x2000, 0x206f, self.tr("General Punctuation")), |
|
125 (0x2070, 0x209f, self.tr("Superscripts and Subscripts")), |
|
126 (0x20a0, 0x20cf, self.tr("Currency Symbols")), |
|
127 (0x20d0, 0x20ff, self.tr("Combining Diacritical Marks")), |
|
128 (0x2100, 0x214f, self.tr("Letterlike Symbols")), |
|
129 (0x2150, 0x218f, self.tr("Number Forms")), |
|
130 (0x2190, 0x21ff, self.tr("Arcolumns")), |
|
131 (0x2200, 0x22ff, self.tr("Mathematical Operators")), |
|
132 (0x2300, 0x23ff, self.tr("Miscellaneous Technical")), |
|
133 (0x2400, 0x243f, self.tr("Control Pictures")), |
|
134 (0x2440, 0x245f, self.tr("Optical Character Recognition")), |
|
135 (0x2460, 0x24ff, self.tr("Enclosed Alphanumerics")), |
|
136 (0x2500, 0x257f, self.tr("Box Drawing")), |
|
137 (0x2580, 0x259f, self.tr("Block Elements")), |
|
138 (0x25A0, 0x25ff, self.tr("Geometric Shapes")), |
|
139 (0x2600, 0x26ff, self.tr("Miscellaneous Symbols")), |
|
140 (0x2700, 0x27bf, self.tr("Dingbats")), |
|
141 (0x27c0, 0x27ef, |
|
142 self.tr("Miscellaneous Mathematical Symbols-A")), |
|
143 (0x27f0, 0x27ff, self.tr("Supplement Arcolumns-A")), |
|
144 (0x2800, 0x28ff, self.tr("Braille Patterns")), |
|
145 (0x2900, 0x297f, self.tr("Supplement Arcolumns-B")), |
|
146 (0x2980, 0x29ff, |
|
147 self.tr("Miscellaneous Mathematical Symbols-B")), |
|
148 (0x2a00, 0x2aff, |
|
149 self.tr("Supplemental Mathematical Operators")), |
|
150 (0x2b00, 0x2bff, |
|
151 self.tr("Miscellaneous Symbols and Arcolumns")), |
|
152 (0x2c00, 0x2c5f, self.tr("Glagolitic")), |
|
153 (0x2c60, 0x2c7f, self.tr("Latin Extended-C")), |
|
154 (0x2c80, 0x2cff, self.tr("Coptic")), |
|
155 (0x2d00, 0x2d2f, self.tr("Georgian Supplement")), |
|
156 (0x2d30, 0x2d7f, self.tr("Tifinagh")), |
|
157 (0x2d80, 0x2ddf, self.tr("Ethiopic Extended")), |
|
158 (0x2de0, 0x2dff, self.tr("Cyrillic Extended-A")), |
|
159 (0x2e00, 0x2e7f, self.tr("Supplemental Punctuation")), |
|
160 (0x2e80, 0x2eff, self.tr("CJK Radicals Supplement")), |
|
161 (0x2f00, 0x2fdf, self.tr("KangXi Radicals")), |
|
162 (0x2ff0, 0x2fff, self.tr("Ideographic Description Chars")), |
|
163 (0x3000, 0x303f, self.tr("CJK Symbols and Punctuation")), |
|
164 (0x3040, 0x309f, self.tr("Hiragana")), |
|
165 (0x30a0, 0x30ff, self.tr("Katakana")), |
|
166 (0x3100, 0x312f, self.tr("Bopomofo")), |
|
167 (0x3130, 0x318f, self.tr("Hangul Compatibility Jamo")), |
|
168 (0x3190, 0x319f, self.tr("Kanbun")), |
|
169 (0x31a0, 0x31bf, self.tr("Bopomofo Extended")), |
|
170 (0x31c0, 0x31ef, self.tr("CJK Strokes")), |
|
171 (0x31f0, 0x31ff, self.tr("Katakana Phonetic Extensions")), |
|
172 (0x3200, 0x32ff, self.tr("Enclosed CJK Letters and Months")), |
|
173 (0x3300, 0x33ff, self.tr("CJK Compatibility")), |
|
174 (0x3400, 0x4dbf, self.tr("CJK Unified Ideogr. Ext. A")), |
|
175 (0x4dc0, 0x4dff, self.tr("Yijing Hexagram Symbols")), |
|
176 (0x4e00, 0x9fff, self.tr("CJK Unified Ideographs")), |
|
177 (0xa000, 0xa48f, self.tr("Yi Syllables")), |
|
178 (0xa490, 0xa4cf, self.tr("Yi Radicals")), |
|
179 (0xa4d0, 0xa4ff, self.tr("Lisu")), |
|
180 (0xa500, 0xa63f, self.tr("Vai")), |
|
181 (0xa640, 0xa69f, self.tr("Cyrillic Extended-B")), |
|
182 (0xa6a0, 0xa6ff, self.tr("Bamum")), |
|
183 (0xa700, 0xa71f, self.tr("Modifier Tone Letters")), |
|
184 (0xa720, 0xa7ff, self.tr("Latin Extended-D")), |
|
185 (0xa800, 0xa82f, self.tr("Syloti Nagri")), |
|
186 (0xa830, 0xa83f, self.tr("Common Indic Number Forms")), |
|
187 (0xa840, 0xa87f, self.tr("Phags-pa")), |
|
188 (0xa880, 0xa8df, self.tr("Saurashtra")), |
|
189 (0xa8e0, 0xa8ff, self.tr("Devanagari Extended")), |
|
190 (0xa900, 0xa92f, self.tr("Kayah Li")), |
|
191 (0xa930, 0xa95f, self.tr("Rejang")), |
|
192 (0xa960, 0xa97f, self.tr("Hangul Jamo Extended-A")), |
|
193 (0xa980, 0xa9df, self.tr("Javanese")), |
|
194 (0xaa00, 0xaa5f, self.tr("Cham")), |
|
195 (0xaa60, 0xaa7f, self.tr("Myanmar Extended-A")), |
|
196 (0xaa80, 0xaadf, self.tr("Tai Viet")), |
|
197 (0xaae0, 0xaaff, self.tr("Meetei Mayek Extensions")), |
|
198 (0xab00, 0xab2f, self.tr("Ethiopic Extended-A")), |
|
199 (0xabc0, 0xabff, self.tr("Meetei Mayek")), |
|
200 (0xac00, 0xd7af, self.tr("Hangul Syllables")), |
|
201 (0xd7b0, 0xd7ff, self.tr("Hangul Jamo Extended-B")), |
|
202 (0xd800, 0xdb7f, self.tr("High Surrogates")), |
|
203 (0xdb80, 0xdbff, self.tr("High Private Use Surrogates")), |
|
204 (0xdc00, 0xdfff, self.tr("Low Surrogates")), |
|
205 (0xe000, 0xf8ff, self.tr("Private Use")), |
|
206 (0xf900, 0xfaff, self.tr("CJK Compatibility Ideographs")), |
|
207 (0xfb00, 0xfb4f, self.tr("Alphabetic Presentation Forms")), |
|
208 (0xfb50, 0xfdff, self.tr("Arabic Presentation Forms-A")), |
|
209 (0xfe00, 0xfe0f, self.tr("Variation Selectors")), |
|
210 (0xfe10, 0xfe1f, self.tr("Vertical Forms")), |
|
211 (0xfe20, 0xfe2f, self.tr("Combining Half Marks")), |
|
212 (0xfe30, 0xfe4f, self.tr("CJK Compatibility Forms")), |
|
213 (0xfe50, 0xfe6f, self.tr("Small Form Variants")), |
|
214 (0xfe70, 0xfeff, self.tr("Arabic Presentation Forms-B")), |
|
215 (0xff00, 0xffef, self.tr("Half- and Fullwidth Forms")), |
|
216 (0xfff0, 0xffff, self.tr("Specials")), |
|
217 ] |
|
218 if sys.maxunicode > 0xffff: |
|
219 self.__tables.extend([ |
|
220 (0x10000, 0x1007f, self.tr("Linear B Syllabary")), |
|
221 (0x10080, 0x100ff, self.tr("Linear B Ideograms")), |
|
222 (0x10100, 0x1013f, self.tr("Aegean Numbers")), |
|
223 (0x10140, 0x1018f, self.tr("Ancient Greek Numbers")), |
|
224 (0x10190, 0x101cf, self.tr("Ancient Symbols")), |
|
225 (0x101d0, 0x101ff, self.tr("Phaistos Disc")), |
|
226 (0x10280, 0x1029f, self.tr("Lycian")), |
|
227 (0x102a0, 0x102df, self.tr("Carian")), |
|
228 (0x10300, 0x1032f, self.tr("Old Italic")), |
|
229 (0x10330, 0x1034f, self.tr("Gothic")), |
|
230 (0x10380, 0x1039f, self.tr("Ugaritic")), |
|
231 (0x103a0, 0x103df, self.tr("Old Persian")), |
|
232 (0x10400, 0x1044f, self.tr("Deseret")), |
|
233 (0x10450, 0x1047f, self.tr("Shavian")), |
|
234 (0x10480, 0x104af, self.tr("Osmanya")), |
|
235 (0x10800, 0x1083f, self.tr("Cypriot Syllabary")), |
|
236 (0x10840, 0x1085f, self.tr("Imperial Aramaic")), |
|
237 (0x10900, 0x1091f, self.tr("Phoenician")), |
|
238 (0x10920, 0x1093f, self.tr("Lydian")), |
|
239 (0x10980, 0x1099f, self.tr("Meroitic Hieroglyphs")), |
|
240 (0x109a0, 0x109ff, self.tr("Meroitic Cursive")), |
|
241 (0x10a00, 0x10a5f, self.tr("Kharoshthi")), |
|
242 (0x10a60, 0x10a7f, self.tr("Old South Arabian")), |
|
243 (0x10b00, 0x10b3f, self.tr("Avestan")), |
|
244 (0x10b40, 0x10b5f, self.tr("Inscriptional Parthian")), |
|
245 (0x10b60, 0x10b7f, self.tr("Inscriptional Pahlavi")), |
|
246 (0x10c00, 0x10c4f, self.tr("Old Turkic")), |
|
247 (0x10e60, 0x10e7f, self.tr("Rumi Numeral Symbols")), |
|
248 (0x11000, 0x1107f, self.tr("Brahmi")), |
|
249 (0x11080, 0x110cf, self.tr("Kaithi")), |
|
250 (0x110d0, 0x110ff, self.tr("Sora Sompeng")), |
|
251 (0x11100, 0x1114f, self.tr("Chakma")), |
|
252 (0x11180, 0x111df, self.tr("Sharada")), |
|
253 (0x11680, 0x116cf, self.tr("Takri")), |
|
254 (0x12000, 0x123ff, self.tr("Cuneiform")), |
|
255 (0x12400, 0x1247f, |
|
256 self.tr("Cuneiform Numbers and Punctuation")), |
|
257 (0x13000, 0x1342f, self.tr("Egyptian Hieroglyphs")), |
|
258 (0x16800, 0x16a3f, self.tr("Bamum Supplement")), |
|
259 (0x16f00, 0x16f9f, self.tr("Miao")), |
|
260 (0x1b000, 0x1b0ff, self.tr("Kana Supplement")), |
|
261 (0x1d000, 0x1d0ff, self.tr("Byzantine Musical Symbols")), |
|
262 (0x1d100, 0x1d1ff, self.tr("Musical Symbols")), |
|
263 (0x1d200, 0x1d24f, |
|
264 self.tr("Ancient Greek Musical Notation")), |
|
265 (0x1d300, 0x1d35f, self.tr("Tai Xuan Jing Symbols")), |
|
266 (0x1d360, 0x1d37f, |
|
267 self.tr("Counting Rod Numerals")), |
|
268 (0x1d400, 0x1d7ff, |
|
269 self.tr("Mathematical Alphanumeric Symbols")), |
|
270 (0x1ee00, 0x1eeff, |
|
271 self.tr("Arabic Mathematical Alphabetic Symbols")), |
|
272 (0x1f000, 0x1f02f, self.tr("Mahjong Tiles")), |
|
273 (0x1f030, 0x1f09f, self.tr("Domino Tiles")), |
|
274 (0x1f0a0, 0x1f0ff, self.tr("Playing Cards")), |
|
275 (0x1f100, 0x1f1ff, |
|
276 self.tr("Enclosed Alphanumeric Supplement")), |
|
277 (0x1f200, 0x1f2ff, |
|
278 self.tr("Enclosed Ideographic Supplement")), |
|
279 (0x1f300, 0x1f5ff, |
|
280 self.tr("Miscellaneous Symbols And Pictographs")), |
|
281 (0x1f600, 0x1f64f, self.tr("Emoticons")), |
|
282 (0x1f680, 0x1f6ff, self.tr("Transport And Map Symbols")), |
|
283 (0x1f700, 0x1f77f, self.tr("Alchemical Symbols")), |
|
284 (0x20000, 0x2a6df, self.tr("CJK Unified Ideogr. Ext. B")), |
|
285 (0x2a700, 0x2b73f, |
|
286 self.tr("CJK Unified Ideographs Extension C")), |
|
287 (0x2b740, 0x2b81f, |
|
288 self.tr("CJK Unified Ideographs Extension D")), |
|
289 (0x2f800, 0x2fa1f, |
|
290 self.tr("CJK Compatapility Ideogr. Suppl.")), |
|
291 (0xe0000, 0xe007f, self.tr("Tags")), |
|
292 (0xe0100, 0xe01ef, |
|
293 self.tr("Variation Selectors Supplement")), |
|
294 (0xf0000, 0xfffff, |
|
295 self.tr("Supplementary Private Use Area-A")), |
|
296 (0x100000, 0x10ffff, |
|
297 self.tr("Supplementary Private Use Area-B")), |
|
298 ]) |
|
299 self.__currentTableIndex = 0 |
|
300 |
|
301 def getTableNames(self): |
|
302 """ |
|
303 Public method to get a list of table names. |
|
304 |
|
305 @return list of table names (list of strings) |
|
306 """ |
|
307 return [table[2] for table in self.__tables] |
|
308 |
|
309 def getTableBoundaries(self, index): |
|
310 """ |
|
311 Public method to get the first and last character position |
|
312 of the given table. |
|
313 |
|
314 @param index index of the character table (integer) |
|
315 @return first and last character position (integer, integer) |
|
316 """ |
|
317 return self.__tables[index][0], self.__tables[index][1] |
|
318 |
|
319 def getTableIndex(self): |
|
320 """ |
|
321 Public method to get the current table index. |
|
322 |
|
323 @return current table index (integer) |
|
324 """ |
|
325 return self.__currentTableIndex |
|
326 |
|
327 def selectTable(self, index): |
|
328 """ |
|
329 Public method to select the shown character table. |
|
330 |
|
331 @param index index of the character table (integer) |
|
332 """ |
|
333 self.beginResetModel() |
|
334 self.__currentTableIndex = index |
|
335 self.endResetModel() |
|
336 |
|
337 def headerData(self, section, orientation, |
|
338 role=Qt.ItemDataRole.DisplayRole): |
|
339 """ |
|
340 Public method to get header data from the model. |
|
341 |
|
342 @param section section number (integer) |
|
343 @param orientation orientation (Qt.Orientation) |
|
344 @param role role of the data to retrieve (Qt.ItemDataRole) |
|
345 @return requested data |
|
346 """ |
|
347 if ( |
|
348 orientation == Qt.Orientation.Horizontal and |
|
349 role == Qt.ItemDataRole.DisplayRole |
|
350 ): |
|
351 return self.__headerData[section] |
|
352 |
|
353 return QAbstractTableModel.headerData(self, section, orientation, role) |
|
354 |
|
355 def data(self, index, role=Qt.ItemDataRole.DisplayRole): |
|
356 """ |
|
357 Public method to get data from the model. |
|
358 |
|
359 @param index index to get data for (QModelIndex) |
|
360 @param role role of the data to retrieve (integer) |
|
361 @return requested data |
|
362 """ |
|
363 symbolId = self.__tables[self.__currentTableIndex][0] + index.row() |
|
364 |
|
365 if role == Qt.ItemDataRole.DisplayRole: |
|
366 col = index.column() |
|
367 if col == 0: |
|
368 return self.__locale.toString(symbolId) |
|
369 elif col == 1: |
|
370 return chr(symbolId) |
|
371 elif col == 2: |
|
372 return "0x{0:04x}".format(symbolId) |
|
373 elif col == 3: |
|
374 if symbolId in html.entities.codepoint2name: |
|
375 return "&{0};".format( |
|
376 html.entities.codepoint2name[symbolId]) |
|
377 elif col == 4: |
|
378 return unicodedata.name(chr(symbolId), '').title() |
|
379 |
|
380 if ( |
|
381 role == Qt.ItemDataRole.BackgroundRole and |
|
382 index.column() == 0 |
|
383 ): |
|
384 if self.__isDark: |
|
385 return QColor("#4d4d4d") |
|
386 else: |
|
387 return QColor(Qt.GlobalColor.lightGray) |
|
388 |
|
389 if role == Qt.ItemDataRole.ForegroundRole: |
|
390 char = chr(symbolId) |
|
391 if self.__isDark: |
|
392 if self.__isDigit(char): |
|
393 return QColor("#8787ff") |
|
394 elif self.__isLetter(char): |
|
395 return QColor("#87ff87") |
|
396 elif self.__isMark(char): |
|
397 return QColor("#ff8787") |
|
398 elif self.__isSymbol(char): |
|
399 return QColor("#ffc060") |
|
400 elif self.__isPunct(char): |
|
401 return QColor("#d080ff") |
|
402 else: |
|
403 return QColor(Qt.GlobalColor.lightGray) |
|
404 else: |
|
405 if self.__isDigit(char): |
|
406 return QColor(Qt.GlobalColor.darkBlue) |
|
407 elif self.__isLetter(char): |
|
408 return QColor(Qt.GlobalColor.darkGreen) |
|
409 elif self.__isMark(char): |
|
410 return QColor(Qt.GlobalColor.darkRed) |
|
411 elif self.__isSymbol(char): |
|
412 return QColor(Qt.GlobalColor.darkYellow) |
|
413 elif self.__isPunct(char): |
|
414 return QColor(Qt.GlobalColor.darkMagenta) |
|
415 else: |
|
416 return QColor(Qt.GlobalColor.darkGray) |
|
417 |
|
418 if ( |
|
419 role == Qt.ItemDataRole.TextAlignmentRole and |
|
420 index.column() in [0, 1, 3] |
|
421 ): |
|
422 return Qt.AlignmentFlag.AlignHCenter.value |
|
423 |
|
424 return None |
|
425 |
|
426 def columnCount(self, parent): |
|
427 """ |
|
428 Public method to get the number of columns of the model. |
|
429 |
|
430 @param parent parent index (QModelIndex) |
|
431 @return number of columns (integer) |
|
432 """ |
|
433 if parent.column() > 0: |
|
434 return 0 |
|
435 else: |
|
436 return len(self.__headerData) |
|
437 |
|
438 def rowCount(self, parent): |
|
439 """ |
|
440 Public method to get the number of rows of the model. |
|
441 |
|
442 @param parent parent index (QModelIndex) |
|
443 @return number of columns (integer) |
|
444 """ |
|
445 if parent.isValid(): |
|
446 return 0 |
|
447 else: |
|
448 first, last = self.__tables[self.__currentTableIndex][:2] |
|
449 return last - first + 1 |
|
450 |
|
451 def __isDigit(self, char): |
|
452 """ |
|
453 Private method to check, if a character is a digit. |
|
454 |
|
455 @param char character to test (one character string) |
|
456 @return flag indicating a digit (boolean) |
|
457 """ |
|
458 return unicodedata.category(str(char)) == "Nd" |
|
459 |
|
460 def __isLetter(self, char): |
|
461 """ |
|
462 Private method to check, if a character is a letter. |
|
463 |
|
464 @param char character to test (one character string) |
|
465 @return flag indicating a letter (boolean) |
|
466 """ |
|
467 return unicodedata.category(str(char)) in ["Lu", "Ll", "Lt", "Lm", |
|
468 "Lo"] |
|
469 |
|
470 def __isMark(self, char): |
|
471 """ |
|
472 Private method to check, if a character is a mark character. |
|
473 |
|
474 @param char character to test (one character string) |
|
475 @return flag indicating a mark character (boolean) |
|
476 """ |
|
477 return unicodedata.category(str(char)) in ["Mn", "Mc", "Me"] |
|
478 |
|
479 def __isSymbol(self, char): |
|
480 """ |
|
481 Private method to check, if a character is a symbol. |
|
482 |
|
483 @param char character to test (one character string) |
|
484 @return flag indicating a symbol (boolean) |
|
485 """ |
|
486 return unicodedata.category(str(char)) in ["Sm", "Sc", "Sk", "So"] |
|
487 |
|
488 def __isPunct(self, char): |
|
489 """ |
|
490 Private method to check, if a character is a punctuation character. |
|
491 |
|
492 @param char character to test (one character string) |
|
493 @return flag indicating a punctuation character (boolean) |
|
494 """ |
|
495 return unicodedata.category(str(char)) in ["Pc", "Pd", "Ps", "Pe", |
|
496 "Pi", "Pf", "Po"] |
|
497 |
|
498 def getLocale(self): |
|
499 """ |
|
500 Public method to get the used locale. |
|
501 |
|
502 @return used locale |
|
503 @rtype QLocale |
|
504 """ |
|
505 return self.__locale |
|
506 |
|
507 |
|
508 class SymbolsWidget(QWidget, Ui_SymbolsWidget): |
|
509 """ |
|
510 Class implementing a widget to select a symbol in various formats. |
|
511 |
|
512 @signal insertSymbol(str) emitted after the user has selected a symbol |
|
513 """ |
|
514 insertSymbol = pyqtSignal(str) |
|
515 |
|
516 def __init__(self, parent=None): |
|
517 """ |
|
518 Constructor |
|
519 |
|
520 @param parent reference to the parent widget (QWidget) |
|
521 """ |
|
522 super().__init__(parent) |
|
523 self.setupUi(self) |
|
524 |
|
525 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
|
526 |
|
527 self.__model = SymbolsModel(self) |
|
528 self.symbolsTable.setModel(self.__model) |
|
529 self.symbolsTable.selectionModel().currentRowChanged.connect( |
|
530 self.__currentRowChanged) |
|
531 |
|
532 self.symbolsTable.horizontalHeader().setSectionResizeMode( |
|
533 QHeaderView.ResizeMode.Fixed) |
|
534 fm = self.fontMetrics() |
|
535 try: |
|
536 em = fm.horizontalAdvance("M") |
|
537 except AttributeError: |
|
538 em = fm.width("M") |
|
539 self.symbolsTable.horizontalHeader().resizeSection(0, em * 5) |
|
540 self.symbolsTable.horizontalHeader().resizeSection(1, em * 5) |
|
541 self.symbolsTable.horizontalHeader().resizeSection(2, em * 6) |
|
542 self.symbolsTable.horizontalHeader().resizeSection(3, em * 8) |
|
543 self.symbolsTable.horizontalHeader().resizeSection(4, em * 85) |
|
544 self.symbolsTable.verticalHeader().setDefaultSectionSize( |
|
545 fm.height() + 4) |
|
546 |
|
547 tableIndex = int( |
|
548 Preferences.getSettings().value("Symbols/CurrentTable", 1)) |
|
549 self.tableCombo.addItems(self.__model.getTableNames()) |
|
550 self.tableCombo.setCurrentIndex(tableIndex) |
|
551 |
|
552 index = self.__model.index( |
|
553 int(Preferences.getSettings().value("Symbols/Top", 0)), |
|
554 0) |
|
555 self.symbolsTable.scrollTo( |
|
556 index, QAbstractItemView.ScrollHint.PositionAtTop) |
|
557 self.symbolsTable.selectionModel().setCurrentIndex( |
|
558 index, |
|
559 QItemSelectionModel.SelectionFlag.SelectCurrent | |
|
560 QItemSelectionModel.SelectionFlag.Rows |
|
561 ) |
|
562 |
|
563 @pyqtSlot(QModelIndex) |
|
564 def on_symbolsTable_activated(self, index): |
|
565 """ |
|
566 Private slot to signal the selection of a symbol. |
|
567 |
|
568 @param index index of the selected symbol (QModelIndex) |
|
569 """ |
|
570 txt = self.__model.data(index) |
|
571 if txt: |
|
572 self.insertSymbol.emit(txt) |
|
573 |
|
574 @pyqtSlot() |
|
575 def on_symbolSpinBox_editingFinished(self): |
|
576 """ |
|
577 Private slot to move the table to the entered symbol id. |
|
578 """ |
|
579 symbolId = self.symbolSpinBox.value() |
|
580 first, last = self.__model.getTableBoundaries( |
|
581 self.__model.getTableIndex()) |
|
582 row = symbolId - first |
|
583 self.symbolsTable.selectRow(row) |
|
584 self.symbolsTable.scrollTo( |
|
585 self.__model.index(row, 0), |
|
586 QAbstractItemView.ScrollHint.PositionAtCenter) |
|
587 |
|
588 @pyqtSlot(int) |
|
589 def on_tableCombo_currentIndexChanged(self, index): |
|
590 """ |
|
591 Private slot to select the current character table. |
|
592 |
|
593 @param index index of the character table (integer) |
|
594 """ |
|
595 self.symbolsTable.setUpdatesEnabled(False) |
|
596 self.__model.selectTable(index) |
|
597 self.symbolsTable.setUpdatesEnabled(True) |
|
598 self.symbolsTable.resizeColumnsToContents() |
|
599 |
|
600 first, last = self.__model.getTableBoundaries(index) |
|
601 self.symbolSpinBox.setMinimum(first) |
|
602 self.symbolSpinBox.setMaximum(last) |
|
603 |
|
604 Preferences.getSettings().setValue("Symbols/CurrentTable", index) |
|
605 |
|
606 def __currentRowChanged(self, current, previous): |
|
607 """ |
|
608 Private slot recording the currently selected row. |
|
609 |
|
610 @param current current index (QModelIndex) |
|
611 @param previous previous current index (QModelIndex) |
|
612 """ |
|
613 Preferences.getSettings().setValue("Symbols/Top", current.row()) |
|
614 self.symbolSpinBox.setValue(self.__model.getLocale().toInt( |
|
615 self.__model.data(self.__model.index(current.row(), 0)))[0]) |