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