src/eric7/Preferences/ConfigurationPages/EditorHighlightingStylesPage.py

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

eric ide

mercurial