|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2006 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Editor File Handling configuration page. |
|
8 """ |
|
9 |
|
10 import sys |
|
11 |
|
12 from PyQt5.QtCore import pyqtSlot |
|
13 from PyQt5.QtWidgets import QListWidgetItem, QInputDialog, QLineEdit |
|
14 from PyQt5.Qsci import QsciScintilla |
|
15 |
|
16 from E5Gui import E5MessageBox |
|
17 from E5Gui.E5Application import e5App |
|
18 |
|
19 from .ConfigurationPageBase import ConfigurationPageBase |
|
20 from .Ui_EditorFilePage import Ui_EditorFilePage |
|
21 |
|
22 from Utilities import supportedCodecs |
|
23 import Preferences |
|
24 |
|
25 |
|
26 class EditorFilePage(ConfigurationPageBase, Ui_EditorFilePage): |
|
27 """ |
|
28 Class implementing the Editor File Handling configuration page. |
|
29 """ |
|
30 def __init__(self): |
|
31 """ |
|
32 Constructor |
|
33 """ |
|
34 super().__init__() |
|
35 self.setupUi(self) |
|
36 self.setObjectName("EditorFilePage") |
|
37 |
|
38 self.__showsOpenFilters = True |
|
39 self.openFileFilters = Preferences.getEditor( |
|
40 "AdditionalOpenFilters")[:] |
|
41 self.saveFileFilters = Preferences.getEditor( |
|
42 "AdditionalSaveFilters")[:] |
|
43 self.fileFiltersList.addItems(self.openFileFilters) |
|
44 |
|
45 self.__setDefaultFiltersLists() |
|
46 |
|
47 self.defaultEncodingComboBox.addItems(sorted(supportedCodecs)) |
|
48 |
|
49 self.previewMarkdownHTMLFormatComboBox.addItems( |
|
50 ["XHTML1", "HTML4", "HTML5"]) |
|
51 self.previewRestDocutilsHTMLFormatComboBox.addItems( |
|
52 ["HTML4", "HTML5"]) |
|
53 |
|
54 # set initial values |
|
55 self.autosaveSlider.setValue( |
|
56 Preferences.getEditor("AutosaveInterval")) |
|
57 self.createBackupFileCheckBox.setChecked( |
|
58 Preferences.getEditor("CreateBackupFile")) |
|
59 self.defaultEncodingComboBox.setCurrentIndex( |
|
60 self.defaultEncodingComboBox.findText( |
|
61 Preferences.getEditor("DefaultEncoding"))) |
|
62 self.advEncodingCheckBox.setChecked( |
|
63 Preferences.getEditor("AdvancedEncodingDetection")) |
|
64 self.warnFilesizeSpinBox.setValue( |
|
65 Preferences.getEditor("WarnFilesize")) |
|
66 self.clearBreakpointsCheckBox.setChecked( |
|
67 Preferences.getEditor("ClearBreaksOnClose")) |
|
68 self.automaticReopenCheckBox.setChecked( |
|
69 Preferences.getEditor("AutoReopen")) |
|
70 self.stripWhitespaceCheckBox.setChecked( |
|
71 Preferences.getEditor("StripTrailingWhitespace")) |
|
72 self.openFilesFilterComboBox.setCurrentIndex( |
|
73 self.openFilesFilterComboBox.findText( |
|
74 Preferences.getEditor("DefaultOpenFilter"))) |
|
75 self.saveFilesFilterComboBox.setCurrentIndex( |
|
76 self.saveFilesFilterComboBox.findText( |
|
77 Preferences.getEditor("DefaultSaveFilter"))) |
|
78 self.automaticEolConversionCheckBox.setChecked( |
|
79 Preferences.getEditor("AutomaticEOLConversion")) |
|
80 self.insertFinalNewlineCheckBox.setChecked( |
|
81 Preferences.getEditor("InsertFinalNewline")) |
|
82 |
|
83 eolMode = Preferences.getEditor("EOLMode") |
|
84 if eolMode == QsciScintilla.EolMode.EolWindows: |
|
85 self.crlfRadioButton.setChecked(True) |
|
86 elif eolMode == QsciScintilla.EolMode.EolMac: |
|
87 self.crRadioButton.setChecked(True) |
|
88 elif eolMode == QsciScintilla.EolMode.EolUnix: |
|
89 self.lfRadioButton.setChecked(True) |
|
90 |
|
91 self.previewRefreshTimeoutSpinBox.setValue( |
|
92 Preferences.getEditor("PreviewRefreshWaitTimer")) |
|
93 |
|
94 self.previewHtmlExtensionsEdit.setText( |
|
95 " ".join(Preferences.getEditor("PreviewHtmlFileNameExtensions"))) |
|
96 |
|
97 self.previewMarkdownExtensionsEdit.setText( |
|
98 " ".join( |
|
99 Preferences.getEditor("PreviewMarkdownFileNameExtensions"))) |
|
100 self.previewRestSphinxCheckBox.setChecked( |
|
101 Preferences.getEditor("PreviewRestUseSphinx")) |
|
102 self.previewMarkdownNLtoBreakCheckBox.setChecked( |
|
103 Preferences.getEditor("PreviewMarkdownNLtoBR")) |
|
104 self.previewMarkdownPyMdownCheckBox.setChecked( |
|
105 Preferences.getEditor("PreviewMarkdownUsePyMdownExtensions")) |
|
106 self.previewMarkdownMathJaxCheckBox.setChecked( |
|
107 Preferences.getEditor("PreviewMarkdownMathJax")) |
|
108 self.previewMarkdownMermaidCheckBox.setChecked( |
|
109 Preferences.getEditor("PreviewMarkdownMermaid")) |
|
110 index = self.previewMarkdownHTMLFormatComboBox.findText( |
|
111 Preferences.getEditor("PreviewMarkdownHTMLFormat")) |
|
112 self.previewMarkdownHTMLFormatComboBox.setCurrentIndex(index) |
|
113 |
|
114 self.previewRestExtensionsEdit.setText( |
|
115 " ".join(Preferences.getEditor("PreviewRestFileNameExtensions"))) |
|
116 index = self.previewRestDocutilsHTMLFormatComboBox.findText( |
|
117 Preferences.getEditor("PreviewRestDocutilsHTMLFormat")) |
|
118 self.previewRestDocutilsHTMLFormatComboBox.setCurrentIndex(index) |
|
119 |
|
120 self.previewQssExtensionsEdit.setText( |
|
121 " ".join(Preferences.getEditor("PreviewQssFileNameExtensions"))) |
|
122 |
|
123 def save(self): |
|
124 """ |
|
125 Public slot to save the Editor File Handling configuration. |
|
126 """ |
|
127 Preferences.setEditor( |
|
128 "AutosaveInterval", |
|
129 self.autosaveSlider.value()) |
|
130 Preferences.setEditor( |
|
131 "CreateBackupFile", |
|
132 self.createBackupFileCheckBox.isChecked()) |
|
133 enc = self.defaultEncodingComboBox.currentText() |
|
134 if not enc: |
|
135 enc = "utf-8" |
|
136 Preferences.setEditor("DefaultEncoding", enc) |
|
137 Preferences.setEditor( |
|
138 "AdvancedEncodingDetection", |
|
139 self.advEncodingCheckBox.isChecked()) |
|
140 Preferences.setEditor( |
|
141 "WarnFilesize", |
|
142 self.warnFilesizeSpinBox.value()) |
|
143 Preferences.setEditor( |
|
144 "ClearBreaksOnClose", |
|
145 self.clearBreakpointsCheckBox.isChecked()) |
|
146 Preferences.setEditor( |
|
147 "AutoReopen", |
|
148 self.automaticReopenCheckBox.isChecked()) |
|
149 Preferences.setEditor( |
|
150 "StripTrailingWhitespace", |
|
151 self.stripWhitespaceCheckBox.isChecked()) |
|
152 Preferences.setEditor( |
|
153 "DefaultOpenFilter", |
|
154 self.openFilesFilterComboBox.currentText()) |
|
155 Preferences.setEditor( |
|
156 "DefaultSaveFilter", |
|
157 self.saveFilesFilterComboBox.currentText()) |
|
158 Preferences.setEditor( |
|
159 "AutomaticEOLConversion", |
|
160 self.automaticEolConversionCheckBox.isChecked()) |
|
161 Preferences.setEditor( |
|
162 "InsertFinalNewline", |
|
163 self.insertFinalNewlineCheckBox.isChecked()) |
|
164 |
|
165 if self.crlfRadioButton.isChecked(): |
|
166 Preferences.setEditor("EOLMode", QsciScintilla.EolMode.EolWindows) |
|
167 elif self.crRadioButton.isChecked(): |
|
168 Preferences.setEditor("EOLMode", QsciScintilla.EolMode.EolMac) |
|
169 elif self.lfRadioButton.isChecked(): |
|
170 Preferences.setEditor("EOLMode", QsciScintilla.EolMode.EolUnix) |
|
171 |
|
172 self.__extractFileFilters() |
|
173 Preferences.setEditor("AdditionalOpenFilters", self.openFileFilters) |
|
174 Preferences.setEditor("AdditionalSaveFilters", self.saveFileFilters) |
|
175 |
|
176 Preferences.setEditor( |
|
177 "PreviewRefreshWaitTimer", |
|
178 self.previewRefreshTimeoutSpinBox.value()) |
|
179 |
|
180 Preferences.setEditor( |
|
181 "PreviewHtmlFileNameExtensions", |
|
182 [ext.strip() for ext in |
|
183 self.previewHtmlExtensionsEdit.text().split()]) |
|
184 |
|
185 Preferences.setEditor( |
|
186 "PreviewMarkdownFileNameExtensions", |
|
187 [ext.strip() for ext in |
|
188 self.previewMarkdownExtensionsEdit.text().split()]) |
|
189 Preferences.setEditor( |
|
190 "PreviewRestUseSphinx", |
|
191 self.previewRestSphinxCheckBox.isChecked()) |
|
192 Preferences.setEditor( |
|
193 "PreviewMarkdownNLtoBR", |
|
194 self.previewMarkdownNLtoBreakCheckBox.isChecked()) |
|
195 Preferences.setEditor( |
|
196 "PreviewMarkdownUsePyMdownExtensions", |
|
197 self.previewMarkdownPyMdownCheckBox.isChecked()) |
|
198 Preferences.setEditor( |
|
199 "PreviewMarkdownMathJax", |
|
200 self.previewMarkdownMathJaxCheckBox.isChecked()) |
|
201 Preferences.setEditor( |
|
202 "PreviewMarkdownMermaid", |
|
203 self.previewMarkdownMermaidCheckBox.isChecked()) |
|
204 Preferences.setEditor( |
|
205 "PreviewMarkdownHTMLFormat", |
|
206 self.previewMarkdownHTMLFormatComboBox.currentText()) |
|
207 |
|
208 Preferences.setEditor( |
|
209 "PreviewRestFileNameExtensions", |
|
210 [ext.strip() for ext in |
|
211 self.previewRestExtensionsEdit.text().split()]) |
|
212 Preferences.setEditor( |
|
213 "PreviewRestDocutilsHTMLFormat", |
|
214 self.previewRestDocutilsHTMLFormatComboBox.currentText()) |
|
215 |
|
216 Preferences.setEditor( |
|
217 "PreviewQssFileNameExtensions", |
|
218 [ext.strip() for ext in |
|
219 self.previewQssExtensionsEdit.text().split()]) |
|
220 |
|
221 def __setDefaultFiltersLists(self, keepSelection=False): |
|
222 """ |
|
223 Private slot to set the default file filter combo boxes. |
|
224 |
|
225 @param keepSelection flag indicating to keep the current selection |
|
226 if possible (boolean) |
|
227 """ |
|
228 if keepSelection: |
|
229 selectedOpenFilter = self.openFilesFilterComboBox.currentText() |
|
230 selectedSaveFilter = self.saveFilesFilterComboBox.currentText() |
|
231 |
|
232 import QScintilla.Lexers |
|
233 openFileFiltersList = QScintilla.Lexers.getOpenFileFiltersList( |
|
234 False, withAdditional=False) + self.openFileFilters |
|
235 openFileFiltersList.sort() |
|
236 self.openFilesFilterComboBox.clear() |
|
237 self.openFilesFilterComboBox.addItems(openFileFiltersList) |
|
238 saveFileFiltersList = QScintilla.Lexers.getSaveFileFiltersList( |
|
239 False, withAdditional=False) + self.saveFileFilters |
|
240 saveFileFiltersList.sort() |
|
241 self.saveFilesFilterComboBox.clear() |
|
242 self.saveFilesFilterComboBox.addItems(saveFileFiltersList) |
|
243 |
|
244 if keepSelection: |
|
245 self.openFilesFilterComboBox.setCurrentIndex( |
|
246 self.openFilesFilterComboBox.findText(selectedOpenFilter)) |
|
247 self.saveFilesFilterComboBox.setCurrentIndex( |
|
248 self.saveFilesFilterComboBox.findText(selectedSaveFilter)) |
|
249 |
|
250 def __extractFileFilters(self): |
|
251 """ |
|
252 Private method to extract the file filters. |
|
253 """ |
|
254 filters = [] |
|
255 for row in range(self.fileFiltersList.count()): |
|
256 filters.append(self.fileFiltersList.item(row).text()) |
|
257 if self.__showsOpenFilters: |
|
258 self.openFileFilters = filters |
|
259 else: |
|
260 self.saveFileFilters = filters |
|
261 |
|
262 def __checkFileFilter(self, fileFilter): |
|
263 """ |
|
264 Private method to check a file filter for validity. |
|
265 |
|
266 @param fileFilter file filter pattern to check (string) |
|
267 @return flag indicating validity (boolean) |
|
268 """ |
|
269 if ( |
|
270 not self.__showsOpenFilters and |
|
271 fileFilter.count("*") != 1 |
|
272 ): |
|
273 E5MessageBox.critical( |
|
274 self, |
|
275 self.tr("Add File Filter"), |
|
276 self.tr("""A Save File Filter must contain exactly one""" |
|
277 """ wildcard pattern. Yours contains {0}.""") |
|
278 .format(fileFilter.count("*"))) |
|
279 return False |
|
280 |
|
281 if fileFilter.count("*") == 0: |
|
282 E5MessageBox.critical( |
|
283 self, |
|
284 self.tr("Add File Filter"), |
|
285 self.tr("""A File Filter must contain at least one""" |
|
286 """ wildcard pattern.""")) |
|
287 return False |
|
288 |
|
289 return True |
|
290 |
|
291 @pyqtSlot() |
|
292 def on_addFileFilterButton_clicked(self): |
|
293 """ |
|
294 Private slot to add a file filter to the list. |
|
295 """ |
|
296 fileFilter, ok = QInputDialog.getText( |
|
297 self, |
|
298 self.tr("Add File Filter"), |
|
299 self.tr("Enter the file filter entry:"), |
|
300 QLineEdit.EchoMode.Normal) |
|
301 if ok and fileFilter and self.__checkFileFilter(fileFilter): |
|
302 self.fileFiltersList.addItem(fileFilter) |
|
303 self.__extractFileFilters() |
|
304 self.__setDefaultFiltersLists(keepSelection=True) |
|
305 |
|
306 @pyqtSlot() |
|
307 def on_editFileFilterButton_clicked(self): |
|
308 """ |
|
309 Private slot called to edit a file filter entry. |
|
310 """ |
|
311 fileFilter = self.fileFiltersList.currentItem().text() |
|
312 fileFilter, ok = QInputDialog.getText( |
|
313 self, |
|
314 self.tr("Add File Filter"), |
|
315 self.tr("Enter the file filter entry:"), |
|
316 QLineEdit.EchoMode.Normal, |
|
317 fileFilter) |
|
318 if ok and fileFilter and self.__checkFileFilter(fileFilter): |
|
319 self.fileFiltersList.currentItem().setText(fileFilter) |
|
320 self.__extractFileFilters() |
|
321 self.__setDefaultFiltersLists(keepSelection=True) |
|
322 |
|
323 @pyqtSlot() |
|
324 def on_deleteFileFilterButton_clicked(self): |
|
325 """ |
|
326 Private slot called to delete a file filter entry. |
|
327 """ |
|
328 self.fileFiltersList.takeItem(self.fileFiltersList.currentRow()) |
|
329 self.__extractFileFilters() |
|
330 self.__setDefaultFiltersLists(keepSelection=True) |
|
331 |
|
332 @pyqtSlot(bool) |
|
333 def on_openFiltersButton_toggled(self, checked): |
|
334 """ |
|
335 Private slot to switch the list of file filters. |
|
336 |
|
337 @param checked flag indicating the check state of the button (boolean) |
|
338 """ |
|
339 self.__extractFileFilters() |
|
340 self.__showsOpenFilters = checked |
|
341 self.fileFiltersList.clear() |
|
342 if checked: |
|
343 self.fileFiltersList.addItems(self.openFileFilters) |
|
344 else: |
|
345 self.fileFiltersList.addItems(self.saveFileFilters) |
|
346 |
|
347 @pyqtSlot(QListWidgetItem, QListWidgetItem) |
|
348 def on_fileFiltersList_currentItemChanged(self, current, previous): |
|
349 """ |
|
350 Private slot to set the state of the edit and delete buttons. |
|
351 |
|
352 @param current new current item (QListWidgetItem) |
|
353 @param previous previous current item (QListWidgetItem) |
|
354 """ |
|
355 self.editFileFilterButton.setEnabled(current is not None) |
|
356 self.deleteFileFilterButton.setEnabled(current is not None) |
|
357 |
|
358 @pyqtSlot() |
|
359 def on_previewMarkdownPyMdownInstallPushButton_clicked(self): |
|
360 """ |
|
361 Private slot to install the pymdown extensions package via pip. |
|
362 """ |
|
363 pip = e5App().getObject("Pip") |
|
364 pip.installPackages(["pymdown-extensions"], interpreter=sys.executable) |
|
365 self.polishPage() |
|
366 |
|
367 def polishPage(self): |
|
368 """ |
|
369 Public slot to perform some polishing actions. |
|
370 """ |
|
371 try: |
|
372 import pymdownx # __IGNORE_WARNING__ |
|
373 self.previewMarkdownPyMdownInstallPushButton.setEnabled(False) |
|
374 del sys.modules["pymdownx"] |
|
375 except ImportError: |
|
376 self.previewMarkdownPyMdownInstallPushButton.setEnabled(True) |
|
377 |
|
378 |
|
379 def create(dlg): |
|
380 """ |
|
381 Module function to create the configuration page. |
|
382 |
|
383 @param dlg reference to the configuration dialog |
|
384 @return reference to the instantiated page (ConfigurationPageBase) |
|
385 """ |
|
386 page = EditorFilePage() |
|
387 return page |