1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2006 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 4# 5 6""" 7Module implementing the Editor General configuration page. 8""" 9 10from PyQt5.QtCore import pyqtSlot, Qt 11from PyQt5.QtWidgets import QTreeWidgetItem, QHeaderView, QDialog 12from PyQt5.Qsci import QsciScintillaBase 13 14from E5Gui import E5MessageBox 15 16from .ConfigurationPageBase import ConfigurationPageBase 17from .Ui_EditorGeneralPage import Ui_EditorGeneralPage 18from .EditorLanguageTabIndentOverrideDialog import ( 19 EditorLanguageTabIndentOverrideDialog 20) 21 22from QScintilla.DocstringGenerator import getSupportedDocstringTypes 23 24import Preferences 25import UI.PixmapCache 26 27 28class EditorGeneralPage(ConfigurationPageBase, Ui_EditorGeneralPage): 29 """ 30 Class implementing the Editor General configuration page. 31 """ 32 def __init__(self): 33 """ 34 Constructor 35 """ 36 super().__init__() 37 self.setupUi(self) 38 self.setObjectName("EditorGeneralPage") 39 40 self.addButton.setIcon(UI.PixmapCache.getIcon("plus")) 41 self.deleteButton.setIcon(UI.PixmapCache.getIcon("minus")) 42 self.editButton.setIcon(UI.PixmapCache.getIcon("edit")) 43 44 for docstringType, docstringStyle in sorted( 45 getSupportedDocstringTypes() 46 ): 47 self.docstringStyleComboBox.addItem(docstringStyle, docstringType) 48 49 # set initial values 50 self.tabwidthSlider.setValue( 51 Preferences.getEditor("TabWidth")) 52 self.indentwidthSlider.setValue( 53 Preferences.getEditor("IndentWidth")) 54 self.tabforindentationCheckBox.setChecked( 55 Preferences.getEditor("TabForIndentation")) 56 self.tabindentsCheckBox.setChecked( 57 Preferences.getEditor("TabIndents")) 58 self.converttabsCheckBox.setChecked( 59 Preferences.getEditor("ConvertTabsOnLoad")) 60 self.autoindentCheckBox.setChecked( 61 Preferences.getEditor("AutoIndentation")) 62 self.comment0CheckBox.setChecked( 63 Preferences.getEditor("CommentColumn0")) 64 65 self.sourceOutlineGroupBox.setChecked( 66 Preferences.getEditor("ShowSourceOutline")) 67 self.sourceOutlineWidthSpinBox.setValue( 68 Preferences.getEditor("SourceOutlineWidth")) 69 self.sourceOutlineWidthStepSpinBox.setValue( 70 Preferences.getEditor("SourceOutlineStepSize")) 71 self.sourceOutlineShowCodingCheckBox.setChecked( 72 Preferences.getEditor("SourceOutlineShowCoding")) 73 74 index = self.docstringStyleComboBox.findData( 75 Preferences.getEditor("DocstringType")) 76 self.docstringStyleComboBox.setCurrentIndex(index) 77 self.docstringCompletionCheckBox.setChecked( 78 Preferences.getEditor("DocstringAutoGenerate")) 79 80 virtualSpaceOptions = Preferences.getEditor("VirtualSpaceOptions") 81 self.vsSelectionCheckBox.setChecked( 82 virtualSpaceOptions & QsciScintillaBase.SCVS_RECTANGULARSELECTION) 83 self.vsUserCheckBox.setChecked( 84 virtualSpaceOptions & QsciScintillaBase.SCVS_USERACCESSIBLE) 85 86 self.__populateLanguageOverrideWidget() 87 88 def save(self): 89 """ 90 Public slot to save the Editor General configuration. 91 """ 92 Preferences.setEditor( 93 "TabWidth", 94 self.tabwidthSlider.value()) 95 Preferences.setEditor( 96 "IndentWidth", 97 self.indentwidthSlider.value()) 98 Preferences.setEditor( 99 "TabForIndentation", 100 self.tabforindentationCheckBox.isChecked()) 101 Preferences.setEditor( 102 "TabIndents", 103 self.tabindentsCheckBox.isChecked()) 104 Preferences.setEditor( 105 "ConvertTabsOnLoad", 106 self.converttabsCheckBox.isChecked()) 107 Preferences.setEditor( 108 "AutoIndentation", 109 self.autoindentCheckBox.isChecked()) 110 Preferences.setEditor( 111 "CommentColumn0", 112 self.comment0CheckBox.isChecked()) 113 114 Preferences.setEditor( 115 "ShowSourceOutline", 116 self.sourceOutlineGroupBox.isChecked()) 117 Preferences.setEditor( 118 "SourceOutlineWidth", 119 self.sourceOutlineWidthSpinBox.value()) 120 Preferences.setEditor( 121 "SourceOutlineStepSize", 122 self.sourceOutlineWidthStepSpinBox.value()) 123 Preferences.setEditor( 124 "SourceOutlineShowCoding", 125 self.sourceOutlineShowCodingCheckBox.isChecked()) 126 127 Preferences.setEditor( 128 "DocstringType", 129 self.docstringStyleComboBox.currentData()) 130 Preferences.setEditor( 131 "DocstringAutoGenerate", 132 self.docstringCompletionCheckBox.isChecked()) 133 134 virtualSpaceOptions = QsciScintillaBase.SCVS_NONE 135 if self.vsSelectionCheckBox.isChecked(): 136 virtualSpaceOptions |= QsciScintillaBase.SCVS_RECTANGULARSELECTION 137 if self.vsUserCheckBox.isChecked(): 138 virtualSpaceOptions |= QsciScintillaBase.SCVS_USERACCESSIBLE 139 Preferences.setEditor("VirtualSpaceOptions", virtualSpaceOptions) 140 141 self.__saveLanguageOverrides() 142 143 def on_tabforindentationCheckBox_toggled(self, checked): 144 """ 145 Private slot used to set the tab conversion check box. 146 147 @param checked flag received from the signal (boolean) 148 """ 149 if checked and self.converttabsCheckBox.isChecked(): 150 self.converttabsCheckBox.setChecked(not checked) 151 self.converttabsCheckBox.setEnabled(not checked) 152 153 def __populateLanguageOverrideWidget(self): 154 """ 155 Private method to populate the language specific indentation and tab 156 width override widget. 157 """ 158 overrides = Preferences.getEditor("TabIndentOverride") 159 for language, (tabWidth, indentWidth) in overrides.items(): 160 self.__createOverrideItem(language, tabWidth, indentWidth) 161 self.languageOverrideWidget.sortItems(0, Qt.SortOrder.AscendingOrder) 162 self.__resizeOverrideColumns() 163 self.on_languageOverrideWidget_itemSelectionChanged() 164 165 def __createOverrideItem(self, language, tabWidth, indentWidth): 166 """ 167 Private method to create an entry for a language override. 168 169 @param language name of the language 170 @type str 171 @param tabWidth tabulator width 172 @type int 173 @param indentWidth indentation width 174 @type int 175 """ 176 itm = QTreeWidgetItem(self.languageOverrideWidget, [ 177 language, 178 "{0:2d}".format(tabWidth), 179 "{0:2d}".format(indentWidth)]) 180 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter) 181 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter) 182 183 def __resizeOverrideColumns(self): 184 """ 185 Private method to resize the list columns. 186 """ 187 self.languageOverrideWidget.header().resizeSections( 188 QHeaderView.ResizeMode.ResizeToContents) 189 self.languageOverrideWidget.header().setStretchLastSection(True) 190 191 def __saveLanguageOverrides(self): 192 """ 193 Private method to save the language specific indentation and tab width 194 overrides. 195 """ 196 overrides = {} 197 for row in range(self.languageOverrideWidget.topLevelItemCount()): 198 itm = self.languageOverrideWidget.topLevelItem(row) 199 language = itm.text(0) 200 overrides[language] = [ 201 int(itm.text(1)), 202 int(itm.text(2)), 203 ] 204 205 Preferences.setEditor("TabIndentOverride", overrides) 206 207 @pyqtSlot() 208 def on_languageOverrideWidget_itemSelectionChanged(self): 209 """ 210 Private slot handling a change of the override selection. 211 """ 212 self.deleteButton.setEnabled( 213 len(self.languageOverrideWidget.selectedItems()) > 0) 214 self.editButton.setEnabled( 215 len(self.languageOverrideWidget.selectedItems()) == 1) 216 217 @pyqtSlot() 218 def on_addButton_clicked(self): 219 """ 220 Private slot to add a new override entry. 221 """ 222 languages = [] 223 for row in range(self.languageOverrideWidget.topLevelItemCount()): 224 itm = self.languageOverrideWidget.topLevelItem(row) 225 languages.append(itm.text(0)) 226 dlg = EditorLanguageTabIndentOverrideDialog( 227 editMode=False, 228 languages=languages, 229 tabWidth=self.tabwidthSlider.value(), 230 indentWidth=self.indentwidthSlider.value(), 231 ) 232 if dlg.exec() == QDialog.DialogCode.Accepted: 233 language, tabWidth, indentWidth = dlg.getData() 234 self.__createOverrideItem(language, tabWidth, indentWidth) 235 self.languageOverrideWidget.sortItems( 236 0, Qt.SortOrder.AscendingOrder) 237 self.__resizeOverrideColumns() 238 239 @pyqtSlot() 240 def on_deleteButton_clicked(self): 241 """ 242 Private slot to delete the selected override entries. 243 """ 244 ok = E5MessageBox.yesNo( 245 self, 246 self.tr("Tab and Indent Override"), 247 self.tr("""Shall the selected entries really be removed?""")) 248 if ok: 249 for itm in self.languageOverrideWidget.selectedItems(): 250 index = self.languageOverrideWidget.indexOfTopLevelItem(itm) 251 self.languageOverrideWidget.takeTopLevelItem(index) 252 del itm 253 254 @pyqtSlot() 255 def on_editButton_clicked(self): 256 """ 257 Private slot to edit the selected override entry. 258 """ 259 itm = self.languageOverrideWidget.selectedItems()[0] 260 dlg = EditorLanguageTabIndentOverrideDialog( 261 editMode=True, 262 languages=[itm.text(0)], 263 tabWidth=int(itm.text(1)), 264 indentWidth=int(itm.text(2)), 265 ) 266 if dlg.exec() == QDialog.DialogCode.Accepted: 267 language, tabWidth, indentWidth = dlg.getData() 268 itm.setText(1, "{0:2d}".format(tabWidth)) 269 itm.setText(2, "{0:2d}".format(indentWidth)) 270 271 272def create(dlg): 273 """ 274 Module function to create the configuration page. 275 276 @param dlg reference to the configuration dialog 277 @return reference to the instantiated page (ConfigurationPageBase) 278 """ 279 page = EditorGeneralPage() 280 return page 281