QScintilla/MiniEditor.py

changeset 6101
b854a825d483
parent 6073
a679240821cb
child 6105
cbd34d558bd9
equal deleted inserted replaced
6100:63d6350f3a34 6101:b854a825d483
32 from Globals import isMacPlatform 32 from Globals import isMacPlatform
33 33
34 import Utilities 34 import Utilities
35 import Preferences 35 import Preferences
36 36
37 from ThirdParty.EditorConfig import editorconfig
38
37 39
38 class MiniScintilla(QsciScintillaCompat): 40 class MiniScintilla(QsciScintillaCompat):
39 """ 41 """
40 Class implementing a QsciScintillaCompat subclass for handling focus 42 Class implementing a QsciScintillaCompat subclass for handling focus
41 events. 43 events.
118 120
119 self.__textEdit = MiniScintilla(self) 121 self.__textEdit = MiniScintilla(self)
120 self.__textEdit.clearSearchIndicators = self.clearSearchIndicators 122 self.__textEdit.clearSearchIndicators = self.clearSearchIndicators
121 self.__textEdit.setSearchIndicator = self.setSearchIndicator 123 self.__textEdit.setSearchIndicator = self.setSearchIndicator
122 self.__textEdit.setUtf8(True) 124 self.__textEdit.setUtf8(True)
123 self.encoding = Preferences.getEditor("DefaultEncoding") 125
124 126
125 self.srHistory = { 127 self.srHistory = {
126 "search": [], 128 "search": [],
127 "replace": [] 129 "replace": []
128 } 130 }
182 self.__textEdit.selectionChanged.connect( 184 self.__textEdit.selectionChanged.connect(
183 self.__searchWidget.selectionChanged) 185 self.__searchWidget.selectionChanged)
184 self.__textEdit.selectionChanged.connect( 186 self.__textEdit.selectionChanged.connect(
185 self.__replaceWidget.selectionChanged) 187 self.__replaceWidget.selectionChanged)
186 188
187 self.__setCurrentFile("")
188 if filename: 189 if filename:
189 self.__loadFile(filename, filetype) 190 self.__loadFile(filename, filetype)
191 else:
192 self.__setCurrentFile("")
193 self.encoding = self.__getEditorConfig("DefaultEncoding")
190 194
191 self.__checkActions() 195 self.__checkActions()
192 196
193 def closeEvent(self, event): 197 def closeEvent(self, event):
194 """ 198 """
250 Private slot to save a copy of the file with a new name. 254 Private slot to save a copy of the file with a new name.
251 """ 255 """
252 fileName = E5FileDialog.getSaveFileName(self) 256 fileName = E5FileDialog.getSaveFileName(self)
253 if not fileName: 257 if not fileName:
254 return 258 return
255 259
256 QApplication.setOverrideCursor(Qt.WaitCursor) 260 self.__writeFile(fileName)
257 txt = self.__textEdit.text()
258 try:
259 self.encoding = Utilities.writeEncodedFile(
260 fileName, txt, self.encoding)
261 except (IOError, Utilities.CodingError, UnicodeError) as why:
262 E5MessageBox.critical(
263 self, self.tr('Save File'),
264 self.tr('<p>The file <b>{0}</b> could not be saved.<br/>'
265 'Reason: {1}</p>')
266 .format(fileName, str(why)))
267 QApplication.restoreOverrideCursor()
268 return
269
270 QApplication.restoreOverrideCursor()
271 self.__statusBar.showMessage(self.tr("File saved"), 2000)
272
273 return
274 261
275 def __about(self): 262 def __about(self):
276 """ 263 """
277 Private slot to show a little About message. 264 Private slot to show a little About message.
278 """ 265 """
2302 Private method to load the given file. 2289 Private method to load the given file.
2303 2290
2304 @param fileName name of the file to load (string) 2291 @param fileName name of the file to load (string)
2305 @param filetype type of the source file (string) 2292 @param filetype type of the source file (string)
2306 """ 2293 """
2294 self.__loadEditorConfig(fileName=fileName)
2295
2307 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) 2296 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
2308 2297
2309 try: 2298 try:
2310 txt, self.encoding = Utilities.readEncodedFile(fileName) 2299 encoding = self.__getEditorConfig("DefaultEncoding",
2300 nodefault=True)
2301 if encoding:
2302 txt, self.encoding = Utilities.readEncodedFileWithEncoding(
2303 fileName, encoding)
2304 else:
2305 txt, self.encoding = Utilities.readEncodedFile(fileName)
2311 except (UnicodeDecodeError, IOError) as why: 2306 except (UnicodeDecodeError, IOError) as why:
2312 QApplication.restoreOverrideCursor() 2307 QApplication.restoreOverrideCursor()
2313 E5MessageBox.critical( 2308 E5MessageBox.critical(
2314 self, self.tr('Open File'), 2309 self, self.tr('Open File'),
2315 self.tr('<p>The file <b>{0}</b> could not be opened.</p>' 2310 self.tr('<p>The file <b>{0}</b> could not be opened.</p>'
2326 else: 2321 else:
2327 self.filetype = filetype 2322 self.filetype = filetype
2328 self.__setCurrentFile(fileName) 2323 self.__setCurrentFile(fileName)
2329 2324
2330 fileEol = self.__textEdit.detectEolString(txt) 2325 fileEol = self.__textEdit.detectEolString(txt)
2326 # TODO: editorconfig: end_of_line
2331 self.__textEdit.setEolModeByEolString(fileEol) 2327 self.__textEdit.setEolModeByEolString(fileEol)
2332 2328
2333 self.__statusBar.showMessage(self.tr("File loaded"), 2000) 2329 self.__statusBar.showMessage(self.tr("File loaded"), 2000)
2334 2330
2335 def __saveFile(self, fileName): 2331 def __saveFile(self, fileName):
2336 """ 2332 """
2337 Private method to save to the given file. 2333 Private method to save to the given file.
2338 2334
2339 @param fileName name of the file to save to (string) 2335 @param fileName name of the file to save to
2340 @return flag indicating success (boolean) 2336 @type str
2341 """ 2337 @return flag indicating success
2338 @rtype bool
2339 """
2340 res = self.__writeFile(fileName)
2341
2342 if res:
2343 self.editorSaved.emit()
2344 self.__setCurrentFile(fileName)
2345
2346 self.__checkActions()
2347
2348 return res
2349
2350 def __writeFile(self, fileName):
2351 """
2352 Private method to write the current editor text to a file.
2353
2354 @param fileName name of the file to be written to
2355 @type str
2356 @return flag indicating success
2357 @rtype bool
2358 """
2359 # TODO: editorconfig: apply end_of_line, trim_trailing_whitespace,
2360 # insert_final_newline
2361 config = self.__loadEditorConfigObject(fileName)
2362
2342 QApplication.setOverrideCursor(Qt.WaitCursor) 2363 QApplication.setOverrideCursor(Qt.WaitCursor)
2343 txt = self.__textEdit.text() 2364 txt = self.__textEdit.text()
2365 # TODO: editorconfig: insert_final_newline
2344 try: 2366 try:
2367 editorConfigEncoding = self.__getEditorConfig(
2368 "DefaultEncoding", nodefault=True, config=config)
2345 self.encoding = Utilities.writeEncodedFile( 2369 self.encoding = Utilities.writeEncodedFile(
2346 fileName, txt, self.encoding) 2370 fileName, txt, self.encoding,
2371 forcedEncoding=editorConfigEncoding)
2347 except (IOError, Utilities.CodingError, UnicodeError) as why: 2372 except (IOError, Utilities.CodingError, UnicodeError) as why:
2373 QApplication.restoreOverrideCursor()
2348 E5MessageBox.critical( 2374 E5MessageBox.critical(
2349 self, self.tr('Save File'), 2375 self, self.tr('Save File'),
2350 self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' 2376 self.tr('<p>The file <b>{0}</b> could not be saved.<br/>'
2351 'Reason: {1}</p>') 2377 'Reason: {1}</p>')
2352 .format(fileName, str(why))) 2378 .format(fileName, str(why)))
2353 QApplication.restoreOverrideCursor()
2354
2355 self.__checkActions()
2356
2357 return False 2379 return False
2358 2380
2359 QApplication.restoreOverrideCursor() 2381 QApplication.restoreOverrideCursor()
2360 self.editorSaved.emit()
2361
2362 self.__setCurrentFile(fileName)
2363 self.__statusBar.showMessage(self.tr("File saved"), 2000) 2382 self.__statusBar.showMessage(self.tr("File saved"), 2000)
2364 2383
2365 self.__checkActions()
2366
2367 return True 2384 return True
2368 2385
2369 def __setCurrentFile(self, fileName): 2386 def __setCurrentFile(self, fileName):
2370 """ 2387 """
2371 Private method to register the file name of the current file. 2388 Private method to register the file name of the current file.
2372 2389
2373 @param fileName name of the file to register (string) 2390 @param fileName name of the file to register (string)
2384 2401
2385 self.__textEdit.setModified(False) 2402 self.__textEdit.setModified(False)
2386 self.setWindowModified(False) 2403 self.setWindowModified(False)
2387 2404
2388 self.setLanguage(self.__bindName(self.__textEdit.text(0))) 2405 self.setLanguage(self.__bindName(self.__textEdit.text(0)))
2406
2407 self.__loadEditorConfig()
2389 2408
2390 def getFileName(self): 2409 def getFileName(self):
2391 """ 2410 """
2392 Public method to return the name of the file being displayed. 2411 Public method to return the name of the file being displayed.
2393 2412
2504 2523
2505 def __setTextDisplay(self): 2524 def __setTextDisplay(self):
2506 """ 2525 """
2507 Private method to configure the text display. 2526 Private method to configure the text display.
2508 """ 2527 """
2528 # TODO: editorconfig: move these to separate method called, when
2529 # EditorConfig has been loaded
2530 # TODO: editorconfig: tab_width
2509 self.__textEdit.setTabWidth(Preferences.getEditor("TabWidth")) 2531 self.__textEdit.setTabWidth(Preferences.getEditor("TabWidth"))
2532 # TODO: editorconfig: indent_size
2510 self.__textEdit.setIndentationWidth( 2533 self.__textEdit.setIndentationWidth(
2511 Preferences.getEditor("IndentWidth")) 2534 Preferences.getEditor("IndentWidth"))
2535 # TODO: editorconfig: indent_style
2512 if self.lexer_ and self.lexer_.alwaysKeepTabs(): 2536 if self.lexer_ and self.lexer_.alwaysKeepTabs():
2513 self.__textEdit.setIndentationsUseTabs(True) 2537 self.__textEdit.setIndentationsUseTabs(True)
2514 else: 2538 else:
2515 self.__textEdit.setIndentationsUseTabs( 2539 self.__textEdit.setIndentationsUseTabs(
2516 Preferences.getEditor("TabForIndentation")) 2540 Preferences.getEditor("TabForIndentation"))
2608 2632
2609 def __setEolMode(self): 2633 def __setEolMode(self):
2610 """ 2634 """
2611 Private method to configure the eol mode of the editor. 2635 Private method to configure the eol mode of the editor.
2612 """ 2636 """
2637 # TODO: editorconfig: end_of_line
2613 eolMode = Preferences.getEditor("EOLMode") 2638 eolMode = Preferences.getEditor("EOLMode")
2614 eolMode = QsciScintilla.EolMode(eolMode) 2639 eolMode = QsciScintilla.EolMode(eolMode)
2615 self.__textEdit.setEolMode(eolMode) 2640 self.__textEdit.setEolMode(eolMode)
2616 2641
2617 def __setMonospaced(self, on): 2642 def __setMonospaced(self, on):
3237 if filetype is None: 3262 if filetype is None:
3238 self.filetype = "" 3263 self.filetype = ""
3239 else: 3264 else:
3240 self.filetype = filetype 3265 self.filetype = filetype
3241 3266
3267 # TODO: editorconfig: end_of_line
3242 fileEol = self.__textEdit.detectEolString(txt) 3268 fileEol = self.__textEdit.detectEolString(txt)
3243 self.__textEdit.setEolModeByEolString(fileEol) 3269 self.__textEdit.setEolModeByEolString(fileEol)
3244 3270
3245 self.__textEdit.setModified(False) 3271 self.__textEdit.setModified(False)
3272
3273 #######################################################################
3274 ## Methods implementing the interface to EditorConfig
3275 #######################################################################
3276
3277 def __loadEditorConfig(self, fileName=""):
3278 """
3279 Private method to load the EditorConfig properties.
3280
3281 @param fileName name of the file
3282 @type str
3283 """
3284 if not fileName:
3285 fileName = self.__curFile
3286
3287 self.__editorConfig = self.__loadEditorConfigObject(fileName)
3288
3289 def __loadEditorConfigObject(self, fileName):
3290 """
3291 Private method to load the EditorConfig properties for the given
3292 file name.
3293
3294 @param fileName name of the file
3295 @type str
3296 @return EditorConfig dictionary
3297 @rtype dict
3298 """
3299 editorConfig = {}
3300
3301 if fileName:
3302 try:
3303 editorConfig = editorconfig.get_properties(fileName)
3304 except editorconfig.EditorConfigError:
3305 E5MessageBox.warning(
3306 self,
3307 self.tr("EditorConfig Properties"),
3308 self.tr("""<p>The EditorConfig properties for file"""
3309 """ <b>{0}</b> could not be loaded.</p>""")
3310 .format(fileName))
3311
3312 return editorConfig
3313
3314 def __getEditorConfig(self, option, nodefault=False, config=None):
3315 """
3316 Private method to get the requested option via EditorConfig.
3317
3318 If there is no EditorConfig defined, the equivalent built-in option
3319 will be used (Preferences.getEditor(). The option must be given as the
3320 Preferences option key. The mapping to the EditorConfig option name
3321 will be done within this method.
3322
3323 @param option Preferences option key
3324 @type str
3325 @param nodefault flag indicating to not get the default value from
3326 Preferences but return None instead
3327 @type bool
3328 @param config reference to an EditorConfig object or None
3329 @type dict
3330 @return value of requested setting or None if nothing was found and
3331 nodefault parameter was True
3332 @rtype any
3333 """
3334 if config is None:
3335 config = self.__editorConfig
3336
3337 if not config:
3338 if nodefault:
3339 return None
3340 else:
3341 return Preferences.getEditor(option)
3342
3343 try:
3344 if option == "EOLMode":
3345 value = config["end_of_line"]
3346 if value == "lf":
3347 value = QsciScintilla.EolUnix
3348 elif value == "crlf":
3349 value = QsciScintilla.EolWindows
3350 elif value == "cr":
3351 value = QsciScintilla.EolMac
3352 else:
3353 value = None
3354 elif option == "DefaultEncoding":
3355 value = config["charset"]
3356 except KeyError:
3357 value = None
3358
3359 if value is None and not nodefault:
3360 # use Preferences in case of error
3361 value = Preferences.getEditor(option)
3362
3363 return value

eric ide

mercurial