|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2006 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Editor Highlighting Styles configuration page. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 from PyQt5.QtCore import pyqtSlot, Qt, QFileInfo, QFile, QIODevice |
|
13 from PyQt5.QtGui import QPalette, QFont |
|
14 from PyQt5.QtWidgets import QColorDialog, QFontDialog, QInputDialog, QMenu, \ |
|
15 QTreeWidgetItem, QDialog |
|
16 |
|
17 from .ConfigurationPageBase import ConfigurationPageBase |
|
18 from .Ui_EditorHighlightingStylesPage import Ui_EditorHighlightingStylesPage |
|
19 from ..SubstyleDefinitionDialog import SubstyleDefinitionDialog |
|
20 |
|
21 from E5Gui import E5MessageBox, E5FileDialog |
|
22 |
|
23 from Globals import qVersionTuple |
|
24 |
|
25 import UI.PixmapCache |
|
26 |
|
27 try: |
|
28 MonospacedFontsOption = QFontDialog.MonospacedFonts |
|
29 except AttributeError: |
|
30 MonospacedFontsOption = QFontDialog.FontDialogOptions(0x10) |
|
31 NoFontsOption = QFontDialog.FontDialogOptions(0) |
|
32 |
|
33 |
|
34 class EditorHighlightingStylesPage(ConfigurationPageBase, |
|
35 Ui_EditorHighlightingStylesPage): |
|
36 """ |
|
37 Class implementing the Editor Highlighting Styles configuration page. |
|
38 """ |
|
39 FAMILYONLY = 0 |
|
40 SIZEONLY = 1 |
|
41 FAMILYANDSIZE = 2 |
|
42 FONT = 99 |
|
43 |
|
44 StyleRole = Qt.UserRole + 1 |
|
45 SubstyleRole = Qt.UserRole + 2 |
|
46 |
|
47 def __init__(self, lexers): |
|
48 """ |
|
49 Constructor |
|
50 |
|
51 @param lexers reference to the lexers dictionary |
|
52 """ |
|
53 super(EditorHighlightingStylesPage, self).__init__() |
|
54 self.setupUi(self) |
|
55 self.setObjectName("EditorHighlightingStylesPage") |
|
56 |
|
57 self.defaultSubstylesButton.setIcon(UI.PixmapCache.getIcon("editUndo")) |
|
58 self.addSubstyleButton.setIcon(UI.PixmapCache.getIcon("plus")) |
|
59 self.deleteSubstyleButton.setIcon(UI.PixmapCache.getIcon("minus")) |
|
60 self.editSubstyleButton.setIcon(UI.PixmapCache.getIcon("edit")) |
|
61 self.copySubstyleButton.setIcon(UI.PixmapCache.getIcon("editCopy")) |
|
62 |
|
63 if qVersionTuple() < (5, 0, 0): |
|
64 self.monospacedButton.setChecked(False) |
|
65 self.monospacedButton.hide() |
|
66 |
|
67 self.__fontButtonMenu = QMenu() |
|
68 act = self.__fontButtonMenu.addAction(self.tr("Font")) |
|
69 act.setData(self.FONT) |
|
70 self.__fontButtonMenu.addSeparator() |
|
71 act = self.__fontButtonMenu.addAction( |
|
72 self.tr("Family and Size only")) |
|
73 act.setData(self.FAMILYANDSIZE) |
|
74 act = self.__fontButtonMenu.addAction(self.tr("Family only")) |
|
75 act.setData(self.FAMILYONLY) |
|
76 act = self.__fontButtonMenu.addAction(self.tr("Size only")) |
|
77 act.setData(self.SIZEONLY) |
|
78 self.__fontButtonMenu.triggered.connect(self.__fontButtonMenuTriggered) |
|
79 self.fontButton.setMenu(self.__fontButtonMenu) |
|
80 |
|
81 self.__allFontsButtonMenu = QMenu() |
|
82 act = self.__allFontsButtonMenu.addAction(self.tr("Font")) |
|
83 act.setData(self.FONT) |
|
84 self.__allFontsButtonMenu.addSeparator() |
|
85 act = self.__allFontsButtonMenu.addAction( |
|
86 self.tr("Family and Size only")) |
|
87 act.setData(self.FAMILYANDSIZE) |
|
88 act = self.__allFontsButtonMenu.addAction(self.tr("Family only")) |
|
89 act.setData(self.FAMILYONLY) |
|
90 act = self.__allFontsButtonMenu.addAction(self.tr("Size only")) |
|
91 act.setData(self.SIZEONLY) |
|
92 self.__allFontsButtonMenu.triggered.connect( |
|
93 self.__allFontsButtonMenuTriggered) |
|
94 self.allFontsButton.setMenu(self.__allFontsButtonMenu) |
|
95 |
|
96 self.lexer = None |
|
97 self.lexers = lexers |
|
98 |
|
99 # set initial values |
|
100 import QScintilla.Lexers |
|
101 languages = sorted([''] + list(self.lexers.keys())) |
|
102 for language in languages: |
|
103 self.lexerLanguageComboBox.addItem( |
|
104 QScintilla.Lexers.getLanguageIcon(language, False), |
|
105 language) |
|
106 self.on_lexerLanguageComboBox_activated("") |
|
107 |
|
108 def save(self): |
|
109 """ |
|
110 Public slot to save the Editor Highlighting Styles configuration. |
|
111 """ |
|
112 for lexer in list(self.lexers.values()): |
|
113 lexer.writeSettings() |
|
114 |
|
115 @pyqtSlot(str) |
|
116 def on_lexerLanguageComboBox_activated(self, language): |
|
117 """ |
|
118 Private slot to fill the style combo of the source page. |
|
119 |
|
120 @param language The lexer language (string) |
|
121 """ |
|
122 self.styleElementList.clear() |
|
123 self.styleGroup.setEnabled(False) |
|
124 self.lexer = None |
|
125 |
|
126 self.exportCurrentButton.setEnabled(language != "") |
|
127 self.importCurrentButton.setEnabled(language != "") |
|
128 |
|
129 if not language: |
|
130 return |
|
131 |
|
132 try: |
|
133 self.lexer = self.lexers[language] |
|
134 except KeyError: |
|
135 return |
|
136 |
|
137 self.styleGroup.setEnabled(True) |
|
138 for description, styleNo, subStyleNo in self.lexer.getStyles(): |
|
139 if subStyleNo >= 0: |
|
140 parent = self.styleElementList.findItems( |
|
141 self.lexer.description(styleNo), Qt.MatchExactly)[0] |
|
142 parent.setExpanded(True) |
|
143 else: |
|
144 parent = self.styleElementList |
|
145 itm = QTreeWidgetItem(parent, [description]) |
|
146 itm.setData(0, self.StyleRole, styleNo) |
|
147 itm.setData(0, self.SubstyleRole, subStyleNo) |
|
148 self.__styleAllItems() |
|
149 self.styleElementList.setCurrentItem( |
|
150 self.styleElementList.topLevelItem(0)) |
|
151 |
|
152 def __stylesForItem(self, itm): |
|
153 """ |
|
154 Private method to get the style and sub-style number of the given item. |
|
155 |
|
156 @param itm reference to the item to extract the styles from |
|
157 @type QTreeWidgetItem |
|
158 @return tuple containing the style and sub-style numbers |
|
159 @rtype tuple of (int, int) |
|
160 """ |
|
161 style = itm.data(0, self.StyleRole) |
|
162 substyle = itm.data(0, self.SubstyleRole) |
|
163 |
|
164 return (style, substyle) |
|
165 |
|
166 def __currentStyles(self): |
|
167 """ |
|
168 Private method to get the styles of the current item. |
|
169 |
|
170 @return tuple containing the style and sub-style numbers |
|
171 @rtype tuple of (int, int) |
|
172 """ |
|
173 itm = self.styleElementList.currentItem() |
|
174 if itm is None: |
|
175 styles = (0, -1) # return default style |
|
176 else: |
|
177 styles = self.__stylesForItem(itm) |
|
178 |
|
179 return styles |
|
180 |
|
181 def __styleOneItem(self, item, style, substyle): |
|
182 """ |
|
183 Private method to style one item of the style element list. |
|
184 |
|
185 @param item reference to the item to be styled |
|
186 @type QTreeWidgetItem |
|
187 @param style base style number |
|
188 @type int |
|
189 @param substyle sub-style number |
|
190 @type int |
|
191 """ |
|
192 colour = self.lexer.color(style, substyle) |
|
193 paper = self.lexer.paper(style, substyle) |
|
194 font = self.lexer.font(style, substyle) |
|
195 eolfill = self.lexer.eolFill(style, substyle) |
|
196 |
|
197 item.setFont(0, font) |
|
198 item.setBackground(0, paper) |
|
199 item.setForeground(0, colour) |
|
200 if eolfill: |
|
201 item.setCheckState(0, Qt.Checked) |
|
202 else: |
|
203 item.setCheckState(0, Qt.Unchecked) |
|
204 |
|
205 def __styleAllItems(self): |
|
206 """ |
|
207 Private method to style all items of the style element list. |
|
208 """ |
|
209 itm = self.styleElementList.topLevelItem(0) |
|
210 while itm is not None: |
|
211 style, substyle = self.__stylesForItem(itm) |
|
212 self.__styleOneItem(itm, style, substyle) |
|
213 itm = self.styleElementList.itemBelow(itm) |
|
214 |
|
215 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
|
216 def on_styleElementList_currentItemChanged(self, current, previous): |
|
217 """ |
|
218 Private method to handle a change of the current row. |
|
219 |
|
220 @param current reference to the current item |
|
221 @type QTreeWidgetItem |
|
222 @param previous reference to the previous item |
|
223 @type QTreeWidgetItem |
|
224 """ |
|
225 if current is None: |
|
226 return |
|
227 |
|
228 style, substyle = self.__stylesForItem(current) |
|
229 colour = self.lexer.color(style, substyle) |
|
230 paper = self.lexer.paper(style, substyle) |
|
231 eolfill = self.lexer.eolFill(style, substyle) |
|
232 font = self.lexer.font(style, substyle) |
|
233 |
|
234 self.sampleText.setFont(font) |
|
235 pl = self.sampleText.palette() |
|
236 pl.setColor(QPalette.Text, colour) |
|
237 pl.setColor(QPalette.Base, paper) |
|
238 self.sampleText.setPalette(pl) |
|
239 self.sampleText.repaint() |
|
240 self.eolfillCheckBox.setChecked(eolfill) |
|
241 |
|
242 selectedOne = len(self.styleElementList.selectedItems()) == 1 |
|
243 self.defaultSubstylesButton.setEnabled( |
|
244 selectedOne and substyle < 0 and self.lexer.isBaseStyle(style)) |
|
245 self.addSubstyleButton.setEnabled( |
|
246 selectedOne and substyle < 0 and self.lexer.isBaseStyle(style)) |
|
247 self.deleteSubstyleButton.setEnabled(selectedOne and substyle >= 0) |
|
248 self.editSubstyleButton.setEnabled(selectedOne and substyle >= 0) |
|
249 self.copySubstyleButton.setEnabled(selectedOne and substyle >= 0) |
|
250 |
|
251 @pyqtSlot() |
|
252 def on_foregroundButton_clicked(self): |
|
253 """ |
|
254 Private method used to select the foreground colour of the selected |
|
255 style and lexer. |
|
256 """ |
|
257 style, substyle = self.__currentStyles() |
|
258 colour = QColorDialog.getColor(self.lexer.color(style, substyle)) |
|
259 if colour.isValid(): |
|
260 pl = self.sampleText.palette() |
|
261 pl.setColor(QPalette.Text, colour) |
|
262 self.sampleText.setPalette(pl) |
|
263 self.sampleText.repaint() |
|
264 for selItem in self.styleElementList.selectedItems(): |
|
265 style, substyle = self.__stylesForItem(selItem) |
|
266 self.lexer.setColor(colour, style, substyle) |
|
267 selItem.setForeground(0, colour) |
|
268 |
|
269 @pyqtSlot() |
|
270 def on_backgroundButton_clicked(self): |
|
271 """ |
|
272 Private method used to select the background colour of the selected |
|
273 style and lexer. |
|
274 """ |
|
275 style, substyle = self.__currentStyles() |
|
276 colour = QColorDialog.getColor(self.lexer.paper(style, substyle)) |
|
277 if colour.isValid(): |
|
278 pl = self.sampleText.palette() |
|
279 pl.setColor(QPalette.Base, colour) |
|
280 self.sampleText.setPalette(pl) |
|
281 self.sampleText.repaint() |
|
282 for selItem in self.styleElementList.selectedItems(): |
|
283 style, substyle = self.__stylesForItem(selItem) |
|
284 self.lexer.setPaper(colour, style, substyle) |
|
285 selItem.setBackground(0, colour) |
|
286 |
|
287 @pyqtSlot() |
|
288 def on_allBackgroundColoursButton_clicked(self): |
|
289 """ |
|
290 Private method used to select the background colour of all styles of a |
|
291 selected lexer. |
|
292 """ |
|
293 style, substyle = self.__currentStyles() |
|
294 colour = QColorDialog.getColor(self.lexer.paper(style, substyle)) |
|
295 if colour.isValid(): |
|
296 pl = self.sampleText.palette() |
|
297 pl.setColor(QPalette.Base, colour) |
|
298 self.sampleText.setPalette(pl) |
|
299 self.sampleText.repaint() |
|
300 |
|
301 itm = self.styleElementList.topLevelItem(0) |
|
302 while itm is not None: |
|
303 style, substyle = self.__stylesForItem(itm) |
|
304 self.lexer.setPaper(colour, style, substyle) |
|
305 itm = self.styleElementList.itemBelow(itm) |
|
306 self.__styleAllItems() |
|
307 |
|
308 def __changeFont(self, doAll, familyOnly, sizeOnly): |
|
309 """ |
|
310 Private slot to change the highlighter font. |
|
311 |
|
312 @param doAll flag indicating to change the font for all styles |
|
313 (boolean) |
|
314 @param familyOnly flag indicating to set the font family only (boolean) |
|
315 @param sizeOnly flag indicating to set the font size only (boolean |
|
316 """ |
|
317 def setFont(font, style, substyle, familyOnly, sizeOnly): |
|
318 """ |
|
319 Local function to set the font. |
|
320 |
|
321 @param font font to be set |
|
322 @type QFont |
|
323 @param style style number |
|
324 @type int |
|
325 @param substyle sub-style number |
|
326 @type int |
|
327 @param familyOnly flag indicating to set the font family only |
|
328 @type bool |
|
329 @param sizeOnly flag indicating to set the font size only |
|
330 @type bool |
|
331 """ |
|
332 if familyOnly or sizeOnly: |
|
333 newFont = QFont(self.lexer.font(style)) |
|
334 if familyOnly: |
|
335 newFont.setFamily(font.family()) |
|
336 if sizeOnly: |
|
337 newFont.setPointSize(font.pointSize()) |
|
338 self.lexer.setFont(newFont, style, substyle) |
|
339 else: |
|
340 self.lexer.setFont(font, style, substyle) |
|
341 |
|
342 def setSampleFont(font, familyOnly, sizeOnly): |
|
343 """ |
|
344 Local function to set the font of the sample text. |
|
345 |
|
346 @param font font to be set (QFont) |
|
347 @param familyOnly flag indicating to set the font family only |
|
348 (boolean) |
|
349 @param sizeOnly flag indicating to set the font size only (boolean |
|
350 """ |
|
351 if familyOnly or sizeOnly: |
|
352 style, substyle = self.__currentStyles() |
|
353 newFont = QFont(self.lexer.font(style, substyle)) |
|
354 if familyOnly: |
|
355 newFont.setFamily(font.family()) |
|
356 if sizeOnly: |
|
357 newFont.setPointSize(font.pointSize()) |
|
358 self.sampleText.setFont(newFont) |
|
359 else: |
|
360 self.sampleText.setFont(font) |
|
361 |
|
362 style, substyle = self.__currentStyles() |
|
363 if self.monospacedButton.isChecked(): |
|
364 options = MonospacedFontsOption |
|
365 else: |
|
366 options = NoFontsOption |
|
367 font, ok = QFontDialog.getFont(self.lexer.font(style, substyle), self, |
|
368 "", options) |
|
369 if ok: |
|
370 setSampleFont(font, familyOnly, sizeOnly) |
|
371 if doAll: |
|
372 itm = self.styleElementList.topLevelItem(0) |
|
373 while itm is not None: |
|
374 style, substyle = self.__stylesForItem(itm) |
|
375 setFont(font, style, substyle, familyOnly, sizeOnly) |
|
376 itm = self.styleElementList.itemBelow(itm) |
|
377 self.__styleAllItems() |
|
378 else: |
|
379 for selItem in self.styleElementList.selectedItems(): |
|
380 style, substyle = self.__stylesForItem(selItem) |
|
381 setFont(font, style, substyle, familyOnly, sizeOnly) |
|
382 itmFont = self.lexer.font(style, substyle) |
|
383 selItem.setFont(0, itmFont) |
|
384 |
|
385 def __fontButtonMenuTriggered(self, act): |
|
386 """ |
|
387 Private slot used to select the font of the selected style and lexer. |
|
388 |
|
389 @param act reference to the triggering action (QAction) |
|
390 """ |
|
391 if act is None: |
|
392 return |
|
393 |
|
394 familyOnly = act.data() in [self.FAMILYANDSIZE, self.FAMILYONLY] |
|
395 sizeOnly = act.data() in [self.FAMILYANDSIZE, self.SIZEONLY] |
|
396 self.__changeFont(False, familyOnly, sizeOnly) |
|
397 |
|
398 def __allFontsButtonMenuTriggered(self, act): |
|
399 """ |
|
400 Private slot used to change the font of all styles of a selected lexer. |
|
401 |
|
402 @param act reference to the triggering action (QAction) |
|
403 """ |
|
404 if act is None: |
|
405 return |
|
406 |
|
407 familyOnly = act.data() in [self.FAMILYANDSIZE, self.FAMILYONLY] |
|
408 sizeOnly = act.data() in [self.FAMILYANDSIZE, self.SIZEONLY] |
|
409 self.__changeFont(True, familyOnly, sizeOnly) |
|
410 |
|
411 @pyqtSlot(bool) |
|
412 def on_eolfillCheckBox_clicked(self, on): |
|
413 """ |
|
414 Private method used to set the eolfill for the selected style and |
|
415 lexer. |
|
416 |
|
417 @param on flag indicating enabled or disabled state (boolean) |
|
418 """ |
|
419 style, substyle = self.__currentStyles() |
|
420 checkState = Qt.Checked if on else Qt.Unchecked |
|
421 for selItem in self.styleElementList.selectedItems(): |
|
422 style, substyle = self.__stylesForItem(selItem) |
|
423 self.lexer.setEolFill(on, style, substyle) |
|
424 selItem.setCheckState(0, checkState) |
|
425 |
|
426 @pyqtSlot() |
|
427 def on_allEolFillButton_clicked(self): |
|
428 """ |
|
429 Private method used to set the eolfill for all styles of a selected |
|
430 lexer. |
|
431 """ |
|
432 on = self.tr("Enabled") |
|
433 off = self.tr("Disabled") |
|
434 selection, ok = QInputDialog.getItem( |
|
435 self, |
|
436 self.tr("Fill to end of line"), |
|
437 self.tr("Select fill to end of line for all styles"), |
|
438 [on, off], |
|
439 0, False) |
|
440 if ok: |
|
441 enabled = selection == on |
|
442 self.eolfillCheckBox.setChecked(enabled) |
|
443 |
|
444 itm = self.styleElementList.topLevelItem(0) |
|
445 while itm is not None: |
|
446 style, substyle = self.__stylesForItem(itm) |
|
447 self.lexer.setEolFill(enabled, style, substyle) |
|
448 itm = self.styleElementList.itemBelow(itm) |
|
449 self.__styleAllItems() |
|
450 |
|
451 @pyqtSlot() |
|
452 def on_defaultButton_clicked(self): |
|
453 """ |
|
454 Private method to set the current style to its default values. |
|
455 """ |
|
456 for selItem in self.styleElementList.selectedItems(): |
|
457 style, substyle = self.__stylesForItem(selItem) |
|
458 self.__setToDefault(style, substyle) |
|
459 self.on_styleElementList_currentItemChanged( |
|
460 self.styleElementList.currentItem(), None) |
|
461 self.__styleAllItems() |
|
462 |
|
463 @pyqtSlot() |
|
464 def on_allDefaultButton_clicked(self): |
|
465 """ |
|
466 Private method to set all styles to their default values. |
|
467 """ |
|
468 itm = self.styleElementList.topLevelItem(0) |
|
469 while itm is not None: |
|
470 style, substyle = self.__stylesForItem(itm) |
|
471 self.__setToDefault(style, substyle) |
|
472 itm = self.styleElementList.itemBelow(itm) |
|
473 self.on_styleElementList_currentItemChanged( |
|
474 self.styleElementList.currentItem(), None) |
|
475 self.__styleAllItems() |
|
476 |
|
477 def __setToDefault(self, style, substyle): |
|
478 """ |
|
479 Private method to set a specific style to its default values. |
|
480 |
|
481 @param style style number |
|
482 @type int |
|
483 @param substyle sub-style number |
|
484 @type int |
|
485 """ |
|
486 self.lexer.setColor(self.lexer.defaultColor(style, substyle), |
|
487 style, substyle) |
|
488 self.lexer.setPaper(self.lexer.defaultPaper(style, substyle), |
|
489 style, substyle) |
|
490 self.lexer.setFont(self.lexer.defaultFont(style, substyle), |
|
491 style, substyle) |
|
492 self.lexer.setEolFill(self.lexer.defaultEolFill(style, substyle), |
|
493 style, substyle) |
|
494 |
|
495 ####################################################################### |
|
496 ## Importing and exporting of styles |
|
497 ####################################################################### |
|
498 |
|
499 @pyqtSlot() |
|
500 def on_importCurrentButton_clicked(self): |
|
501 """ |
|
502 Private slot to import the styles of the current lexer. |
|
503 """ |
|
504 self.__importStyles({self.lexer.language(): self.lexer}) |
|
505 |
|
506 @pyqtSlot() |
|
507 def on_exportCurrentButton_clicked(self): |
|
508 """ |
|
509 Private slot to export the styles of the current lexer. |
|
510 """ |
|
511 self.__exportStyles([self.lexer]) |
|
512 |
|
513 @pyqtSlot() |
|
514 def on_importAllButton_clicked(self): |
|
515 """ |
|
516 Private slot to import the styles of all lexers. |
|
517 """ |
|
518 self.__importStyles(self.lexers) |
|
519 |
|
520 @pyqtSlot() |
|
521 def on_exportAllButton_clicked(self): |
|
522 """ |
|
523 Private slot to export the styles of all lexers. |
|
524 """ |
|
525 self.__exportStyles(list(self.lexers.values())) |
|
526 |
|
527 def __exportStyles(self, lexers): |
|
528 """ |
|
529 Private method to export the styles of the given lexers. |
|
530 |
|
531 @param lexers list of lexer objects for which to export the styles |
|
532 """ |
|
533 from eric6config import getConfig |
|
534 stylesDir = getConfig("ericStylesDir") |
|
535 |
|
536 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( |
|
537 self, |
|
538 self.tr("Export Highlighting Styles"), |
|
539 stylesDir, |
|
540 self.tr("Highlighting styles file (*.e6h)"), |
|
541 "", |
|
542 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) |
|
543 |
|
544 if not fn: |
|
545 return |
|
546 |
|
547 ext = QFileInfo(fn).suffix() |
|
548 if not ext: |
|
549 ex = selectedFilter.split("(*")[1].split(")")[0] |
|
550 if ex: |
|
551 fn += ex |
|
552 |
|
553 f = QFile(fn) |
|
554 if f.open(QIODevice.WriteOnly): |
|
555 from E5XML.HighlightingStylesWriter import HighlightingStylesWriter |
|
556 HighlightingStylesWriter(f, lexers).writeXML() |
|
557 f.close() |
|
558 else: |
|
559 E5MessageBox.critical( |
|
560 self, |
|
561 self.tr("Export Highlighting Styles"), |
|
562 self.tr( |
|
563 """<p>The highlighting styles could not be exported""" |
|
564 """ to file <b>{0}</b>.</p><p>Reason: {1}</p>""") |
|
565 .format(fn, f.errorString()) |
|
566 ) |
|
567 |
|
568 def __importStyles(self, lexers): |
|
569 """ |
|
570 Private method to import the styles of the given lexers. |
|
571 |
|
572 @param lexers dictionary of lexer objects for which to import the |
|
573 styles |
|
574 """ |
|
575 from eric6config import getConfig |
|
576 stylesDir = getConfig("ericStylesDir") |
|
577 |
|
578 fn = E5FileDialog.getOpenFileName( |
|
579 self, |
|
580 self.tr("Import Highlighting Styles"), |
|
581 stylesDir, |
|
582 self.tr("Highlighting styles file (*.e6h *.e4h)")) |
|
583 |
|
584 if not fn: |
|
585 return |
|
586 |
|
587 f = QFile(fn) |
|
588 if f.open(QIODevice.ReadOnly): |
|
589 from E5XML.HighlightingStylesReader import HighlightingStylesReader |
|
590 reader = HighlightingStylesReader(f, lexers) |
|
591 reader.readXML() |
|
592 f.close() |
|
593 else: |
|
594 E5MessageBox.critical( |
|
595 self, |
|
596 self.tr("Import Highlighting Styles"), |
|
597 self.tr( |
|
598 """<p>The highlighting styles could not be read""" |
|
599 """ from file <b>{0}</b>.</p><p>Reason: {1}</p>""") |
|
600 .format(fn, f.errorString()) |
|
601 ) |
|
602 return |
|
603 |
|
604 self.on_lexerLanguageComboBox_activated( |
|
605 self.lexerLanguageComboBox.currentText()) |
|
606 |
|
607 ####################################################################### |
|
608 ## Methods to save and restore the state |
|
609 ####################################################################### |
|
610 |
|
611 def saveState(self): |
|
612 """ |
|
613 Public method to save the current state of the widget. |
|
614 |
|
615 @return list containing the index of the selected lexer language |
|
616 and a tuple containing the index of the parent selected lexer |
|
617 entry and the index of the selected entry |
|
618 @rtype list of int and tuple of (int, int) |
|
619 """ |
|
620 itm = self.styleElementList.currentItem() |
|
621 parent = itm.parent() |
|
622 if parent is None: |
|
623 currentData = ( |
|
624 None, self.styleElementList.indexOfTopLevelItem(itm)) |
|
625 else: |
|
626 currentData = ( |
|
627 self.styleElementList.indexOfTopLevelItem(parent), |
|
628 parent.indexOfChild(itm) |
|
629 ) |
|
630 |
|
631 savedState = [ |
|
632 self.lexerLanguageComboBox.currentIndex(), |
|
633 currentData, |
|
634 ] |
|
635 return savedState |
|
636 |
|
637 def setState(self, state): |
|
638 """ |
|
639 Public method to set the state of the widget. |
|
640 |
|
641 @param state state data generated by saveState |
|
642 """ |
|
643 self.lexerLanguageComboBox.setCurrentIndex(state[0]) |
|
644 self.on_lexerLanguageComboBox_activated( |
|
645 self.lexerLanguageComboBox.currentText()) |
|
646 |
|
647 parentIndex, index = state[1] |
|
648 if parentIndex is None: |
|
649 itm = self.styleElementList.topLevelItem(index) |
|
650 else: |
|
651 parent = self.styleElementList.topLevelItem(parentIndex) |
|
652 itm = parent.child(index) |
|
653 self.styleElementList.setCurrentItem(itm) |
|
654 |
|
655 ####################################################################### |
|
656 ## Methods to add, delete and edit sub-styles and their definitions |
|
657 ####################################################################### |
|
658 |
|
659 @pyqtSlot() |
|
660 def on_addSubstyleButton_clicked(self): |
|
661 """ |
|
662 Private slot to add a new sub-style. |
|
663 """ |
|
664 style, substyle = self.__currentStyles() |
|
665 dlg = SubstyleDefinitionDialog( |
|
666 self.lexer, style, substyle, parent=self) |
|
667 if dlg.exec_() == QDialog.Accepted: |
|
668 description, words = dlg.getData() |
|
669 substyle = self.lexer.addSubstyle(style) |
|
670 self.lexer.setDescription(description, style, substyle) |
|
671 self.lexer.setWords(words, style, substyle) |
|
672 |
|
673 parent = self.styleElementList.findItems( |
|
674 self.lexer.description(style), Qt.MatchExactly)[0] |
|
675 parent.setExpanded(True) |
|
676 itm = QTreeWidgetItem(parent, [description]) |
|
677 itm.setData(0, self.StyleRole, style) |
|
678 itm.setData(0, self.SubstyleRole, substyle) |
|
679 self.__styleOneItem(itm, style, substyle) |
|
680 |
|
681 @pyqtSlot() |
|
682 def on_deleteSubstyleButton_clicked(self): |
|
683 """ |
|
684 Private slot to delete the selected sub-style. |
|
685 """ |
|
686 style, substyle = self.__currentStyles() |
|
687 ok = E5MessageBox.yesNo( |
|
688 self, |
|
689 self.tr("Delete Sub-Style"), |
|
690 self.tr("""<p>Shall the sub-style <b>{0}</b> really be""" |
|
691 """ deleted?</p>""").format( |
|
692 self.lexer.description(style, substyle)) |
|
693 ) |
|
694 if ok: |
|
695 self.lexer.delSubstyle(style, substyle) |
|
696 |
|
697 itm = self.styleElementList.currentItem() |
|
698 parent = itm.parent() |
|
699 index = parent.indexOfChild(itm) |
|
700 parent.takeChild(index) |
|
701 del itm |
|
702 |
|
703 @pyqtSlot() |
|
704 def on_editSubstyleButton_clicked(self): |
|
705 """ |
|
706 Private slot to edit the selected sub-style entry. |
|
707 """ |
|
708 style, substyle = self.__currentStyles() |
|
709 dlg = SubstyleDefinitionDialog( |
|
710 self.lexer, style, substyle, parent=self) |
|
711 if dlg.exec_() == QDialog.Accepted: |
|
712 description, words = dlg.getData() |
|
713 self.lexer.setDescription(description, style, substyle) |
|
714 self.lexer.setWords(words, style, substyle) |
|
715 |
|
716 itm = self.styleElementList.currentItem() |
|
717 itm.setText(0, description) |
|
718 |
|
719 @pyqtSlot() |
|
720 def on_copySubstyleButton_clicked(self): |
|
721 """ |
|
722 Private slot to copy the selected sub-style. |
|
723 """ |
|
724 style, substyle = self.__currentStyles() |
|
725 newSubstyle = self.lexer.addSubstyle(style) |
|
726 |
|
727 description = self.tr("{0} - Copy").format( |
|
728 self.lexer.description(style, substyle)) |
|
729 self.lexer.setDescription(description, style, newSubstyle) |
|
730 self.lexer.setWords(self.lexer.words(style, substyle), |
|
731 style, newSubstyle) |
|
732 self.lexer.setColor(self.lexer.color(style, substyle), |
|
733 style, newSubstyle) |
|
734 self.lexer.setPaper(self.lexer.paper(style, substyle), |
|
735 style, newSubstyle) |
|
736 self.lexer.setFont(self.lexer.font(style, substyle), |
|
737 style, newSubstyle) |
|
738 self.lexer.setEolFill(self.lexer.eolFill(style, substyle), |
|
739 style, newSubstyle) |
|
740 |
|
741 parent = self.styleElementList.findItems( |
|
742 self.lexer.description(style), Qt.MatchExactly)[0] |
|
743 parent.setExpanded(True) |
|
744 itm = QTreeWidgetItem(parent, [description]) |
|
745 itm.setData(0, self.StyleRole, style) |
|
746 itm.setData(0, self.SubstyleRole, newSubstyle) |
|
747 self.__styleOneItem(itm, style, newSubstyle) |
|
748 |
|
749 @pyqtSlot() |
|
750 def on_defaultSubstylesButton_clicked(self): |
|
751 """ |
|
752 Private slot to reset all substyles to default values. |
|
753 """ |
|
754 style, substyle = self.__currentStyles() |
|
755 ok = E5MessageBox.yesNo( |
|
756 self, |
|
757 self.tr("Reset Sub-Styles to Default"), |
|
758 self.tr("<p>Do you really want to reset all defined sub-styles of" |
|
759 " <b>{0}</b> to the default values?</p>""") |
|
760 .format(self.lexer.description(style, substyle)) |
|
761 ) |
|
762 if ok: |
|
763 # 1. reset sub-styles |
|
764 self.lexer.loadDefaultSubStyles(style) |
|
765 |
|
766 # 2. delete all existing sub-style items |
|
767 parent = self.styleElementList.currentItem() |
|
768 while parent.childCount() > 0: |
|
769 itm = parent.takeChild(0) # __IGNORE_WARNING__ |
|
770 del itm |
|
771 |
|
772 # 3. create the new list of sub-style items |
|
773 for description, _, substyle in self.lexer.getSubStyles(style): |
|
774 itm = QTreeWidgetItem(parent, [description]) |
|
775 itm.setData(0, self.StyleRole, style) |
|
776 itm.setData(0, self.SubstyleRole, substyle) |
|
777 self.__styleOneItem(itm, style, substyle) |
|
778 |
|
779 |
|
780 def create(dlg): |
|
781 """ |
|
782 Module function to create the configuration page. |
|
783 |
|
784 @param dlg reference to the configuration dialog |
|
785 @return reference to the instantiated page (ConfigurationPageBase) |
|
786 """ |
|
787 page = EditorHighlightingStylesPage(dlg.getLexers()) |
|
788 return page |