267 # true if we are in drop mode |
276 # true if we are in drop mode |
268 self.inLinesChanged = False |
277 self.inLinesChanged = False |
269 # true if we are propagating a lines changed event |
278 # true if we are propagating a lines changed event |
270 self.__hasTaskMarkers = False |
279 self.__hasTaskMarkers = False |
271 # no task markers present |
280 # no task markers present |
272 |
281 |
273 self.macros = {} # list of defined macros |
282 self.macros = {} # list of defined macros |
274 self.curMacro = None |
283 self.curMacro = None |
275 self.recording = False |
284 self.recording = False |
276 |
285 |
277 self.acAPI = False |
286 self.acAPI = False |
278 |
287 |
279 self.__lastEditPosition = None |
288 self.__lastEditPosition = None |
280 self.__annotationLines = 0 |
289 self.__annotationLines = 0 |
281 |
290 |
282 self.__docstringGenerator = None |
291 self.__docstringGenerator = None |
283 |
292 |
284 # list of clones |
293 # list of clones |
285 self.__clones = [] |
294 self.__clones = [] |
286 |
295 |
287 # clear QScintilla defined keyboard commands |
296 # clear QScintilla defined keyboard commands |
288 # we do our own handling through the view manager |
297 # we do our own handling through the view manager |
289 self.clearAlternateKeys() |
298 self.clearAlternateKeys() |
290 self.clearKeys() |
299 self.clearKeys() |
291 |
300 |
292 self.__markerMap = EditorMarkerMap(self) |
301 self.__markerMap = EditorMarkerMap(self) |
293 |
302 |
294 # initialize the mark occurrences timer |
303 # initialize the mark occurrences timer |
295 self.__markOccurrencesTimer = QTimer(self) |
304 self.__markOccurrencesTimer = QTimer(self) |
296 self.__markOccurrencesTimer.setSingleShot(True) |
305 self.__markOccurrencesTimer.setSingleShot(True) |
297 self.__markOccurrencesTimer.setInterval( |
306 self.__markOccurrencesTimer.setInterval( |
298 Preferences.getEditor("MarkOccurrencesTimeout")) |
307 Preferences.getEditor("MarkOccurrencesTimeout") |
|
308 ) |
299 self.__markOccurrencesTimer.timeout.connect(self.__markOccurrences) |
309 self.__markOccurrencesTimer.timeout.connect(self.__markOccurrences) |
300 self.__markedText = "" |
310 self.__markedText = "" |
301 self.__searchIndicatorLines = [] |
311 self.__searchIndicatorLines = [] |
302 |
312 |
303 # initialize some spellchecking stuff |
313 # initialize some spellchecking stuff |
304 self.spell = None |
314 self.spell = None |
305 self.lastLine = 0 |
315 self.lastLine = 0 |
306 self.lastIndex = 0 |
316 self.lastIndex = 0 |
307 self.__inSpellLanguageChanged = False |
317 self.__inSpellLanguageChanged = False |
308 |
318 |
309 # initialize some cooperation stuff |
319 # initialize some cooperation stuff |
310 self.__isSyncing = False |
320 self.__isSyncing = False |
311 self.__receivedWhileSyncing = [] |
321 self.__receivedWhileSyncing = [] |
312 self.__savedText = "" |
322 self.__savedText = "" |
313 self.__inSharedEdit = False |
323 self.__inSharedEdit = False |
314 self.__isShared = False |
324 self.__isShared = False |
315 self.__inRemoteSharedEdit = False |
325 self.__inRemoteSharedEdit = False |
316 |
326 |
317 # connect signals before loading the text |
327 # connect signals before loading the text |
318 self.modificationChanged.connect(self.__modificationChanged) |
328 self.modificationChanged.connect(self.__modificationChanged) |
319 self.cursorPositionChanged.connect(self.__cursorPositionChanged) |
329 self.cursorPositionChanged.connect(self.__cursorPositionChanged) |
320 self.modificationAttempted.connect(self.__modificationReadOnly) |
330 self.modificationAttempted.connect(self.__modificationReadOnly) |
321 |
331 |
322 # define the margins markers |
332 # define the margins markers |
323 self.__changeMarkerSaved = self.markerDefine( |
333 self.__changeMarkerSaved = self.markerDefine( |
324 self.__createChangeMarkerPixmap( |
334 self.__createChangeMarkerPixmap("OnlineChangeTraceMarkerSaved") |
325 "OnlineChangeTraceMarkerSaved")) |
335 ) |
326 self.__changeMarkerUnsaved = self.markerDefine( |
336 self.__changeMarkerUnsaved = self.markerDefine( |
327 self.__createChangeMarkerPixmap( |
337 self.__createChangeMarkerPixmap("OnlineChangeTraceMarkerUnsaved") |
328 "OnlineChangeTraceMarkerUnsaved")) |
338 ) |
329 self.breakpoint = self.markerDefine( |
339 self.breakpoint = self.markerDefine(UI.PixmapCache.getPixmap("break")) |
330 UI.PixmapCache.getPixmap("break")) |
340 self.cbreakpoint = self.markerDefine(UI.PixmapCache.getPixmap("cBreak")) |
331 self.cbreakpoint = self.markerDefine( |
341 self.tbreakpoint = self.markerDefine(UI.PixmapCache.getPixmap("tBreak")) |
332 UI.PixmapCache.getPixmap("cBreak")) |
342 self.tcbreakpoint = self.markerDefine(UI.PixmapCache.getPixmap("tCBreak")) |
333 self.tbreakpoint = self.markerDefine( |
343 self.dbreakpoint = self.markerDefine(UI.PixmapCache.getPixmap("breakDisabled")) |
334 UI.PixmapCache.getPixmap("tBreak")) |
344 self.bookmark = self.markerDefine(UI.PixmapCache.getPixmap("bookmark16")) |
335 self.tcbreakpoint = self.markerDefine( |
345 self.syntaxerror = self.markerDefine(UI.PixmapCache.getPixmap("syntaxError")) |
336 UI.PixmapCache.getPixmap("tCBreak")) |
346 self.notcovered = self.markerDefine(UI.PixmapCache.getPixmap("notcovered")) |
337 self.dbreakpoint = self.markerDefine( |
347 self.taskmarker = self.markerDefine(UI.PixmapCache.getPixmap("task")) |
338 UI.PixmapCache.getPixmap("breakDisabled")) |
348 self.warning = self.markerDefine(UI.PixmapCache.getPixmap("warning")) |
339 self.bookmark = self.markerDefine( |
349 |
340 UI.PixmapCache.getPixmap("bookmark16")) |
|
341 self.syntaxerror = self.markerDefine( |
|
342 UI.PixmapCache.getPixmap("syntaxError")) |
|
343 self.notcovered = self.markerDefine( |
|
344 UI.PixmapCache.getPixmap("notcovered")) |
|
345 self.taskmarker = self.markerDefine( |
|
346 UI.PixmapCache.getPixmap("task")) |
|
347 self.warning = self.markerDefine( |
|
348 UI.PixmapCache.getPixmap("warning")) |
|
349 |
|
350 # define the line markers |
350 # define the line markers |
351 if Preferences.getEditor("LineMarkersBackground"): |
351 if Preferences.getEditor("LineMarkersBackground"): |
|
352 self.currentline = self.markerDefine(QsciScintilla.MarkerSymbol.Background) |
|
353 self.errorline = self.markerDefine(QsciScintilla.MarkerSymbol.Background) |
|
354 self.__setLineMarkerColours() |
|
355 else: |
352 self.currentline = self.markerDefine( |
356 self.currentline = self.markerDefine( |
353 QsciScintilla.MarkerSymbol.Background) |
357 UI.PixmapCache.getPixmap("currentLineMarker") |
|
358 ) |
354 self.errorline = self.markerDefine( |
359 self.errorline = self.markerDefine( |
355 QsciScintilla.MarkerSymbol.Background) |
360 UI.PixmapCache.getPixmap("errorLineMarker") |
356 self.__setLineMarkerColours() |
361 ) |
357 else: |
362 |
358 self.currentline = self.markerDefine( |
|
359 UI.PixmapCache.getPixmap("currentLineMarker")) |
|
360 self.errorline = self.markerDefine( |
|
361 UI.PixmapCache.getPixmap("errorLineMarker")) |
|
362 |
|
363 self.breakpointMask = ( |
363 self.breakpointMask = ( |
364 (1 << self.breakpoint) | |
364 (1 << self.breakpoint) |
365 (1 << self.cbreakpoint) | |
365 | (1 << self.cbreakpoint) |
366 (1 << self.tbreakpoint) | |
366 | (1 << self.tbreakpoint) |
367 (1 << self.tcbreakpoint) | |
367 | (1 << self.tcbreakpoint) |
368 (1 << self.dbreakpoint) |
368 | (1 << self.dbreakpoint) |
369 ) |
369 ) |
370 |
370 |
371 self.changeMarkersMask = ( |
371 self.changeMarkersMask = (1 << self.__changeMarkerSaved) | ( |
372 (1 << self.__changeMarkerSaved) | |
372 1 << self.__changeMarkerUnsaved |
373 (1 << self.__changeMarkerUnsaved) |
373 ) |
374 ) |
374 |
375 |
|
376 # configure the margins |
375 # configure the margins |
377 self.__setMarginsDisplay() |
376 self.__setMarginsDisplay() |
378 self.linesChanged.connect(self.__resizeLinenoMargin) |
377 self.linesChanged.connect(self.__resizeLinenoMargin) |
379 |
378 |
380 self.marginClicked.connect(self.__marginClicked) |
379 self.marginClicked.connect(self.__marginClicked) |
381 |
380 |
382 # set the eol mode |
381 # set the eol mode |
383 self.__setEolMode() |
382 self.__setEolMode() |
384 |
383 |
385 # set the text display |
384 # set the text display |
386 self.__setTextDisplay() |
385 self.__setTextDisplay() |
387 |
386 |
388 # initialize the online syntax check timer |
387 # initialize the online syntax check timer |
389 try: |
388 try: |
390 self.syntaxCheckService = ericApp().getObject('SyntaxCheckService') |
389 self.syntaxCheckService = ericApp().getObject("SyntaxCheckService") |
391 self.syntaxCheckService.syntaxChecked.connect( |
390 self.syntaxCheckService.syntaxChecked.connect( |
392 self.__processSyntaxCheckResult) |
391 self.__processSyntaxCheckResult |
393 self.syntaxCheckService.error.connect( |
392 ) |
394 self.__processSyntaxCheckError) |
393 self.syntaxCheckService.error.connect(self.__processSyntaxCheckError) |
395 self.__initOnlineSyntaxCheck() |
394 self.__initOnlineSyntaxCheck() |
396 except KeyError: |
395 except KeyError: |
397 self.syntaxCheckService = None |
396 self.syntaxCheckService = None |
398 |
397 |
399 self.isResourcesFile = False |
398 self.isResourcesFile = False |
400 if editor is None: |
399 if editor is None: |
401 if self.fileName: |
400 if self.fileName: |
402 if ( |
401 if ( |
403 (pathlib.Path(self.fileName).stat().st_size // 1024) > |
402 pathlib.Path(self.fileName).stat().st_size // 1024 |
404 Preferences.getEditor("WarnFilesize") |
403 ) > Preferences.getEditor("WarnFilesize"): |
405 ): |
|
406 res = EricMessageBox.yesNo( |
404 res = EricMessageBox.yesNo( |
407 self, |
405 self, |
408 self.tr("Open File"), |
406 self.tr("Open File"), |
409 self.tr("""<p>The size of the file <b>{0}</b>""" |
407 self.tr( |
410 """ is <b>{1} KB</b>.""" |
408 """<p>The size of the file <b>{0}</b>""" |
411 """ Do you really want to load it?</p>""") |
409 """ is <b>{1} KB</b>.""" |
412 .format( |
410 """ Do you really want to load it?</p>""" |
|
411 ).format( |
413 self.fileName, |
412 self.fileName, |
414 pathlib.Path(self.fileName).stat().st_size // 1024 |
413 pathlib.Path(self.fileName).stat().st_size // 1024, |
415 ), |
414 ), |
416 icon=EricMessageBox.Warning) |
415 icon=EricMessageBox.Warning, |
|
416 ) |
417 if not res: |
417 if not res: |
418 raise OSError() |
418 raise OSError() |
419 self.readFile(self.fileName, True) |
419 self.readFile(self.fileName, True) |
420 self.__bindLexer(self.fileName) |
420 self.__bindLexer(self.fileName) |
421 self.__bindCompleter(self.fileName) |
421 self.__bindCompleter(self.fileName) |
422 self.checkSyntax() |
422 self.checkSyntax() |
423 self.isResourcesFile = self.fileName.endswith(".qrc") |
423 self.isResourcesFile = self.fileName.endswith(".qrc") |
424 |
424 |
425 self.__convertTabs() |
425 self.__convertTabs() |
426 |
426 |
427 self.recolor() |
427 self.recolor() |
428 else: |
428 else: |
429 # clone the given editor |
429 # clone the given editor |
430 self.setDocument(editor.document()) |
430 self.setDocument(editor.document()) |
431 self.breaks = editor.breaks |
431 self.breaks = editor.breaks |
433 self.syntaxerrors = editor.syntaxerrors |
433 self.syntaxerrors = editor.syntaxerrors |
434 self.notcoveredMarkers = editor.notcoveredMarkers |
434 self.notcoveredMarkers = editor.notcoveredMarkers |
435 self.showingNotcoveredMarkers = editor.showingNotcoveredMarkers |
435 self.showingNotcoveredMarkers = editor.showingNotcoveredMarkers |
436 self.isResourcesFile = editor.isResourcesFile |
436 self.isResourcesFile = editor.isResourcesFile |
437 self.lastModified = editor.lastModified |
437 self.lastModified = editor.lastModified |
438 |
438 |
439 self.addClone(editor) |
439 self.addClone(editor) |
440 editor.addClone(self) |
440 editor.addClone(self) |
441 |
441 |
442 self.gotoLine(1) |
442 self.gotoLine(1) |
443 |
443 |
444 # connect the mouse hover signals |
444 # connect the mouse hover signals |
445 self.SCN_DWELLSTART.connect(self.__showMouseHoverHelp) |
445 self.SCN_DWELLSTART.connect(self.__showMouseHoverHelp) |
446 self.SCN_DWELLEND.connect(self.__cancelMouseHoverHelp) |
446 self.SCN_DWELLEND.connect(self.__cancelMouseHoverHelp) |
447 self.__mouseHoverHelp = None |
447 self.__mouseHoverHelp = None |
448 self.__showingMouseHoverHelp = False |
448 self.__showingMouseHoverHelp = False |
449 |
449 |
450 # set the text display again |
450 # set the text display again |
451 self.__setTextDisplay() |
451 self.__setTextDisplay() |
452 |
452 |
453 # set the auto-completion function |
453 # set the auto-completion function |
454 self.__acContext = True |
454 self.__acContext = True |
455 self.__acText = "" |
455 self.__acText = "" |
456 self.__acCompletions = set() |
456 self.__acCompletions = set() |
457 self.__acCompletionsFinished = 0 |
457 self.__acCompletionsFinished = 0 |
458 self.__acCache = EricCache( |
458 self.__acCache = EricCache( |
459 size=Preferences.getEditor("AutoCompletionCacheSize")) |
459 size=Preferences.getEditor("AutoCompletionCacheSize") |
|
460 ) |
460 self.__acCache.setMaximumCacheTime( |
461 self.__acCache.setMaximumCacheTime( |
461 Preferences.getEditor("AutoCompletionCacheTime")) |
462 Preferences.getEditor("AutoCompletionCacheTime") |
462 self.__acCacheEnabled = Preferences.getEditor( |
463 ) |
463 "AutoCompletionCacheEnabled") |
464 self.__acCacheEnabled = Preferences.getEditor("AutoCompletionCacheEnabled") |
464 self.__acTimer = QTimer(self) |
465 self.__acTimer = QTimer(self) |
465 self.__acTimer.setSingleShot(True) |
466 self.__acTimer.setSingleShot(True) |
466 self.__acTimer.setInterval( |
467 self.__acTimer.setInterval(Preferences.getEditor("AutoCompletionTimeout")) |
467 Preferences.getEditor("AutoCompletionTimeout")) |
|
468 self.__acTimer.timeout.connect(self.__autoComplete) |
468 self.__acTimer.timeout.connect(self.__autoComplete) |
469 |
469 |
470 self.__acWatchdog = QTimer(self) |
470 self.__acWatchdog = QTimer(self) |
471 self.__acWatchdog.setSingleShot(True) |
471 self.__acWatchdog.setSingleShot(True) |
472 self.__acWatchdog.setInterval( |
472 self.__acWatchdog.setInterval( |
473 Preferences.getEditor("AutoCompletionWatchdogTime")) |
473 Preferences.getEditor("AutoCompletionWatchdogTime") |
|
474 ) |
474 self.__acWatchdog.timeout.connect(self.autoCompleteQScintilla) |
475 self.__acWatchdog.timeout.connect(self.autoCompleteQScintilla) |
475 |
476 |
476 self.userListActivated.connect(self.__completionListSelected) |
477 self.userListActivated.connect(self.__completionListSelected) |
477 self.SCN_CHARADDED.connect(self.__charAdded) |
478 self.SCN_CHARADDED.connect(self.__charAdded) |
478 self.SCN_AUTOCCANCELLED.connect(self.__autocompletionCancelled) |
479 self.SCN_AUTOCCANCELLED.connect(self.__autocompletionCancelled) |
479 |
480 |
480 self.__completionListHookFunctions = {} |
481 self.__completionListHookFunctions = {} |
481 self.__completionListAsyncHookFunctions = {} |
482 self.__completionListAsyncHookFunctions = {} |
482 self.__setAutoCompletion() |
483 self.__setAutoCompletion() |
483 |
484 |
484 # set the call-tips function |
485 # set the call-tips function |
485 self.__ctHookFunctions = {} |
486 self.__ctHookFunctions = {} |
486 self.__setCallTips() |
487 self.__setCallTips() |
487 |
488 |
488 # set the mouse click handlers (fired on mouse release) |
489 # set the mouse click handlers (fired on mouse release) |
489 self.__mouseClickHandlers = {} |
490 self.__mouseClickHandlers = {} |
490 # dictionary with tuple of keyboard modifier and mouse button as key |
491 # dictionary with tuple of keyboard modifier and mouse button as key |
491 # and tuple of plug-in name and function as value |
492 # and tuple of plug-in name and function as value |
492 |
493 |
493 sh = self.sizeHint() |
494 sh = self.sizeHint() |
494 if sh.height() < 300: |
495 if sh.height() < 300: |
495 sh.setHeight(300) |
496 sh.setHeight(300) |
496 self.resize(sh) |
497 self.resize(sh) |
497 |
498 |
498 # Make sure tabbing through a QWorkspace works. |
499 # Make sure tabbing through a QWorkspace works. |
499 self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) |
500 self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) |
500 |
501 |
501 self.__updateReadOnly(True) |
502 self.__updateReadOnly(True) |
502 |
503 |
503 self.setWhatsThis(self.tr( |
504 self.setWhatsThis( |
504 """<b>A Source Editor Window</b>""" |
505 self.tr( |
505 """<p>This window is used to display and edit a source file.""" |
506 """<b>A Source Editor Window</b>""" |
506 """ You can open as many of these as you like. The name of the""" |
507 """<p>This window is used to display and edit a source file.""" |
507 """ file is displayed in the window's titlebar.</p>""" |
508 """ You can open as many of these as you like. The name of the""" |
508 """<p>In order to set breakpoints just click in the space""" |
509 """ file is displayed in the window's titlebar.</p>""" |
509 """ between the line numbers and the fold markers. Via the""" |
510 """<p>In order to set breakpoints just click in the space""" |
510 """ context menu of the margins they may be edited.</p>""" |
511 """ between the line numbers and the fold markers. Via the""" |
511 """<p>In order to set bookmarks just Shift click in the space""" |
512 """ context menu of the margins they may be edited.</p>""" |
512 """ between the line numbers and the fold markers.</p>""" |
513 """<p>In order to set bookmarks just Shift click in the space""" |
513 """<p>These actions can be reversed via the context menu.</p>""" |
514 """ between the line numbers and the fold markers.</p>""" |
514 """<p>Ctrl clicking on a syntax error marker shows some info""" |
515 """<p>These actions can be reversed via the context menu.</p>""" |
515 """ about this error.</p>""" |
516 """<p>Ctrl clicking on a syntax error marker shows some info""" |
516 )) |
517 """ about this error.</p>""" |
517 |
518 ) |
|
519 ) |
|
520 |
518 # Set the editors size, if it is too big for the view manager. |
521 # Set the editors size, if it is too big for the view manager. |
519 if self.vm is not None: |
522 if self.vm is not None: |
520 req = self.size() |
523 req = self.size() |
521 bnd = req.boundedTo(self.vm.size()) |
524 bnd = req.boundedTo(self.vm.size()) |
522 |
525 |
523 if bnd.width() < req.width() or bnd.height() < req.height(): |
526 if bnd.width() < req.width() or bnd.height() < req.height(): |
524 self.resize(bnd) |
527 self.resize(bnd) |
525 |
528 |
526 # set the autosave flag |
529 # set the autosave flag |
527 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0 |
530 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0 |
528 self.autosaveManuallyDisabled = False |
531 self.autosaveManuallyDisabled = False |
529 |
532 |
530 # code coverage related attributes |
533 # code coverage related attributes |
531 self.__coverageFile = "" |
534 self.__coverageFile = "" |
532 |
535 |
533 self.__initContextMenu() |
536 self.__initContextMenu() |
534 self.__initContextMenuMargins() |
537 self.__initContextMenuMargins() |
535 |
538 |
536 self.__checkEol() |
539 self.__checkEol() |
537 if editor is None: |
540 if editor is None: |
538 self.__checkLanguage() |
541 self.__checkLanguage() |
539 self.__checkEncoding() |
542 self.__checkEncoding() |
540 self.__checkSpellLanguage() |
543 self.__checkSpellLanguage() |
541 else: |
544 else: |
542 # it's a clone |
545 # it's a clone |
543 self.__languageChanged(editor.apiLanguage, propagate=False) |
546 self.__languageChanged(editor.apiLanguage, propagate=False) |
544 self.__encodingChanged(editor.encoding, propagate=False) |
547 self.__encodingChanged(editor.encoding, propagate=False) |
545 self.__spellLanguageChanged(editor.getSpellingLanguage(), |
548 self.__spellLanguageChanged(editor.getSpellingLanguage(), propagate=False) |
546 propagate=False) |
|
547 # link the warnings to the original editor |
549 # link the warnings to the original editor |
548 self.warnings = editor.warnings |
550 self.warnings = editor.warnings |
549 |
551 |
550 self.setAcceptDrops(True) |
552 self.setAcceptDrops(True) |
551 |
553 |
552 # breakpoint handling |
554 # breakpoint handling |
553 self.breakpointModel = self.dbs.getBreakPointModel() |
555 self.breakpointModel = self.dbs.getBreakPointModel() |
554 self.__restoreBreakpoints() |
556 self.__restoreBreakpoints() |
555 self.breakpointModel.rowsAboutToBeRemoved.connect( |
557 self.breakpointModel.rowsAboutToBeRemoved.connect(self.__deleteBreakPoints) |
556 self.__deleteBreakPoints) |
|
557 self.breakpointModel.dataAboutToBeChanged.connect( |
558 self.breakpointModel.dataAboutToBeChanged.connect( |
558 self.__breakPointDataAboutToBeChanged) |
559 self.__breakPointDataAboutToBeChanged |
559 self.breakpointModel.dataChanged.connect( |
560 ) |
560 self.__changeBreakPoints) |
561 self.breakpointModel.dataChanged.connect(self.__changeBreakPoints) |
561 self.breakpointModel.rowsInserted.connect( |
562 self.breakpointModel.rowsInserted.connect(self.__addBreakPoints) |
562 self.__addBreakPoints) |
|
563 self.SCN_MODIFIED.connect(self.__modified) |
563 self.SCN_MODIFIED.connect(self.__modified) |
564 |
564 |
565 # establish connection to some ViewManager action groups |
565 # establish connection to some ViewManager action groups |
566 self.addActions(self.vm.editorActGrp.actions()) |
566 self.addActions(self.vm.editorActGrp.actions()) |
567 self.addActions(self.vm.editActGrp.actions()) |
567 self.addActions(self.vm.editActGrp.actions()) |
568 self.addActions(self.vm.copyActGrp.actions()) |
568 self.addActions(self.vm.copyActGrp.actions()) |
569 self.addActions(self.vm.viewActGrp.actions()) |
569 self.addActions(self.vm.viewActGrp.actions()) |
570 |
570 |
571 # register images to be shown in autocompletion lists |
571 # register images to be shown in autocompletion lists |
572 self.__registerImages() |
572 self.__registerImages() |
573 |
573 |
574 # connect signals after loading the text |
574 # connect signals after loading the text |
575 self.textChanged.connect(self.__textChanged) |
575 self.textChanged.connect(self.__textChanged) |
576 |
576 |
577 # initialize the online change trace timer |
577 # initialize the online change trace timer |
578 self.__initOnlineChangeTrace() |
578 self.__initOnlineChangeTrace() |
579 |
579 |
580 if ( |
580 if ( |
581 self.fileName and |
581 self.fileName |
582 self.project.isOpen() and |
582 and self.project.isOpen() |
583 self.project.isProjectSource(self.fileName) |
583 and self.project.isProjectSource(self.fileName) |
584 ): |
584 ): |
585 self.project.projectPropertiesChanged.connect( |
585 self.project.projectPropertiesChanged.connect( |
586 self.__projectPropertiesChanged) |
586 self.__projectPropertiesChanged |
587 |
587 ) |
|
588 |
588 self.grabGesture(Qt.GestureType.PinchGesture) |
589 self.grabGesture(Qt.GestureType.PinchGesture) |
589 |
590 |
590 self.SCN_ZOOM.connect(self.__markerMap.update) |
591 self.SCN_ZOOM.connect(self.__markerMap.update) |
591 self.__markerMap.update() |
592 self.__markerMap.update() |
592 |
593 |
593 def __setFileName(self, name): |
594 def __setFileName(self, name): |
594 """ |
595 """ |
595 Private method to set the file name of the current file. |
596 Private method to set the file name of the current file. |
596 |
597 |
597 @param name name of the current file |
598 @param name name of the current file |
598 @type str |
599 @type str |
599 """ |
600 """ |
600 self.fileName = name |
601 self.fileName = name |
601 |
602 |
602 if self.fileName: |
603 if self.fileName: |
603 self.__fileNameExtension = ( |
604 self.__fileNameExtension = os.path.splitext(self.fileName)[1][1:].lower() |
604 os.path.splitext(self.fileName)[1][1:].lower() |
|
605 ) |
|
606 else: |
605 else: |
607 self.__fileNameExtension = "" |
606 self.__fileNameExtension = "" |
608 |
607 |
609 def __registerImages(self): |
608 def __registerImages(self): |
610 """ |
609 """ |
611 Private method to register images for autocompletion lists. |
610 Private method to register images for autocompletion lists. |
612 """ |
611 """ |
613 # finale size of the completion images |
612 # finale size of the completion images |
614 imageSize = QSize(22, 22) |
613 imageSize = QSize(22, 22) |
615 |
614 |
616 self.registerImage( |
615 self.registerImage(self.ClassID, UI.PixmapCache.getPixmap("class", imageSize)) |
617 self.ClassID, |
|
618 UI.PixmapCache.getPixmap("class", imageSize)) |
|
619 self.registerImage( |
616 self.registerImage( |
620 self.ClassProtectedID, |
617 self.ClassProtectedID, |
621 UI.PixmapCache.getPixmap("class_protected", imageSize)) |
618 UI.PixmapCache.getPixmap("class_protected", imageSize), |
|
619 ) |
622 self.registerImage( |
620 self.registerImage( |
623 self.ClassPrivateID, |
621 self.ClassPrivateID, UI.PixmapCache.getPixmap("class_private", imageSize) |
624 UI.PixmapCache.getPixmap("class_private", imageSize)) |
622 ) |
625 self.registerImage( |
623 self.registerImage(self.MethodID, UI.PixmapCache.getPixmap("method", imageSize)) |
626 self.MethodID, |
|
627 UI.PixmapCache.getPixmap("method", imageSize)) |
|
628 self.registerImage( |
624 self.registerImage( |
629 self.MethodProtectedID, |
625 self.MethodProtectedID, |
630 UI.PixmapCache.getPixmap("method_protected", imageSize)) |
626 UI.PixmapCache.getPixmap("method_protected", imageSize), |
|
627 ) |
631 self.registerImage( |
628 self.registerImage( |
632 self.MethodPrivateID, |
629 self.MethodPrivateID, UI.PixmapCache.getPixmap("method_private", imageSize) |
633 UI.PixmapCache.getPixmap("method_private", imageSize)) |
630 ) |
634 self.registerImage( |
631 self.registerImage( |
635 self.AttributeID, |
632 self.AttributeID, UI.PixmapCache.getPixmap("attribute", imageSize) |
636 UI.PixmapCache.getPixmap("attribute", imageSize)) |
633 ) |
637 self.registerImage( |
634 self.registerImage( |
638 self.AttributeProtectedID, |
635 self.AttributeProtectedID, |
639 UI.PixmapCache.getPixmap("attribute_protected", imageSize)) |
636 UI.PixmapCache.getPixmap("attribute_protected", imageSize), |
|
637 ) |
640 self.registerImage( |
638 self.registerImage( |
641 self.AttributePrivateID, |
639 self.AttributePrivateID, |
642 UI.PixmapCache.getPixmap("attribute_private", imageSize)) |
640 UI.PixmapCache.getPixmap("attribute_private", imageSize), |
|
641 ) |
|
642 self.registerImage(self.EnumID, UI.PixmapCache.getPixmap("enum", imageSize)) |
643 self.registerImage( |
643 self.registerImage( |
644 self.EnumID, |
644 self.KeywordsID, UI.PixmapCache.getPixmap("keywords", imageSize) |
645 UI.PixmapCache.getPixmap("enum", imageSize)) |
645 ) |
|
646 self.registerImage(self.ModuleID, UI.PixmapCache.getPixmap("module", imageSize)) |
|
647 |
646 self.registerImage( |
648 self.registerImage( |
647 self.KeywordsID, |
649 self.FromDocumentID, UI.PixmapCache.getPixmap("editor", imageSize) |
648 UI.PixmapCache.getPixmap("keywords", imageSize)) |
650 ) |
|
651 |
649 self.registerImage( |
652 self.registerImage( |
650 self.ModuleID, |
653 self.TemplateImageID, UI.PixmapCache.getPixmap("templateViewer", imageSize) |
651 UI.PixmapCache.getPixmap("module", imageSize)) |
654 ) |
652 |
655 |
653 self.registerImage( |
|
654 self.FromDocumentID, |
|
655 UI.PixmapCache.getPixmap("editor", imageSize)) |
|
656 |
|
657 self.registerImage( |
|
658 self.TemplateImageID, |
|
659 UI.PixmapCache.getPixmap("templateViewer", imageSize)) |
|
660 |
|
661 def addClone(self, editor): |
656 def addClone(self, editor): |
662 """ |
657 """ |
663 Public method to add a clone to our list. |
658 Public method to add a clone to our list. |
664 |
659 |
665 @param editor reference to the cloned editor |
660 @param editor reference to the cloned editor |
666 @type Editor |
661 @type Editor |
667 """ |
662 """ |
668 self.__clones.append(editor) |
663 self.__clones.append(editor) |
669 |
664 |
670 editor.editorRenamed.connect(self.fileRenamed) |
665 editor.editorRenamed.connect(self.fileRenamed) |
671 editor.languageChanged.connect(self.languageChanged) |
666 editor.languageChanged.connect(self.languageChanged) |
672 editor.eolChanged.connect(self.__eolChanged) |
667 editor.eolChanged.connect(self.__eolChanged) |
673 editor.encodingChanged.connect(self.__encodingChanged) |
668 editor.encodingChanged.connect(self.__encodingChanged) |
674 editor.spellLanguageChanged.connect(self.__spellLanguageChanged) |
669 editor.spellLanguageChanged.connect(self.__spellLanguageChanged) |
675 |
670 |
676 def removeClone(self, editor): |
671 def removeClone(self, editor): |
677 """ |
672 """ |
678 Public method to remove a clone from our list. |
673 Public method to remove a clone from our list. |
679 |
674 |
680 @param editor reference to the cloned editor |
675 @param editor reference to the cloned editor |
681 @type Editor |
676 @type Editor |
682 """ |
677 """ |
683 if editor in self.__clones: |
678 if editor in self.__clones: |
684 editor.editorRenamed.disconnect(self.fileRenamed) |
679 editor.editorRenamed.disconnect(self.fileRenamed) |
685 editor.languageChanged.disconnect(self.languageChanged) |
680 editor.languageChanged.disconnect(self.languageChanged) |
686 editor.eolChanged.disconnect(self.__eolChanged) |
681 editor.eolChanged.disconnect(self.__eolChanged) |
687 editor.encodingChanged.disconnect(self.__encodingChanged) |
682 editor.encodingChanged.disconnect(self.__encodingChanged) |
688 editor.spellLanguageChanged.disconnect(self.__spellLanguageChanged) |
683 editor.spellLanguageChanged.disconnect(self.__spellLanguageChanged) |
689 self.__clones.remove(editor) |
684 self.__clones.remove(editor) |
690 |
685 |
691 def isClone(self, editor): |
686 def isClone(self, editor): |
692 """ |
687 """ |
693 Public method to test, if the given editor is a clone. |
688 Public method to test, if the given editor is a clone. |
694 |
689 |
695 @param editor reference to the cloned editor |
690 @param editor reference to the cloned editor |
696 @type Editor |
691 @type Editor |
697 @return flag indicating a clone |
692 @return flag indicating a clone |
698 @rtype bool |
693 @rtype bool |
699 """ |
694 """ |
700 return editor in self.__clones |
695 return editor in self.__clones |
701 |
696 |
702 def __bindName(self, line0): |
697 def __bindName(self, line0): |
703 """ |
698 """ |
704 Private method to generate a dummy filename for binding a lexer. |
699 Private method to generate a dummy filename for binding a lexer. |
705 |
700 |
706 @param line0 first line of text to use in the generation process |
701 @param line0 first line of text to use in the generation process |
707 (string) |
702 (string) |
708 @return dummy file name to be used for binding a lexer (string) |
703 @return dummy file name to be used for binding a lexer (string) |
709 """ |
704 """ |
710 bindName = "" |
705 bindName = "" |
711 line0 = line0.lower() |
706 line0 = line0.lower() |
712 |
707 |
713 # check first line if it does not start with #! |
708 # check first line if it does not start with #! |
714 if line0.startswith(("<html", "<!doctype html", "<?php")): |
709 if line0.startswith(("<html", "<!doctype html", "<?php")): |
715 bindName = "dummy.html" |
710 bindName = "dummy.html" |
716 elif line0.startswith(("<?xml", "<!doctype")): |
711 elif line0.startswith(("<?xml", "<!doctype")): |
717 bindName = "dummy.xml" |
712 bindName = "dummy.xml" |
718 elif line0.startswith("index: "): |
713 elif line0.startswith("index: "): |
719 bindName = "dummy.diff" |
714 bindName = "dummy.diff" |
720 elif line0.startswith("\\documentclass"): |
715 elif line0.startswith("\\documentclass"): |
721 bindName = "dummy.tex" |
716 bindName = "dummy.tex" |
722 |
717 |
723 if not bindName and self.filetype: |
718 if not bindName and self.filetype: |
724 # check filetype |
719 # check filetype |
725 from . import Lexers |
720 from . import Lexers |
|
721 |
726 supportedLanguages = Lexers.getSupportedLanguages() |
722 supportedLanguages = Lexers.getSupportedLanguages() |
727 if self.filetype in supportedLanguages: |
723 if self.filetype in supportedLanguages: |
728 bindName = supportedLanguages[self.filetype][1] |
724 bindName = supportedLanguages[self.filetype][1] |
729 elif self.filetype in ["Python", "Python3", "MicroPython"]: |
725 elif self.filetype in ["Python", "Python3", "MicroPython"]: |
730 bindName = "dummy.py" |
726 bindName = "dummy.py" |
731 |
727 |
732 if not bindName and line0.startswith("#!"): |
728 if not bindName and line0.startswith("#!"): |
733 # #! marker detection |
729 # #! marker detection |
734 if ( |
730 if ( |
735 "python3" in line0 or |
731 "python3" in line0 |
736 "python" in line0 or |
732 or "python" in line0 |
737 "pypy3" in line0 or |
733 or "pypy3" in line0 |
738 "pypy" in line0 |
734 or "pypy" in line0 |
739 ): |
735 ): |
740 bindName = "dummy.py" |
736 bindName = "dummy.py" |
741 self.filetype = "Python3" |
737 self.filetype = "Python3" |
742 elif ("/bash" in line0 or "/sh" in line0): |
738 elif "/bash" in line0 or "/sh" in line0: |
743 bindName = "dummy.sh" |
739 bindName = "dummy.sh" |
744 elif "ruby" in line0: |
740 elif "ruby" in line0: |
745 bindName = "dummy.rb" |
741 bindName = "dummy.rb" |
746 self.filetype = "Ruby" |
742 self.filetype = "Ruby" |
747 elif "perl" in line0: |
743 elif "perl" in line0: |
830 self.__menus["Eol"] = self.eolMenu |
826 self.__menus["Eol"] = self.eolMenu |
831 self.encodingsMenu = self.__initContextMenuEncodings() |
827 self.encodingsMenu = self.__initContextMenuEncodings() |
832 self.__menus["Encodings"] = self.encodingsMenu |
828 self.__menus["Encodings"] = self.encodingsMenu |
833 self.spellCheckMenu = self.__initContextMenuSpellCheck() |
829 self.spellCheckMenu = self.__initContextMenuSpellCheck() |
834 self.__menus["SpellCheck"] = self.spellCheckMenu |
830 self.__menus["SpellCheck"] = self.spellCheckMenu |
835 |
831 |
836 self.menuActs["Undo"] = self.menu.addAction( |
832 self.menuActs["Undo"] = self.menu.addAction( |
837 UI.PixmapCache.getIcon("editUndo"), |
833 UI.PixmapCache.getIcon("editUndo"), self.tr("Undo"), self.undo |
838 self.tr('Undo'), self.undo) |
834 ) |
839 self.menuActs["Redo"] = self.menu.addAction( |
835 self.menuActs["Redo"] = self.menu.addAction( |
840 UI.PixmapCache.getIcon("editRedo"), |
836 UI.PixmapCache.getIcon("editRedo"), self.tr("Redo"), self.redo |
841 self.tr('Redo'), self.redo) |
837 ) |
842 self.menuActs["Revert"] = self.menu.addAction( |
838 self.menuActs["Revert"] = self.menu.addAction( |
843 self.tr("Revert to last saved state"), |
839 self.tr("Revert to last saved state"), self.revertToUnmodified |
844 self.revertToUnmodified) |
840 ) |
845 self.menu.addSeparator() |
841 self.menu.addSeparator() |
846 self.menuActs["Cut"] = self.menu.addAction( |
842 self.menuActs["Cut"] = self.menu.addAction( |
847 UI.PixmapCache.getIcon("editCut"), |
843 UI.PixmapCache.getIcon("editCut"), self.tr("Cut"), self.cut |
848 self.tr('Cut'), self.cut) |
844 ) |
849 self.menuActs["Copy"] = self.menu.addAction( |
845 self.menuActs["Copy"] = self.menu.addAction( |
850 UI.PixmapCache.getIcon("editCopy"), |
846 UI.PixmapCache.getIcon("editCopy"), self.tr("Copy"), self.copy |
851 self.tr('Copy'), self.copy) |
847 ) |
852 self.menuActs["Paste"] = self.menu.addAction( |
848 self.menuActs["Paste"] = self.menu.addAction( |
853 UI.PixmapCache.getIcon("editPaste"), |
849 UI.PixmapCache.getIcon("editPaste"), self.tr("Paste"), self.paste |
854 self.tr('Paste'), self.paste) |
850 ) |
855 if not self.miniMenu: |
851 if not self.miniMenu: |
856 self.menu.addSeparator() |
852 self.menu.addSeparator() |
857 self.menu.addAction( |
853 self.menu.addAction( |
858 UI.PixmapCache.getIcon("editIndent"), |
854 UI.PixmapCache.getIcon("editIndent"), |
859 self.tr('Indent'), self.indentLineOrSelection) |
855 self.tr("Indent"), |
|
856 self.indentLineOrSelection, |
|
857 ) |
860 self.menu.addAction( |
858 self.menu.addAction( |
861 UI.PixmapCache.getIcon("editUnindent"), |
859 UI.PixmapCache.getIcon("editUnindent"), |
862 self.tr('Unindent'), self.unindentLineOrSelection) |
860 self.tr("Unindent"), |
|
861 self.unindentLineOrSelection, |
|
862 ) |
863 self.menuActs["Comment"] = self.menu.addAction( |
863 self.menuActs["Comment"] = self.menu.addAction( |
864 UI.PixmapCache.getIcon("editComment"), |
864 UI.PixmapCache.getIcon("editComment"), |
865 self.tr('Comment'), self.commentLineOrSelection) |
865 self.tr("Comment"), |
|
866 self.commentLineOrSelection, |
|
867 ) |
866 self.menuActs["Uncomment"] = self.menu.addAction( |
868 self.menuActs["Uncomment"] = self.menu.addAction( |
867 UI.PixmapCache.getIcon("editUncomment"), |
869 UI.PixmapCache.getIcon("editUncomment"), |
868 self.tr('Uncomment'), self.uncommentLineOrSelection) |
870 self.tr("Uncomment"), |
|
871 self.uncommentLineOrSelection, |
|
872 ) |
869 self.menu.addSeparator() |
873 self.menu.addSeparator() |
870 self.menuActs["Docstring"] = self.menu.addAction( |
874 self.menuActs["Docstring"] = self.menu.addAction( |
871 self.tr("Generate Docstring"), |
875 self.tr("Generate Docstring"), self.__insertDocstring |
872 self.__insertDocstring) |
876 ) |
873 self.menu.addSeparator() |
877 self.menu.addSeparator() |
874 self.menu.addAction( |
878 self.menu.addAction(self.tr("Select to brace"), self.selectToMatchingBrace) |
875 self.tr('Select to brace'), self.selectToMatchingBrace) |
879 self.menu.addAction(self.tr("Select all"), self.__selectAll) |
876 self.menu.addAction(self.tr('Select all'), self.__selectAll) |
880 self.menu.addAction(self.tr("Deselect all"), self.__deselectAll) |
877 self.menu.addAction( |
|
878 self.tr('Deselect all'), self.__deselectAll) |
|
879 self.menuActs["ExecuteSelection"] = self.menu.addAction( |
881 self.menuActs["ExecuteSelection"] = self.menu.addAction( |
880 self.tr("Execute Selection In Console"), |
882 self.tr("Execute Selection In Console"), self.__executeSelection |
881 self.__executeSelection) |
883 ) |
882 else: |
884 else: |
883 self.menuActs["ExecuteSelection"] = None |
885 self.menuActs["ExecuteSelection"] = None |
884 self.menu.addSeparator() |
886 self.menu.addSeparator() |
885 self.menu.addMenu(self.spellCheckMenu) |
887 self.menu.addMenu(self.spellCheckMenu) |
886 self.menu.addSeparator() |
888 self.menu.addSeparator() |
887 self.menuActs["Languages"] = self.menu.addMenu(self.languagesMenu) |
889 self.menuActs["Languages"] = self.menu.addMenu(self.languagesMenu) |
888 self.menuActs["Encodings"] = self.menu.addMenu(self.encodingsMenu) |
890 self.menuActs["Encodings"] = self.menu.addMenu(self.encodingsMenu) |
889 self.menuActs["Eol"] = self.menu.addMenu(self.eolMenu) |
891 self.menuActs["Eol"] = self.menu.addMenu(self.eolMenu) |
890 self.menu.addSeparator() |
892 self.menu.addSeparator() |
891 self.menuActs["MonospacedFont"] = self.menu.addAction( |
893 self.menuActs["MonospacedFont"] = self.menu.addAction( |
892 self.tr("Use Monospaced Font"), |
894 self.tr("Use Monospaced Font"), self.handleMonospacedEnable |
893 self.handleMonospacedEnable) |
895 ) |
894 self.menuActs["MonospacedFont"].setCheckable(True) |
896 self.menuActs["MonospacedFont"].setCheckable(True) |
895 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) |
897 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) |
896 self.menuActs["AutosaveEnable"] = self.menu.addAction( |
898 self.menuActs["AutosaveEnable"] = self.menu.addAction( |
897 self.tr("Autosave enabled"), self.__autosaveEnable) |
899 self.tr("Autosave enabled"), self.__autosaveEnable |
|
900 ) |
898 self.menuActs["AutosaveEnable"].setCheckable(True) |
901 self.menuActs["AutosaveEnable"].setCheckable(True) |
899 self.menuActs["AutosaveEnable"].setChecked(self.autosaveEnabled) |
902 self.menuActs["AutosaveEnable"].setChecked(self.autosaveEnabled) |
900 self.menuActs["TypingAidsEnabled"] = self.menu.addAction( |
903 self.menuActs["TypingAidsEnabled"] = self.menu.addAction( |
901 self.tr("Typing aids enabled"), self.__toggleTypingAids) |
904 self.tr("Typing aids enabled"), self.__toggleTypingAids |
|
905 ) |
902 self.menuActs["TypingAidsEnabled"].setCheckable(True) |
906 self.menuActs["TypingAidsEnabled"].setCheckable(True) |
903 self.menuActs["TypingAidsEnabled"].setEnabled( |
907 self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None) |
904 self.completer is not None) |
|
905 self.menuActs["TypingAidsEnabled"].setChecked( |
908 self.menuActs["TypingAidsEnabled"].setChecked( |
906 self.completer is not None and self.completer.isEnabled()) |
909 self.completer is not None and self.completer.isEnabled() |
|
910 ) |
907 self.menuActs["AutoCompletionEnable"] = self.menu.addAction( |
911 self.menuActs["AutoCompletionEnable"] = self.menu.addAction( |
908 self.tr("Automatic Completion enabled"), |
912 self.tr("Automatic Completion enabled"), self.__toggleAutoCompletionEnable |
909 self.__toggleAutoCompletionEnable) |
913 ) |
910 self.menuActs["AutoCompletionEnable"].setCheckable(True) |
914 self.menuActs["AutoCompletionEnable"].setCheckable(True) |
911 self.menuActs["AutoCompletionEnable"].setChecked( |
915 self.menuActs["AutoCompletionEnable"].setChecked( |
912 self.autoCompletionThreshold() != -1) |
916 self.autoCompletionThreshold() != -1 |
|
917 ) |
913 if not self.isResourcesFile: |
918 if not self.isResourcesFile: |
914 self.menu.addMenu(self.autocompletionMenu) |
919 self.menu.addMenu(self.autocompletionMenu) |
915 self.menuActs["calltip"] = self.menu.addAction( |
920 self.menuActs["calltip"] = self.menu.addAction( |
916 self.tr('Calltip'), self.callTip) |
921 self.tr("Calltip"), self.callTip |
|
922 ) |
917 self.menuActs["codeInfo"] = self.menu.addAction( |
923 self.menuActs["codeInfo"] = self.menu.addAction( |
918 self.tr('Code Info'), self.__showCodeInfo) |
924 self.tr("Code Info"), self.__showCodeInfo |
|
925 ) |
919 self.menu.addSeparator() |
926 self.menu.addSeparator() |
920 if self.isResourcesFile: |
927 if self.isResourcesFile: |
921 self.menu.addMenu(self.resourcesMenu) |
928 self.menu.addMenu(self.resourcesMenu) |
922 else: |
929 else: |
923 self.menuActs["Check"] = self.menu.addMenu(self.checksMenu) |
930 self.menuActs["Check"] = self.menu.addMenu(self.checksMenu) |
927 self.menu.addSeparator() |
934 self.menu.addSeparator() |
928 self.menuActs["Tools"] = self.menu.addMenu(self.toolsMenu) |
935 self.menuActs["Tools"] = self.menu.addMenu(self.toolsMenu) |
929 self.menu.addSeparator() |
936 self.menu.addSeparator() |
930 self.menu.addAction( |
937 self.menu.addAction( |
931 UI.PixmapCache.getIcon("documentNewView"), |
938 UI.PixmapCache.getIcon("documentNewView"), |
932 self.tr('New Document View'), self.__newView) |
939 self.tr("New Document View"), |
|
940 self.__newView, |
|
941 ) |
933 self.menuActs["NewSplit"] = self.menu.addAction( |
942 self.menuActs["NewSplit"] = self.menu.addAction( |
934 UI.PixmapCache.getIcon("splitVertical"), |
943 UI.PixmapCache.getIcon("splitVertical"), |
935 self.tr('New Document View (with new split)'), |
944 self.tr("New Document View (with new split)"), |
936 self.__newViewNewSplit) |
945 self.__newViewNewSplit, |
|
946 ) |
937 self.menuActs["NewSplit"].setEnabled(self.vm.canSplit()) |
947 self.menuActs["NewSplit"].setEnabled(self.vm.canSplit()) |
938 self.menu.addSeparator() |
948 self.menu.addSeparator() |
939 self.reopenEncodingMenu = self.__initContextMenuReopenWithEncoding() |
949 self.reopenEncodingMenu = self.__initContextMenuReopenWithEncoding() |
940 self.menuActs["Reopen"] = self.menu.addMenu(self.reopenEncodingMenu) |
950 self.menuActs["Reopen"] = self.menu.addMenu(self.reopenEncodingMenu) |
941 self.menuActs["Save"] = self.menu.addAction( |
951 self.menuActs["Save"] = self.menu.addAction( |
942 UI.PixmapCache.getIcon("fileSave"), |
952 UI.PixmapCache.getIcon("fileSave"), self.tr("Save"), self.__contextSave |
943 self.tr('Save'), self.__contextSave) |
953 ) |
944 self.menu.addAction( |
954 self.menu.addAction( |
945 UI.PixmapCache.getIcon("fileSaveAs"), |
955 UI.PixmapCache.getIcon("fileSaveAs"), |
946 self.tr('Save As...'), self.__contextSaveAs) |
956 self.tr("Save As..."), |
|
957 self.__contextSaveAs, |
|
958 ) |
947 self.menu.addAction( |
959 self.menu.addAction( |
948 UI.PixmapCache.getIcon("fileSaveCopy"), |
960 UI.PixmapCache.getIcon("fileSaveCopy"), |
949 self.tr('Save Copy...'), self.__contextSaveCopy) |
961 self.tr("Save Copy..."), |
950 |
962 self.__contextSaveCopy, |
|
963 ) |
|
964 |
951 self.menu.aboutToShow.connect(self.__showContextMenu) |
965 self.menu.aboutToShow.connect(self.__showContextMenu) |
952 |
966 |
953 self.spellingMenu = QMenu() |
967 self.spellingMenu = QMenu() |
954 self.__menus["Spelling"] = self.spellingMenu |
968 self.__menus["Spelling"] = self.spellingMenu |
955 |
969 |
956 self.spellingMenu.aboutToShow.connect(self.__showContextMenuSpelling) |
970 self.spellingMenu.aboutToShow.connect(self.__showContextMenuSpelling) |
957 self.spellingMenu.triggered.connect( |
971 self.spellingMenu.triggered.connect(self.__contextMenuSpellingTriggered) |
958 self.__contextMenuSpellingTriggered) |
|
959 |
972 |
960 def __initContextMenuAutocompletion(self): |
973 def __initContextMenuAutocompletion(self): |
961 """ |
974 """ |
962 Private method used to setup the Checks context sub menu. |
975 Private method used to setup the Checks context sub menu. |
963 |
976 |
964 @return reference to the generated menu |
977 @return reference to the generated menu |
965 @rtype QMenu |
978 @rtype QMenu |
966 """ |
979 """ |
967 menu = QMenu(self.tr('Complete')) |
980 menu = QMenu(self.tr("Complete")) |
968 |
981 |
969 self.menuActs["acDynamic"] = menu.addAction( |
982 self.menuActs["acDynamic"] = menu.addAction( |
970 self.tr('Complete'), self.autoComplete) |
983 self.tr("Complete"), self.autoComplete |
|
984 ) |
971 menu.addSeparator() |
985 menu.addSeparator() |
972 self.menuActs["acClearCache"] = menu.addAction( |
986 self.menuActs["acClearCache"] = menu.addAction( |
973 self.tr("Clear Completions Cache"), self.__clearCompletionsCache) |
987 self.tr("Clear Completions Cache"), self.__clearCompletionsCache |
|
988 ) |
974 menu.addSeparator() |
989 menu.addSeparator() |
975 menu.addAction( |
990 menu.addAction(self.tr("Complete from Document"), self.autoCompleteFromDocument) |
976 self.tr('Complete from Document'), self.autoCompleteFromDocument) |
|
977 self.menuActs["acAPI"] = menu.addAction( |
991 self.menuActs["acAPI"] = menu.addAction( |
978 self.tr('Complete from APIs'), self.autoCompleteFromAPIs) |
992 self.tr("Complete from APIs"), self.autoCompleteFromAPIs |
|
993 ) |
979 self.menuActs["acAPIDocument"] = menu.addAction( |
994 self.menuActs["acAPIDocument"] = menu.addAction( |
980 self.tr('Complete from Document and APIs'), |
995 self.tr("Complete from Document and APIs"), self.autoCompleteFromAll |
981 self.autoCompleteFromAll) |
996 ) |
982 |
997 |
983 menu.aboutToShow.connect(self.__showContextMenuAutocompletion) |
998 menu.aboutToShow.connect(self.__showContextMenuAutocompletion) |
984 |
999 |
985 return menu |
1000 return menu |
986 |
1001 |
987 def __initContextMenuChecks(self): |
1002 def __initContextMenuChecks(self): |
988 """ |
1003 """ |
989 Private method used to setup the Checks context sub menu. |
1004 Private method used to setup the Checks context sub menu. |
990 |
1005 |
991 @return reference to the generated menu |
1006 @return reference to the generated menu |
992 @rtype QMenu |
1007 @rtype QMenu |
993 """ |
1008 """ |
994 menu = QMenu(self.tr('Check')) |
1009 menu = QMenu(self.tr("Check")) |
995 menu.aboutToShow.connect(self.__showContextMenuChecks) |
1010 menu.aboutToShow.connect(self.__showContextMenuChecks) |
996 return menu |
1011 return menu |
997 |
1012 |
998 def __initContextMenuFormatting(self): |
1013 def __initContextMenuFormatting(self): |
999 """ |
1014 """ |
1000 Private method used to setup the Code Formatting context sub menu. |
1015 Private method used to setup the Code Formatting context sub menu. |
1001 |
1016 |
1002 @return reference to the generated menu |
1017 @return reference to the generated menu |
1003 @rtype QMenu |
1018 @rtype QMenu |
1004 """ |
1019 """ |
1005 menu = QMenu(self.tr("Code Formatting")) |
1020 menu = QMenu(self.tr("Code Formatting")) |
1006 |
1021 |
1007 menu.addAction( |
1022 menu.addAction( |
1008 self.tr("Format Code"), |
1023 self.tr("Format Code"), |
1009 lambda: self.__performFormatWithBlack(BlackFormattingAction.Format) |
1024 lambda: self.__performFormatWithBlack(BlackFormattingAction.Format), |
1010 ) |
1025 ) |
1011 menu.addAction( |
1026 menu.addAction( |
1012 self.tr("Check Formatting"), |
1027 self.tr("Check Formatting"), |
1013 lambda: self.__performFormatWithBlack(BlackFormattingAction.Check) |
1028 lambda: self.__performFormatWithBlack(BlackFormattingAction.Check), |
1014 ) |
1029 ) |
1015 menu.addAction( |
1030 menu.addAction( |
1016 self.tr("Formatting Diff"), |
1031 self.tr("Formatting Diff"), |
1017 lambda: self.__performFormatWithBlack(BlackFormattingAction.Diff) |
1032 lambda: self.__performFormatWithBlack(BlackFormattingAction.Diff), |
1018 ) |
1033 ) |
1019 |
1034 |
1020 menu.aboutToShow.connect(self.__showContextMenuFormatting) |
1035 menu.aboutToShow.connect(self.__showContextMenuFormatting) |
1021 |
1036 |
1022 return menu |
1037 return menu |
1023 |
1038 |
1024 def __initContextMenuTools(self): |
1039 def __initContextMenuTools(self): |
1025 """ |
1040 """ |
1026 Private method used to setup the Tools context sub menu. |
1041 Private method used to setup the Tools context sub menu. |
1027 |
1042 |
1028 @return reference to the generated menu |
1043 @return reference to the generated menu |
1029 @rtype QMenu |
1044 @rtype QMenu |
1030 """ |
1045 """ |
1031 menu = QMenu(self.tr('Tools')) |
1046 menu = QMenu(self.tr("Tools")) |
1032 menu.aboutToShow.connect(self.__showContextMenuTools) |
1047 menu.aboutToShow.connect(self.__showContextMenuTools) |
1033 return menu |
1048 return menu |
1034 |
1049 |
1035 def __initContextMenuShow(self): |
1050 def __initContextMenuShow(self): |
1036 """ |
1051 """ |
1037 Private method used to setup the Show context sub menu. |
1052 Private method used to setup the Show context sub menu. |
1038 |
1053 |
1039 @return reference to the generated menu |
1054 @return reference to the generated menu |
1040 @rtype QMenu |
1055 @rtype QMenu |
1041 """ |
1056 """ |
1042 menu = QMenu(self.tr('Show')) |
1057 menu = QMenu(self.tr("Show")) |
1043 |
1058 |
1044 menu.addAction(self.tr('Code metrics...'), self.__showCodeMetrics) |
1059 menu.addAction(self.tr("Code metrics..."), self.__showCodeMetrics) |
1045 self.coverageMenuAct = menu.addAction( |
1060 self.coverageMenuAct = menu.addAction( |
1046 self.tr('Code coverage...'), self.__showCodeCoverage) |
1061 self.tr("Code coverage..."), self.__showCodeCoverage |
|
1062 ) |
1047 self.coverageShowAnnotationMenuAct = menu.addAction( |
1063 self.coverageShowAnnotationMenuAct = menu.addAction( |
1048 self.tr('Show code coverage annotations'), |
1064 self.tr("Show code coverage annotations"), self.codeCoverageShowAnnotations |
1049 self.codeCoverageShowAnnotations) |
1065 ) |
1050 self.coverageHideAnnotationMenuAct = menu.addAction( |
1066 self.coverageHideAnnotationMenuAct = menu.addAction( |
1051 self.tr('Hide code coverage annotations'), |
1067 self.tr("Hide code coverage annotations"), |
1052 self.__codeCoverageHideAnnotations) |
1068 self.__codeCoverageHideAnnotations, |
|
1069 ) |
1053 self.profileMenuAct = menu.addAction( |
1070 self.profileMenuAct = menu.addAction( |
1054 self.tr('Profile data...'), self.__showProfileData) |
1071 self.tr("Profile data..."), self.__showProfileData |
1055 |
1072 ) |
|
1073 |
1056 menu.aboutToShow.connect(self.__showContextMenuShow) |
1074 menu.aboutToShow.connect(self.__showContextMenuShow) |
1057 |
1075 |
1058 return menu |
1076 return menu |
1059 |
1077 |
1060 def __initContextMenuGraphics(self): |
1078 def __initContextMenuGraphics(self): |
1061 """ |
1079 """ |
1062 Private method used to setup the diagrams context sub menu. |
1080 Private method used to setup the diagrams context sub menu. |
1063 |
1081 |
1064 @return reference to the generated menu |
1082 @return reference to the generated menu |
1065 @rtype QMenu |
1083 @rtype QMenu |
1066 """ |
1084 """ |
1067 menu = QMenu(self.tr('Diagrams')) |
1085 menu = QMenu(self.tr("Diagrams")) |
1068 |
1086 |
1069 menu.addAction( |
1087 menu.addAction(self.tr("Class Diagram..."), self.__showClassDiagram) |
1070 self.tr('Class Diagram...'), self.__showClassDiagram) |
1088 menu.addAction(self.tr("Package Diagram..."), self.__showPackageDiagram) |
1071 menu.addAction( |
1089 menu.addAction(self.tr("Imports Diagram..."), self.__showImportsDiagram) |
1072 self.tr('Package Diagram...'), self.__showPackageDiagram) |
|
1073 menu.addAction( |
|
1074 self.tr('Imports Diagram...'), self.__showImportsDiagram) |
|
1075 self.applicationDiagramMenuAct = menu.addAction( |
1090 self.applicationDiagramMenuAct = menu.addAction( |
1076 self.tr('Application Diagram...'), |
1091 self.tr("Application Diagram..."), self.__showApplicationDiagram |
1077 self.__showApplicationDiagram) |
1092 ) |
1078 menu.addSeparator() |
1093 menu.addSeparator() |
1079 menu.addAction( |
1094 menu.addAction( |
1080 UI.PixmapCache.getIcon("open"), |
1095 UI.PixmapCache.getIcon("open"), |
1081 self.tr("Load Diagram..."), self.__loadDiagram) |
1096 self.tr("Load Diagram..."), |
1082 |
1097 self.__loadDiagram, |
|
1098 ) |
|
1099 |
1083 menu.aboutToShow.connect(self.__showContextMenuGraphics) |
1100 menu.aboutToShow.connect(self.__showContextMenuGraphics) |
1084 |
1101 |
1085 return menu |
1102 return menu |
1086 |
1103 |
1087 def __initContextMenuLanguages(self): |
1104 def __initContextMenuLanguages(self): |
1088 """ |
1105 """ |
1089 Private method used to setup the Languages context sub menu. |
1106 Private method used to setup the Languages context sub menu. |
1090 |
1107 |
1091 @return reference to the generated menu |
1108 @return reference to the generated menu |
1092 @rtype QMenu |
1109 @rtype QMenu |
1093 """ |
1110 """ |
1094 menu = QMenu(self.tr("Languages")) |
1111 menu = QMenu(self.tr("Languages")) |
1095 |
1112 |
1096 self.languagesActGrp = QActionGroup(self) |
1113 self.languagesActGrp = QActionGroup(self) |
1097 self.noLanguageAct = menu.addAction( |
1114 self.noLanguageAct = menu.addAction( |
1098 UI.PixmapCache.getIcon("fileText"), |
1115 UI.PixmapCache.getIcon("fileText"), self.tr("Text") |
1099 self.tr("Text")) |
1116 ) |
1100 self.noLanguageAct.setCheckable(True) |
1117 self.noLanguageAct.setCheckable(True) |
1101 self.noLanguageAct.setData("None") |
1118 self.noLanguageAct.setData("None") |
1102 self.languagesActGrp.addAction(self.noLanguageAct) |
1119 self.languagesActGrp.addAction(self.noLanguageAct) |
1103 menu.addSeparator() |
1120 menu.addSeparator() |
1104 |
1121 |
1105 from . import Lexers |
1122 from . import Lexers |
|
1123 |
1106 self.supportedLanguages = {} |
1124 self.supportedLanguages = {} |
1107 supportedLanguages = Lexers.getSupportedLanguages() |
1125 supportedLanguages = Lexers.getSupportedLanguages() |
1108 languages = sorted(supportedLanguages.keys()) |
1126 languages = sorted(supportedLanguages.keys()) |
1109 for language in languages: |
1127 for language in languages: |
1110 if language != "Guessed": |
1128 if language != "Guessed": |
1111 self.supportedLanguages[language] = ( |
1129 self.supportedLanguages[language] = supportedLanguages[language][:2] |
1112 supportedLanguages[language][:2] |
|
1113 ) |
|
1114 act = menu.addAction( |
1130 act = menu.addAction( |
1115 UI.PixmapCache.getIcon(supportedLanguages[language][2]), |
1131 UI.PixmapCache.getIcon(supportedLanguages[language][2]), |
1116 self.supportedLanguages[language][0]) |
1132 self.supportedLanguages[language][0], |
|
1133 ) |
1117 act.setCheckable(True) |
1134 act.setCheckable(True) |
1118 act.setData(language) |
1135 act.setData(language) |
1119 self.supportedLanguages[language].append(act) |
1136 self.supportedLanguages[language].append(act) |
1120 self.languagesActGrp.addAction(act) |
1137 self.languagesActGrp.addAction(act) |
1121 |
1138 |
1122 menu.addSeparator() |
1139 menu.addSeparator() |
1123 self.pygmentsAct = menu.addAction(self.tr("Guessed")) |
1140 self.pygmentsAct = menu.addAction(self.tr("Guessed")) |
1124 self.pygmentsAct.setCheckable(True) |
1141 self.pygmentsAct.setCheckable(True) |
1125 self.pygmentsAct.setData("Guessed") |
1142 self.pygmentsAct.setData("Guessed") |
1126 self.languagesActGrp.addAction(self.pygmentsAct) |
1143 self.languagesActGrp.addAction(self.pygmentsAct) |
1127 self.pygmentsSelAct = menu.addAction(self.tr("Alternatives")) |
1144 self.pygmentsSelAct = menu.addAction(self.tr("Alternatives")) |
1128 self.pygmentsSelAct.setData("Alternatives") |
1145 self.pygmentsSelAct.setData("Alternatives") |
1129 |
1146 |
1130 menu.triggered.connect(self.__languageMenuTriggered) |
1147 menu.triggered.connect(self.__languageMenuTriggered) |
1131 menu.aboutToShow.connect(self.__showContextMenuLanguages) |
1148 menu.aboutToShow.connect(self.__showContextMenuLanguages) |
1132 |
1149 |
1133 return menu |
1150 return menu |
1134 |
1151 |
1135 def __initContextMenuEncodings(self): |
1152 def __initContextMenuEncodings(self): |
1136 """ |
1153 """ |
1137 Private method used to setup the Encodings context sub menu. |
1154 Private method used to setup the Encodings context sub menu. |
1138 |
1155 |
1139 @return reference to the generated menu |
1156 @return reference to the generated menu |
1140 @rtype QMenu |
1157 @rtype QMenu |
1141 """ |
1158 """ |
1142 self.supportedEncodings = {} |
1159 self.supportedEncodings = {} |
1143 |
1160 |
1144 menu = QMenu(self.tr("Encodings")) |
1161 menu = QMenu(self.tr("Encodings")) |
1145 |
1162 |
1146 self.encodingsActGrp = QActionGroup(self) |
1163 self.encodingsActGrp = QActionGroup(self) |
1147 |
1164 |
1148 for encoding in sorted(Utilities.supportedCodecs): |
1165 for encoding in sorted(Utilities.supportedCodecs): |
1149 act = menu.addAction(encoding) |
1166 act = menu.addAction(encoding) |
1150 act.setCheckable(True) |
1167 act.setCheckable(True) |
1151 act.setData(encoding) |
1168 act.setData(encoding) |
1152 self.supportedEncodings[encoding] = act |
1169 self.supportedEncodings[encoding] = act |
1153 self.encodingsActGrp.addAction(act) |
1170 self.encodingsActGrp.addAction(act) |
1154 |
1171 |
1155 menu.triggered.connect(self.__encodingsMenuTriggered) |
1172 menu.triggered.connect(self.__encodingsMenuTriggered) |
1156 menu.aboutToShow.connect(self.__showContextMenuEncodings) |
1173 menu.aboutToShow.connect(self.__showContextMenuEncodings) |
1157 |
1174 |
1158 return menu |
1175 return menu |
1159 |
1176 |
1160 def __initContextMenuReopenWithEncoding(self): |
1177 def __initContextMenuReopenWithEncoding(self): |
1161 """ |
1178 """ |
1162 Private method used to setup the Reopen With Encoding context sub menu. |
1179 Private method used to setup the Reopen With Encoding context sub menu. |
1163 |
1180 |
1164 @return reference to the generated menu |
1181 @return reference to the generated menu |
1165 @rtype QMenu |
1182 @rtype QMenu |
1166 """ |
1183 """ |
1167 menu = QMenu(self.tr("Re-Open With Encoding")) |
1184 menu = QMenu(self.tr("Re-Open With Encoding")) |
1168 menu.setIcon(UI.PixmapCache.getIcon("open")) |
1185 menu.setIcon(UI.PixmapCache.getIcon("open")) |
1169 |
1186 |
1170 for encoding in sorted(Utilities.supportedCodecs): |
1187 for encoding in sorted(Utilities.supportedCodecs): |
1171 act = menu.addAction(encoding) |
1188 act = menu.addAction(encoding) |
1172 act.setData(encoding) |
1189 act.setData(encoding) |
1173 |
1190 |
1174 menu.triggered.connect(self.__reopenWithEncodingMenuTriggered) |
1191 menu.triggered.connect(self.__reopenWithEncodingMenuTriggered) |
1175 |
1192 |
1176 return menu |
1193 return menu |
1177 |
1194 |
1178 def __initContextMenuEol(self): |
1195 def __initContextMenuEol(self): |
1179 """ |
1196 """ |
1180 Private method to setup the eol context sub menu. |
1197 Private method to setup the eol context sub menu. |
1181 |
1198 |
1182 @return reference to the generated menu |
1199 @return reference to the generated menu |
1183 @rtype QMenu |
1200 @rtype QMenu |
1184 """ |
1201 """ |
1185 self.supportedEols = {} |
1202 self.supportedEols = {} |
1186 |
1203 |
1187 menu = QMenu(self.tr("End-of-Line Type")) |
1204 menu = QMenu(self.tr("End-of-Line Type")) |
1188 |
1205 |
1189 self.eolActGrp = QActionGroup(self) |
1206 self.eolActGrp = QActionGroup(self) |
1190 |
1207 |
1191 act = menu.addAction(UI.PixmapCache.getIcon("eolLinux"), |
1208 act = menu.addAction(UI.PixmapCache.getIcon("eolLinux"), self.tr("Unix")) |
1192 self.tr("Unix")) |
|
1193 act.setCheckable(True) |
1209 act.setCheckable(True) |
1194 act.setData('\n') |
1210 act.setData("\n") |
1195 self.supportedEols['\n'] = act |
1211 self.supportedEols["\n"] = act |
1196 self.eolActGrp.addAction(act) |
1212 self.eolActGrp.addAction(act) |
1197 |
1213 |
1198 act = menu.addAction(UI.PixmapCache.getIcon("eolWindows"), |
1214 act = menu.addAction(UI.PixmapCache.getIcon("eolWindows"), self.tr("Windows")) |
1199 self.tr("Windows")) |
|
1200 act.setCheckable(True) |
1215 act.setCheckable(True) |
1201 act.setData('\r\n') |
1216 act.setData("\r\n") |
1202 self.supportedEols['\r\n'] = act |
1217 self.supportedEols["\r\n"] = act |
1203 self.eolActGrp.addAction(act) |
1218 self.eolActGrp.addAction(act) |
1204 |
1219 |
1205 act = menu.addAction(UI.PixmapCache.getIcon("eolMac"), |
1220 act = menu.addAction(UI.PixmapCache.getIcon("eolMac"), self.tr("Macintosh")) |
1206 self.tr("Macintosh")) |
|
1207 act.setCheckable(True) |
1221 act.setCheckable(True) |
1208 act.setData('\r') |
1222 act.setData("\r") |
1209 self.supportedEols['\r'] = act |
1223 self.supportedEols["\r"] = act |
1210 self.eolActGrp.addAction(act) |
1224 self.eolActGrp.addAction(act) |
1211 |
1225 |
1212 menu.triggered.connect(self.__eolMenuTriggered) |
1226 menu.triggered.connect(self.__eolMenuTriggered) |
1213 menu.aboutToShow.connect(self.__showContextMenuEol) |
1227 menu.aboutToShow.connect(self.__showContextMenuEol) |
1214 |
1228 |
1215 return menu |
1229 return menu |
1216 |
1230 |
1217 def __initContextMenuSpellCheck(self): |
1231 def __initContextMenuSpellCheck(self): |
1218 """ |
1232 """ |
1219 Private method used to setup the spell checking context sub menu. |
1233 Private method used to setup the spell checking context sub menu. |
1220 |
1234 |
1221 @return reference to the generated menu |
1235 @return reference to the generated menu |
1222 @rtype QMenu |
1236 @rtype QMenu |
1223 """ |
1237 """ |
1224 menu = QMenu(self.tr("Spelling")) |
1238 menu = QMenu(self.tr("Spelling")) |
1225 menu.setIcon(UI.PixmapCache.getIcon("spellchecking")) |
1239 menu.setIcon(UI.PixmapCache.getIcon("spellchecking")) |
1226 |
1240 |
1227 self.spellLanguagesMenu = self.__initContextMenuSpellLanguages() |
1241 self.spellLanguagesMenu = self.__initContextMenuSpellLanguages() |
1228 self.__menus["SpellLanguages"] = self.spellLanguagesMenu |
1242 self.__menus["SpellLanguages"] = self.spellLanguagesMenu |
1229 |
1243 |
1230 self.menuActs["SpellCheck"] = menu.addAction( |
1244 self.menuActs["SpellCheck"] = menu.addAction( |
1231 UI.PixmapCache.getIcon("spellchecking"), |
1245 UI.PixmapCache.getIcon("spellchecking"), |
1232 self.tr('Check spelling...'), self.checkSpelling) |
1246 self.tr("Check spelling..."), |
|
1247 self.checkSpelling, |
|
1248 ) |
1233 self.menuActs["SpellCheckSelection"] = menu.addAction( |
1249 self.menuActs["SpellCheckSelection"] = menu.addAction( |
1234 UI.PixmapCache.getIcon("spellchecking"), |
1250 UI.PixmapCache.getIcon("spellchecking"), |
1235 self.tr('Check spelling of selection...'), |
1251 self.tr("Check spelling of selection..."), |
1236 self.__checkSpellingSelection) |
1252 self.__checkSpellingSelection, |
|
1253 ) |
1237 self.menuActs["SpellCheckRemove"] = menu.addAction( |
1254 self.menuActs["SpellCheckRemove"] = menu.addAction( |
1238 self.tr("Remove from dictionary"), |
1255 self.tr("Remove from dictionary"), self.__removeFromSpellingDictionary |
1239 self.__removeFromSpellingDictionary) |
1256 ) |
1240 self.menuActs["SpellCheckLanguages"] = menu.addMenu( |
1257 self.menuActs["SpellCheckLanguages"] = menu.addMenu(self.spellLanguagesMenu) |
1241 self.spellLanguagesMenu) |
1258 |
1242 |
|
1243 menu.aboutToShow.connect(self.__showContextMenuSpellCheck) |
1259 menu.aboutToShow.connect(self.__showContextMenuSpellCheck) |
1244 |
1260 |
1245 return menu |
1261 return menu |
1246 |
1262 |
1247 def __initContextMenuSpellLanguages(self): |
1263 def __initContextMenuSpellLanguages(self): |
1248 """ |
1264 """ |
1249 Private method to setup the spell checking languages context sub menu. |
1265 Private method to setup the spell checking languages context sub menu. |
1250 |
1266 |
1251 @return reference to the generated menu |
1267 @return reference to the generated menu |
1252 @rtype QMenu |
1268 @rtype QMenu |
1253 """ |
1269 """ |
1254 self.supportedSpellLanguages = {} |
1270 self.supportedSpellLanguages = {} |
1255 |
1271 |
1256 menu = QMenu(self.tr("Spell Check Languages")) |
1272 menu = QMenu(self.tr("Spell Check Languages")) |
1257 |
1273 |
1258 self.spellLanguagesActGrp = QActionGroup(self) |
1274 self.spellLanguagesActGrp = QActionGroup(self) |
1259 |
1275 |
1260 self.noSpellLanguageAct = menu.addAction( |
1276 self.noSpellLanguageAct = menu.addAction(self.tr("No Language")) |
1261 self.tr("No Language")) |
|
1262 self.noSpellLanguageAct.setCheckable(True) |
1277 self.noSpellLanguageAct.setCheckable(True) |
1263 self.noSpellLanguageAct.setData("") |
1278 self.noSpellLanguageAct.setData("") |
1264 self.spellLanguagesActGrp.addAction(self.noSpellLanguageAct) |
1279 self.spellLanguagesActGrp.addAction(self.noSpellLanguageAct) |
1265 menu.addSeparator() |
1280 menu.addSeparator() |
1266 |
1281 |
1267 for language in sorted(SpellChecker.getAvailableLanguages()): |
1282 for language in sorted(SpellChecker.getAvailableLanguages()): |
1268 act = menu.addAction(language) |
1283 act = menu.addAction(language) |
1269 act.setCheckable(True) |
1284 act.setCheckable(True) |
1270 act.setData(language) |
1285 act.setData(language) |
1271 self.supportedSpellLanguages[language] = act |
1286 self.supportedSpellLanguages[language] = act |
1272 self.spellLanguagesActGrp.addAction(act) |
1287 self.spellLanguagesActGrp.addAction(act) |
1273 |
1288 |
1274 menu.triggered.connect(self.__spellLanguagesMenuTriggered) |
1289 menu.triggered.connect(self.__spellLanguagesMenuTriggered) |
1275 menu.aboutToShow.connect(self.__showContextMenuSpellLanguages) |
1290 menu.aboutToShow.connect(self.__showContextMenuSpellLanguages) |
1276 |
1291 |
1277 return menu |
1292 return menu |
1278 |
1293 |
1279 def __initContextMenuMargins(self): |
1294 def __initContextMenuMargins(self): |
1280 """ |
1295 """ |
1281 Private method used to setup the context menu for the margins. |
1296 Private method used to setup the context menu for the margins. |
1282 """ |
1297 """ |
1283 self.marginMenuActs = {} |
1298 self.marginMenuActs = {} |
1284 |
1299 |
1285 # bookmark margin |
1300 # bookmark margin |
1286 self.bmMarginMenu = QMenu() |
1301 self.bmMarginMenu = QMenu() |
1287 |
1302 |
1288 self.bmMarginMenu.addAction( |
1303 self.bmMarginMenu.addAction(self.tr("Toggle bookmark"), self.menuToggleBookmark) |
1289 self.tr('Toggle bookmark'), self.menuToggleBookmark) |
|
1290 self.marginMenuActs["NextBookmark"] = self.bmMarginMenu.addAction( |
1304 self.marginMenuActs["NextBookmark"] = self.bmMarginMenu.addAction( |
1291 self.tr('Next bookmark'), self.nextBookmark) |
1305 self.tr("Next bookmark"), self.nextBookmark |
|
1306 ) |
1292 self.marginMenuActs["PreviousBookmark"] = self.bmMarginMenu.addAction( |
1307 self.marginMenuActs["PreviousBookmark"] = self.bmMarginMenu.addAction( |
1293 self.tr('Previous bookmark'), self.previousBookmark) |
1308 self.tr("Previous bookmark"), self.previousBookmark |
|
1309 ) |
1294 self.marginMenuActs["ClearBookmark"] = self.bmMarginMenu.addAction( |
1310 self.marginMenuActs["ClearBookmark"] = self.bmMarginMenu.addAction( |
1295 self.tr('Clear all bookmarks'), self.clearBookmarks) |
1311 self.tr("Clear all bookmarks"), self.clearBookmarks |
1296 |
1312 ) |
|
1313 |
1297 self.bmMarginMenu.aboutToShow.connect( |
1314 self.bmMarginMenu.aboutToShow.connect( |
1298 lambda: self.__showContextMenuMargin(self.bmMarginMenu)) |
1315 lambda: self.__showContextMenuMargin(self.bmMarginMenu) |
1299 |
1316 ) |
|
1317 |
1300 # breakpoint margin |
1318 # breakpoint margin |
1301 self.bpMarginMenu = QMenu() |
1319 self.bpMarginMenu = QMenu() |
1302 |
1320 |
1303 self.marginMenuActs["Breakpoint"] = self.bpMarginMenu.addAction( |
1321 self.marginMenuActs["Breakpoint"] = self.bpMarginMenu.addAction( |
1304 self.tr('Toggle breakpoint'), self.menuToggleBreakpoint) |
1322 self.tr("Toggle breakpoint"), self.menuToggleBreakpoint |
|
1323 ) |
1305 self.marginMenuActs["TempBreakpoint"] = self.bpMarginMenu.addAction( |
1324 self.marginMenuActs["TempBreakpoint"] = self.bpMarginMenu.addAction( |
1306 self.tr('Toggle temporary breakpoint'), |
1325 self.tr("Toggle temporary breakpoint"), self.__menuToggleTemporaryBreakpoint |
1307 self.__menuToggleTemporaryBreakpoint) |
1326 ) |
1308 self.marginMenuActs["EditBreakpoint"] = self.bpMarginMenu.addAction( |
1327 self.marginMenuActs["EditBreakpoint"] = self.bpMarginMenu.addAction( |
1309 self.tr('Edit breakpoint...'), self.menuEditBreakpoint) |
1328 self.tr("Edit breakpoint..."), self.menuEditBreakpoint |
|
1329 ) |
1310 self.marginMenuActs["EnableBreakpoint"] = self.bpMarginMenu.addAction( |
1330 self.marginMenuActs["EnableBreakpoint"] = self.bpMarginMenu.addAction( |
1311 self.tr('Enable breakpoint'), |
1331 self.tr("Enable breakpoint"), self.__menuToggleBreakpointEnabled |
1312 self.__menuToggleBreakpointEnabled) |
1332 ) |
1313 self.marginMenuActs["NextBreakpoint"] = self.bpMarginMenu.addAction( |
1333 self.marginMenuActs["NextBreakpoint"] = self.bpMarginMenu.addAction( |
1314 self.tr('Next breakpoint'), self.menuNextBreakpoint) |
1334 self.tr("Next breakpoint"), self.menuNextBreakpoint |
1315 self.marginMenuActs["PreviousBreakpoint"] = ( |
1335 ) |
1316 self.bpMarginMenu.addAction( |
1336 self.marginMenuActs["PreviousBreakpoint"] = self.bpMarginMenu.addAction( |
1317 self.tr('Previous breakpoint'), |
1337 self.tr("Previous breakpoint"), self.menuPreviousBreakpoint |
1318 self.menuPreviousBreakpoint) |
|
1319 ) |
1338 ) |
1320 self.marginMenuActs["ClearBreakpoint"] = self.bpMarginMenu.addAction( |
1339 self.marginMenuActs["ClearBreakpoint"] = self.bpMarginMenu.addAction( |
1321 self.tr('Clear all breakpoints'), self.__menuClearBreakpoints) |
1340 self.tr("Clear all breakpoints"), self.__menuClearBreakpoints |
1322 |
1341 ) |
|
1342 |
1323 self.bpMarginMenu.aboutToShow.connect( |
1343 self.bpMarginMenu.aboutToShow.connect( |
1324 lambda: self.__showContextMenuMargin(self.bpMarginMenu)) |
1344 lambda: self.__showContextMenuMargin(self.bpMarginMenu) |
1325 |
1345 ) |
|
1346 |
1326 # fold margin |
1347 # fold margin |
1327 self.foldMarginMenu = QMenu() |
1348 self.foldMarginMenu = QMenu() |
1328 |
1349 |
1329 self.marginMenuActs["ToggleAllFolds"] = ( |
1350 self.marginMenuActs["ToggleAllFolds"] = self.foldMarginMenu.addAction( |
1330 self.foldMarginMenu.addAction( |
1351 self.tr("Toggle all folds"), self.foldAll |
1331 self.tr("Toggle all folds"), |
1352 ) |
1332 self.foldAll) |
1353 self.marginMenuActs[ |
1333 ) |
1354 "ToggleAllFoldsAndChildren" |
1334 self.marginMenuActs["ToggleAllFoldsAndChildren"] = ( |
1355 ] = self.foldMarginMenu.addAction( |
1335 self.foldMarginMenu.addAction( |
1356 self.tr("Toggle all folds (including children)"), lambda: self.foldAll(True) |
1336 self.tr("Toggle all folds (including children)"), |
1357 ) |
1337 lambda: self.foldAll(True)) |
1358 self.marginMenuActs["ToggleCurrentFold"] = self.foldMarginMenu.addAction( |
1338 ) |
1359 self.tr("Toggle current fold"), self.toggleCurrentFold |
1339 self.marginMenuActs["ToggleCurrentFold"] = ( |
|
1340 self.foldMarginMenu.addAction( |
|
1341 self.tr("Toggle current fold"), |
|
1342 self.toggleCurrentFold) |
|
1343 ) |
1360 ) |
1344 self.foldMarginMenu.addSeparator() |
1361 self.foldMarginMenu.addSeparator() |
1345 self.marginMenuActs["ExpandChildren"] = ( |
1362 self.marginMenuActs["ExpandChildren"] = self.foldMarginMenu.addAction( |
1346 self.foldMarginMenu.addAction( |
1363 self.tr("Expand (including children)"), |
1347 self.tr("Expand (including children)"), |
1364 self.__contextMenuExpandFoldWithChildren, |
1348 self.__contextMenuExpandFoldWithChildren) |
1365 ) |
1349 ) |
1366 self.marginMenuActs["CollapseChildren"] = self.foldMarginMenu.addAction( |
1350 self.marginMenuActs["CollapseChildren"] = ( |
1367 self.tr("Collapse (including children)"), |
1351 self.foldMarginMenu.addAction( |
1368 self.__contextMenuCollapseFoldWithChildren, |
1352 self.tr("Collapse (including children)"), |
|
1353 self.__contextMenuCollapseFoldWithChildren) |
|
1354 ) |
1369 ) |
1355 self.foldMarginMenu.addSeparator() |
1370 self.foldMarginMenu.addSeparator() |
1356 self.marginMenuActs["ClearAllFolds"] = ( |
1371 self.marginMenuActs["ClearAllFolds"] = self.foldMarginMenu.addAction( |
1357 self.foldMarginMenu.addAction( |
1372 self.tr("Clear all folds"), self.clearFolds |
1358 self.tr("Clear all folds"), |
1373 ) |
1359 self.clearFolds) |
1374 |
1360 ) |
|
1361 |
|
1362 self.foldMarginMenu.aboutToShow.connect( |
1375 self.foldMarginMenu.aboutToShow.connect( |
1363 lambda: self.__showContextMenuMargin(self.foldMarginMenu)) |
1376 lambda: self.__showContextMenuMargin(self.foldMarginMenu) |
1364 |
1377 ) |
|
1378 |
1365 # indicator margin |
1379 # indicator margin |
1366 self.indicMarginMenu = QMenu() |
1380 self.indicMarginMenu = QMenu() |
1367 |
1381 |
1368 self.marginMenuActs["GotoSyntaxError"] = ( |
1382 self.marginMenuActs["GotoSyntaxError"] = self.indicMarginMenu.addAction( |
1369 self.indicMarginMenu.addAction( |
1383 self.tr("Goto syntax error"), self.gotoSyntaxError |
1370 self.tr('Goto syntax error'), self.gotoSyntaxError) |
1384 ) |
1371 ) |
1385 self.marginMenuActs["ShowSyntaxError"] = self.indicMarginMenu.addAction( |
1372 self.marginMenuActs["ShowSyntaxError"] = ( |
1386 self.tr("Show syntax error message"), self.__showSyntaxError |
1373 self.indicMarginMenu.addAction( |
1387 ) |
1374 self.tr('Show syntax error message'), |
1388 self.marginMenuActs["ClearSyntaxError"] = self.indicMarginMenu.addAction( |
1375 self.__showSyntaxError) |
1389 self.tr("Clear syntax error"), self.clearSyntaxError |
1376 ) |
|
1377 self.marginMenuActs["ClearSyntaxError"] = ( |
|
1378 self.indicMarginMenu.addAction( |
|
1379 self.tr('Clear syntax error'), self.clearSyntaxError) |
|
1380 ) |
1390 ) |
1381 self.indicMarginMenu.addSeparator() |
1391 self.indicMarginMenu.addSeparator() |
1382 self.marginMenuActs["NextWarningMarker"] = ( |
1392 self.marginMenuActs["NextWarningMarker"] = self.indicMarginMenu.addAction( |
1383 self.indicMarginMenu.addAction( |
1393 self.tr("Next warning"), self.nextWarning |
1384 self.tr("Next warning"), self.nextWarning) |
1394 ) |
1385 ) |
1395 self.marginMenuActs["PreviousWarningMarker"] = self.indicMarginMenu.addAction( |
1386 self.marginMenuActs["PreviousWarningMarker"] = ( |
1396 self.tr("Previous warning"), self.previousWarning |
1387 self.indicMarginMenu.addAction( |
1397 ) |
1388 self.tr("Previous warning"), self.previousWarning) |
1398 self.marginMenuActs["ShowWarning"] = self.indicMarginMenu.addAction( |
1389 ) |
1399 self.tr("Show warning message"), self.__showWarning |
1390 self.marginMenuActs["ShowWarning"] = ( |
1400 ) |
1391 self.indicMarginMenu.addAction( |
1401 self.marginMenuActs["ClearWarnings"] = self.indicMarginMenu.addAction( |
1392 self.tr('Show warning message'), self.__showWarning) |
1402 self.tr("Clear warnings"), self.clearWarnings |
1393 ) |
|
1394 self.marginMenuActs["ClearWarnings"] = ( |
|
1395 self.indicMarginMenu.addAction( |
|
1396 self.tr('Clear warnings'), self.clearWarnings) |
|
1397 ) |
1403 ) |
1398 self.indicMarginMenu.addSeparator() |
1404 self.indicMarginMenu.addSeparator() |
1399 self.marginMenuActs["NextCoverageMarker"] = ( |
1405 self.marginMenuActs["NextCoverageMarker"] = self.indicMarginMenu.addAction( |
1400 self.indicMarginMenu.addAction( |
1406 self.tr("Next uncovered line"), self.nextUncovered |
1401 self.tr('Next uncovered line'), self.nextUncovered) |
1407 ) |
1402 ) |
1408 self.marginMenuActs["PreviousCoverageMarker"] = self.indicMarginMenu.addAction( |
1403 self.marginMenuActs["PreviousCoverageMarker"] = ( |
1409 self.tr("Previous uncovered line"), self.previousUncovered |
1404 self.indicMarginMenu.addAction( |
|
1405 self.tr('Previous uncovered line'), self.previousUncovered) |
|
1406 ) |
1410 ) |
1407 self.indicMarginMenu.addSeparator() |
1411 self.indicMarginMenu.addSeparator() |
1408 self.marginMenuActs["NextTaskMarker"] = ( |
1412 self.marginMenuActs["NextTaskMarker"] = self.indicMarginMenu.addAction( |
1409 self.indicMarginMenu.addAction( |
1413 self.tr("Next task"), self.nextTask |
1410 self.tr('Next task'), self.nextTask) |
1414 ) |
1411 ) |
1415 self.marginMenuActs["PreviousTaskMarker"] = self.indicMarginMenu.addAction( |
1412 self.marginMenuActs["PreviousTaskMarker"] = ( |
1416 self.tr("Previous task"), self.previousTask |
1413 self.indicMarginMenu.addAction( |
|
1414 self.tr('Previous task'), self.previousTask) |
|
1415 ) |
1417 ) |
1416 self.indicMarginMenu.addSeparator() |
1418 self.indicMarginMenu.addSeparator() |
1417 self.marginMenuActs["NextChangeMarker"] = ( |
1419 self.marginMenuActs["NextChangeMarker"] = self.indicMarginMenu.addAction( |
1418 self.indicMarginMenu.addAction( |
1420 self.tr("Next change"), self.nextChange |
1419 self.tr('Next change'), self.nextChange) |
1421 ) |
1420 ) |
1422 self.marginMenuActs["PreviousChangeMarker"] = self.indicMarginMenu.addAction( |
1421 self.marginMenuActs["PreviousChangeMarker"] = ( |
1423 self.tr("Previous change"), self.previousChange |
1422 self.indicMarginMenu.addAction( |
1424 ) |
1423 self.tr('Previous change'), self.previousChange) |
1425 self.marginMenuActs["ClearChangeMarkers"] = self.indicMarginMenu.addAction( |
1424 ) |
1426 self.tr("Clear changes"), self.__reinitOnlineChangeTrace |
1425 self.marginMenuActs["ClearChangeMarkers"] = ( |
1427 ) |
1426 self.indicMarginMenu.addAction( |
1428 |
1427 self.tr('Clear changes'), self.__reinitOnlineChangeTrace) |
|
1428 ) |
|
1429 |
|
1430 self.indicMarginMenu.aboutToShow.connect( |
1429 self.indicMarginMenu.aboutToShow.connect( |
1431 lambda: self.__showContextMenuMargin(self.indicMarginMenu)) |
1430 lambda: self.__showContextMenuMargin(self.indicMarginMenu) |
1432 |
1431 ) |
|
1432 |
1433 def exportFile(self, exporterFormat): |
1433 def exportFile(self, exporterFormat): |
1434 """ |
1434 """ |
1435 Public method to export the file. |
1435 Public method to export the file. |
1436 |
1436 |
1437 @param exporterFormat format the file should be exported into (string) |
1437 @param exporterFormat format the file should be exported into (string) |
1438 """ |
1438 """ |
1439 if exporterFormat: |
1439 if exporterFormat: |
1440 from . import Exporters |
1440 from . import Exporters |
|
1441 |
1441 exporter = Exporters.getExporter(exporterFormat, self) |
1442 exporter = Exporters.getExporter(exporterFormat, self) |
1442 if exporter: |
1443 if exporter: |
1443 exporter.exportSource() |
1444 exporter.exportSource() |
1444 else: |
1445 else: |
1445 EricMessageBox.critical( |
1446 EricMessageBox.critical( |
1446 self, |
1447 self, |
1447 self.tr("Export source"), |
1448 self.tr("Export source"), |
1448 self.tr( |
1449 self.tr( |
1449 """<p>No exporter available for the """ |
1450 """<p>No exporter available for the """ |
1450 """export format <b>{0}</b>. Aborting...</p>""") |
1451 """export format <b>{0}</b>. Aborting...</p>""" |
1451 .format(exporterFormat)) |
1452 ).format(exporterFormat), |
|
1453 ) |
1452 else: |
1454 else: |
1453 EricMessageBox.critical( |
1455 EricMessageBox.critical( |
1454 self, |
1456 self, |
1455 self.tr("Export source"), |
1457 self.tr("Export source"), |
1456 self.tr("""No export format given. Aborting...""")) |
1458 self.tr("""No export format given. Aborting..."""), |
1457 |
1459 ) |
|
1460 |
1458 def __showContextMenuLanguages(self): |
1461 def __showContextMenuLanguages(self): |
1459 """ |
1462 """ |
1460 Private slot handling the aboutToShow signal of the languages context |
1463 Private slot handling the aboutToShow signal of the languages context |
1461 menu. |
1464 menu. |
1462 """ |
1465 """ |
1463 if self.apiLanguage.startswith("Pygments|"): |
1466 if self.apiLanguage.startswith("Pygments|"): |
1464 self.pygmentsSelAct.setText( |
1467 self.pygmentsSelAct.setText( |
1465 self.tr("Alternatives ({0})").format( |
1468 self.tr("Alternatives ({0})").format(self.getLanguage(normalized=False)) |
1466 self.getLanguage(normalized=False))) |
1469 ) |
1467 else: |
1470 else: |
1468 self.pygmentsSelAct.setText(self.tr("Alternatives")) |
1471 self.pygmentsSelAct.setText(self.tr("Alternatives")) |
1469 self.showMenu.emit("Languages", self.languagesMenu, self) |
1472 self.showMenu.emit("Languages", self.languagesMenu, self) |
1470 |
1473 |
1471 def __selectPygmentsLexer(self): |
1474 def __selectPygmentsLexer(self): |
1472 """ |
1475 """ |
1473 Private method to select a specific pygments lexer. |
1476 Private method to select a specific pygments lexer. |
1474 |
1477 |
1475 @return name of the selected pygments lexer (string) |
1478 @return name of the selected pygments lexer (string) |
1476 """ |
1479 """ |
1477 from pygments.lexers import get_all_lexers |
1480 from pygments.lexers import get_all_lexers |
|
1481 |
1478 lexerList = sorted(lex[0] for lex in get_all_lexers()) |
1482 lexerList = sorted(lex[0] for lex in get_all_lexers()) |
1479 try: |
1483 try: |
1480 lexerSel = lexerList.index( |
1484 lexerSel = lexerList.index( |
1481 self.getLanguage(normalized=False, forPygments=True)) |
1485 self.getLanguage(normalized=False, forPygments=True) |
|
1486 ) |
1482 except ValueError: |
1487 except ValueError: |
1483 lexerSel = 0 |
1488 lexerSel = 0 |
1484 lexerName, ok = QInputDialog.getItem( |
1489 lexerName, ok = QInputDialog.getItem( |
1485 self, |
1490 self, |
1486 self.tr("Pygments Lexer"), |
1491 self.tr("Pygments Lexer"), |
1487 self.tr("Select the Pygments lexer to apply."), |
1492 self.tr("Select the Pygments lexer to apply."), |
1488 lexerList, |
1493 lexerList, |
1489 lexerSel, |
1494 lexerSel, |
1490 False) |
1495 False, |
|
1496 ) |
1491 if ok and lexerName: |
1497 if ok and lexerName: |
1492 return lexerName |
1498 return lexerName |
1493 else: |
1499 else: |
1494 return "" |
1500 return "" |
1495 |
1501 |
1496 def __languageMenuTriggered(self, act): |
1502 def __languageMenuTriggered(self, act): |
1497 """ |
1503 """ |
1498 Private method to handle the selection of a lexer language. |
1504 Private method to handle the selection of a lexer language. |
1499 |
1505 |
1500 @param act reference to the action that was triggered (QAction) |
1506 @param act reference to the action that was triggered (QAction) |
1501 """ |
1507 """ |
1502 if act == self.noLanguageAct: |
1508 if act == self.noLanguageAct: |
1503 self.__resetLanguage() |
1509 self.__resetLanguage() |
1504 elif act == self.pygmentsAct: |
1510 elif act == self.pygmentsAct: |
1626 act = self.languagesActGrp.checkedAction() |
1626 act = self.languagesActGrp.checkedAction() |
1627 if act: |
1627 if act: |
1628 act.setChecked(False) |
1628 act.setChecked(False) |
1629 else: |
1629 else: |
1630 self.supportedLanguages[self.apiLanguage][2].setChecked(True) |
1630 self.supportedLanguages[self.apiLanguage][2].setChecked(True) |
1631 |
1631 |
1632 def projectLexerAssociationsChanged(self): |
1632 def projectLexerAssociationsChanged(self): |
1633 """ |
1633 """ |
1634 Public slot to handle changes of the project lexer associations. |
1634 Public slot to handle changes of the project lexer associations. |
1635 """ |
1635 """ |
1636 self.setLanguage(self.fileName) |
1636 self.setLanguage(self.fileName) |
1637 |
1637 |
1638 def __showContextMenuEncodings(self): |
1638 def __showContextMenuEncodings(self): |
1639 """ |
1639 """ |
1640 Private slot handling the aboutToShow signal of the encodings context |
1640 Private slot handling the aboutToShow signal of the encodings context |
1641 menu. |
1641 menu. |
1642 """ |
1642 """ |
1643 self.showMenu.emit("Encodings", self.encodingsMenu, self) |
1643 self.showMenu.emit("Encodings", self.encodingsMenu, self) |
1644 |
1644 |
1645 def __encodingsMenuTriggered(self, act): |
1645 def __encodingsMenuTriggered(self, act): |
1646 """ |
1646 """ |
1647 Private method to handle the selection of an encoding. |
1647 Private method to handle the selection of an encoding. |
1648 |
1648 |
1649 @param act reference to the action that was triggered (QAction) |
1649 @param act reference to the action that was triggered (QAction) |
1650 """ |
1650 """ |
1651 encoding = act.data() |
1651 encoding = act.data() |
1652 self.setModified(True) |
1652 self.setModified(True) |
1653 self.__encodingChanged("{0}-selected".format(encoding)) |
1653 self.__encodingChanged("{0}-selected".format(encoding)) |
1654 |
1654 |
1655 def __checkEncoding(self): |
1655 def __checkEncoding(self): |
1656 """ |
1656 """ |
1657 Private method to check the selected encoding of the encodings submenu. |
1657 Private method to check the selected encoding of the encodings submenu. |
1658 """ |
1658 """ |
1659 with contextlib.suppress(AttributeError, KeyError): |
1659 with contextlib.suppress(AttributeError, KeyError): |
1660 (self.supportedEncodings[self.__normalizedEncoding()] |
1660 (self.supportedEncodings[self.__normalizedEncoding()].setChecked(True)) |
1661 .setChecked(True)) |
1661 |
1662 |
|
1663 def __encodingChanged(self, encoding, propagate=True): |
1662 def __encodingChanged(self, encoding, propagate=True): |
1664 """ |
1663 """ |
1665 Private slot to handle a change of the encoding. |
1664 Private slot to handle a change of the encoding. |
1666 |
1665 |
1667 @param encoding changed encoding (string) |
1666 @param encoding changed encoding (string) |
1668 @param propagate flag indicating to propagate the change (boolean) |
1667 @param propagate flag indicating to propagate the change (boolean) |
1669 """ |
1668 """ |
1670 self.encoding = encoding |
1669 self.encoding = encoding |
1671 self.__checkEncoding() |
1670 self.__checkEncoding() |
1672 |
1671 |
1673 if not self.inEncodingChanged and propagate: |
1672 if not self.inEncodingChanged and propagate: |
1674 self.inEncodingChanged = True |
1673 self.inEncodingChanged = True |
1675 self.encodingChanged.emit(self.encoding) |
1674 self.encodingChanged.emit(self.encoding) |
1676 self.inEncodingChanged = False |
1675 self.inEncodingChanged = False |
1677 |
1676 |
1678 def __normalizedEncoding(self, encoding=""): |
1677 def __normalizedEncoding(self, encoding=""): |
1679 """ |
1678 """ |
1680 Private method to calculate the normalized encoding string. |
1679 Private method to calculate the normalized encoding string. |
1681 |
1680 |
1682 @param encoding encoding to be normalized (string) |
1681 @param encoding encoding to be normalized (string) |
1683 @return normalized encoding (string) |
1682 @return normalized encoding (string) |
1684 """ |
1683 """ |
1685 if not encoding: |
1684 if not encoding: |
1686 encoding = self.encoding |
1685 encoding = self.encoding |
1687 return ( |
1686 return ( |
1688 encoding |
1687 encoding.replace("-default", "") |
1689 .replace("-default", "") |
|
1690 .replace("-guessed", "") |
1688 .replace("-guessed", "") |
1691 .replace("-selected", "") |
1689 .replace("-selected", "") |
1692 ) |
1690 ) |
1693 |
1691 |
1694 def __showContextMenuEol(self): |
1692 def __showContextMenuEol(self): |
1695 """ |
1693 """ |
1696 Private slot handling the aboutToShow signal of the eol context menu. |
1694 Private slot handling the aboutToShow signal of the eol context menu. |
1697 """ |
1695 """ |
1698 self.showMenu.emit("Eol", self.eolMenu, self) |
1696 self.showMenu.emit("Eol", self.eolMenu, self) |
1699 |
1697 |
1700 def __eolMenuTriggered(self, act): |
1698 def __eolMenuTriggered(self, act): |
1701 """ |
1699 """ |
1702 Private method to handle the selection of an eol type. |
1700 Private method to handle the selection of an eol type. |
1703 |
1701 |
1704 @param act reference to the action that was triggered (QAction) |
1702 @param act reference to the action that was triggered (QAction) |
1705 """ |
1703 """ |
1706 eol = act.data() |
1704 eol = act.data() |
1707 self.setEolModeByEolString(eol) |
1705 self.setEolModeByEolString(eol) |
1708 self.convertEols(self.eolMode()) |
1706 self.convertEols(self.eolMode()) |
1709 |
1707 |
1710 def __checkEol(self): |
1708 def __checkEol(self): |
1711 """ |
1709 """ |
1712 Private method to check the selected eol type of the eol submenu. |
1710 Private method to check the selected eol type of the eol submenu. |
1713 """ |
1711 """ |
1714 with contextlib.suppress(AttributeError, TypeError): |
1712 with contextlib.suppress(AttributeError, TypeError): |
1715 self.supportedEols[self.getLineSeparator()].setChecked(True) |
1713 self.supportedEols[self.getLineSeparator()].setChecked(True) |
1716 |
1714 |
1717 def __eolChanged(self): |
1715 def __eolChanged(self): |
1718 """ |
1716 """ |
1719 Private slot to handle a change of the eol mode. |
1717 Private slot to handle a change of the eol mode. |
1720 """ |
1718 """ |
1721 self.__checkEol() |
1719 self.__checkEol() |
1722 |
1720 |
1723 if not self.inEolChanged: |
1721 if not self.inEolChanged: |
1724 self.inEolChanged = True |
1722 self.inEolChanged = True |
1725 eol = self.getLineSeparator() |
1723 eol = self.getLineSeparator() |
1726 self.eolChanged.emit(eol) |
1724 self.eolChanged.emit(eol) |
1727 self.inEolChanged = False |
1725 self.inEolChanged = False |
1728 |
1726 |
1729 def __showContextMenuSpellCheck(self): |
1727 def __showContextMenuSpellCheck(self): |
1730 """ |
1728 """ |
1731 Private slot handling the aboutToShow signal of the spell check |
1729 Private slot handling the aboutToShow signal of the spell check |
1732 context menu. |
1730 context menu. |
1733 """ |
1731 """ |
1734 spellingAvailable = SpellChecker.isAvailable() |
1732 spellingAvailable = SpellChecker.isAvailable() |
1735 self.menuActs["SpellCheck"].setEnabled(spellingAvailable) |
1733 self.menuActs["SpellCheck"].setEnabled(spellingAvailable) |
1736 self.menuActs["SpellCheckSelection"].setEnabled( |
1734 self.menuActs["SpellCheckSelection"].setEnabled( |
1737 spellingAvailable and self.hasSelectedText()) |
1735 spellingAvailable and self.hasSelectedText() |
|
1736 ) |
1738 self.menuActs["SpellCheckRemove"].setEnabled( |
1737 self.menuActs["SpellCheckRemove"].setEnabled( |
1739 spellingAvailable and self.spellingMenuPos >= 0) |
1738 spellingAvailable and self.spellingMenuPos >= 0 |
|
1739 ) |
1740 self.menuActs["SpellCheckLanguages"].setEnabled(spellingAvailable) |
1740 self.menuActs["SpellCheckLanguages"].setEnabled(spellingAvailable) |
1741 |
1741 |
1742 self.showMenu.emit("SpellCheck", self.spellCheckMenu, self) |
1742 self.showMenu.emit("SpellCheck", self.spellCheckMenu, self) |
1743 |
1743 |
1744 def __showContextMenuSpellLanguages(self): |
1744 def __showContextMenuSpellLanguages(self): |
1745 """ |
1745 """ |
1746 Private slot handling the aboutToShow signal of the spell check |
1746 Private slot handling the aboutToShow signal of the spell check |
1747 languages context menu. |
1747 languages context menu. |
1748 """ |
1748 """ |
1749 self.showMenu.emit("SpellLanguage", self.spellLanguagesMenu, self) |
1749 self.showMenu.emit("SpellLanguage", self.spellLanguagesMenu, self) |
1750 |
1750 |
1751 def __spellLanguagesMenuTriggered(self, act): |
1751 def __spellLanguagesMenuTriggered(self, act): |
1752 """ |
1752 """ |
1753 Private method to handle the selection of a spell check language. |
1753 Private method to handle the selection of a spell check language. |
1754 |
1754 |
1755 @param act reference to the action that was triggered |
1755 @param act reference to the action that was triggered |
1756 @type QAction |
1756 @type QAction |
1757 """ |
1757 """ |
1758 language = act.data() |
1758 language = act.data() |
1759 self.__setSpellingLanguage(language) |
1759 self.__setSpellingLanguage(language) |
1760 self.spellLanguageChanged.emit(language) |
1760 self.spellLanguageChanged.emit(language) |
1761 |
1761 |
1762 def __checkSpellLanguage(self): |
1762 def __checkSpellLanguage(self): |
1763 """ |
1763 """ |
1764 Private slot to check the selected spell check language action. |
1764 Private slot to check the selected spell check language action. |
1765 """ |
1765 """ |
1766 language = self.getSpellingLanguage() |
1766 language = self.getSpellingLanguage() |
1767 with contextlib.suppress(AttributeError, KeyError): |
1767 with contextlib.suppress(AttributeError, KeyError): |
1768 self.supportedSpellLanguages[language].setChecked(True) |
1768 self.supportedSpellLanguages[language].setChecked(True) |
1769 |
1769 |
1770 def __spellLanguageChanged(self, language, propagate=True): |
1770 def __spellLanguageChanged(self, language, propagate=True): |
1771 """ |
1771 """ |
1772 Private slot to handle a change of the spell check language. |
1772 Private slot to handle a change of the spell check language. |
1773 |
1773 |
1774 @param language new spell check language |
1774 @param language new spell check language |
1775 @type str |
1775 @type str |
1776 @param propagate flag indicating to propagate the change |
1776 @param propagate flag indicating to propagate the change |
1777 @type bool |
1777 @type bool |
1778 """ |
1778 """ |
1779 self.__setSpellingLanguage(language) |
1779 self.__setSpellingLanguage(language) |
1780 self.__checkSpellLanguage() |
1780 self.__checkSpellLanguage() |
1781 |
1781 |
1782 if not self.__inSpellLanguageChanged and propagate: |
1782 if not self.__inSpellLanguageChanged and propagate: |
1783 self.__inSpellLanguageChanged = True |
1783 self.__inSpellLanguageChanged = True |
1784 self.spellLanguageChanged.emit(language) |
1784 self.spellLanguageChanged.emit(language) |
1785 self.__inSpellLanguageChanged = False |
1785 self.__inSpellLanguageChanged = False |
1786 |
1786 |
1787 def __bindLexer(self, filename, pyname=""): |
1787 def __bindLexer(self, filename, pyname=""): |
1788 """ |
1788 """ |
1789 Private slot to set the correct lexer depending on language. |
1789 Private slot to set the correct lexer depending on language. |
1790 |
1790 |
1791 @param filename filename used to determine the associated lexer |
1791 @param filename filename used to determine the associated lexer |
1792 language (string) |
1792 language (string) |
1793 @param pyname name of the pygments lexer to use (string) |
1793 @param pyname name of the pygments lexer to use (string) |
1794 """ |
1794 """ |
1795 if ( |
1795 if self.lexer_ is not None and ( |
1796 self.lexer_ is not None and |
1796 self.lexer_.lexer() == "container" or self.lexer_.lexer() is None |
1797 (self.lexer_.lexer() == "container" or |
|
1798 self.lexer_.lexer() is None) |
|
1799 ): |
1797 ): |
1800 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded) |
1798 self.SCN_STYLENEEDED.disconnect(self.__styleNeeded) |
1801 |
1799 |
1802 language = "" |
1800 language = "" |
1803 if not self.filetype: |
1801 if not self.filetype: |
1804 if filename: |
1802 if filename: |
1805 basename = os.path.basename(filename) |
1803 basename = os.path.basename(filename) |
1806 if ( |
1804 if self.project.isOpen() and self.project.isProjectFile(filename): |
1807 self.project.isOpen() and |
|
1808 self.project.isProjectFile(filename) |
|
1809 ): |
|
1810 language = self.project.getEditorLexerAssoc(basename) |
1805 language = self.project.getEditorLexerAssoc(basename) |
1811 if not language: |
1806 if not language: |
1812 language = Preferences.getEditorLexerAssoc(basename) |
1807 language = Preferences.getEditorLexerAssoc(basename) |
1813 if language == "Text": |
1808 if language == "Text": |
1814 # no highlighting for plain text files |
1809 # no highlighting for plain text files |
1815 self.__resetLanguage() |
1810 self.__resetLanguage() |
1816 return |
1811 return |
1817 |
1812 |
1818 if not language: |
1813 if not language: |
1819 bindName = self.__bindName(self.text(0)) |
1814 bindName = self.__bindName(self.text(0)) |
1820 if bindName: |
1815 if bindName: |
1821 language = Preferences.getEditorLexerAssoc(bindName) |
1816 language = Preferences.getEditorLexerAssoc(bindName) |
1822 if language == "Python": |
1817 if language == "Python": |
1823 # correction for Python |
1818 # correction for Python |
1824 pyVer = Utilities.determinePythonVersion( |
1819 pyVer = Utilities.determinePythonVersion(filename, self.text(0), self) |
1825 filename, self.text(0), self) |
|
1826 language = "Python{0}".format(pyVer) |
1820 language = "Python{0}".format(pyVer) |
1827 if language in ['Python3', 'MicroPython', 'Cython', 'Ruby', |
1821 if language in [ |
1828 'JavaScript', 'YAML', 'JSON']: |
1822 "Python3", |
|
1823 "MicroPython", |
|
1824 "Cython", |
|
1825 "Ruby", |
|
1826 "JavaScript", |
|
1827 "YAML", |
|
1828 "JSON", |
|
1829 ]: |
1829 self.filetype = language |
1830 self.filetype = language |
1830 else: |
1831 else: |
1831 self.filetype = "" |
1832 self.filetype = "" |
1832 else: |
1833 else: |
1833 language = self.filetype |
1834 language = self.filetype |
1834 |
1835 |
1835 if language.startswith("Pygments|"): |
1836 if language.startswith("Pygments|"): |
1836 pyname = language |
1837 pyname = language |
1837 self.filetype = language.split("|")[-1] |
1838 self.filetype = language.split("|")[-1] |
1838 language = "" |
1839 language = "" |
1839 |
1840 |
1840 from . import Lexers |
1841 from . import Lexers |
|
1842 |
1841 self.lexer_ = Lexers.getLexer(language, self, pyname=pyname) |
1843 self.lexer_ = Lexers.getLexer(language, self, pyname=pyname) |
1842 if self.lexer_ is None: |
1844 if self.lexer_ is None: |
1843 self.setLexer() |
1845 self.setLexer() |
1844 self.apiLanguage = "" |
1846 self.apiLanguage = "" |
1845 return |
1847 return |
1846 |
1848 |
1847 if pyname: |
1849 if pyname: |
1848 if pyname.startswith("Pygments|"): |
1850 if pyname.startswith("Pygments|"): |
1849 self.apiLanguage = pyname |
1851 self.apiLanguage = pyname |
1850 else: |
1852 else: |
1851 self.apiLanguage = "Pygments|{0}".format(pyname) |
1853 self.apiLanguage = "Pygments|{0}".format(pyname) |
1862 self.apiLanguage = "Gettext" |
1864 self.apiLanguage = "Gettext" |
1863 self.setLexer(self.lexer_) |
1865 self.setLexer(self.lexer_) |
1864 self.__setMarginsDisplay() |
1866 self.__setMarginsDisplay() |
1865 if self.lexer_.lexer() == "container" or self.lexer_.lexer() is None: |
1867 if self.lexer_.lexer() == "container" or self.lexer_.lexer() is None: |
1866 self.SCN_STYLENEEDED.connect(self.__styleNeeded) |
1868 self.SCN_STYLENEEDED.connect(self.__styleNeeded) |
1867 |
1869 |
1868 # get the font for style 0 and set it as the default font |
1870 # get the font for style 0 and set it as the default font |
1869 key = ( |
1871 key = ( |
1870 'Scintilla/Guessed/style0/font' |
1872 "Scintilla/Guessed/style0/font" |
1871 if pyname and pyname.startswith("Pygments|") else |
1873 if pyname and pyname.startswith("Pygments|") |
1872 'Scintilla/{0}/style0/font'.format(self.lexer_.language()) |
1874 else "Scintilla/{0}/style0/font".format(self.lexer_.language()) |
1873 ) |
1875 ) |
1874 fdesc = Preferences.getSettings().value(key) |
1876 fdesc = Preferences.getSettings().value(key) |
1875 if fdesc is not None: |
1877 if fdesc is not None: |
1876 font = QFont([fdesc[0]], int(fdesc[1])) |
1878 font = QFont([fdesc[0]], int(fdesc[1])) |
1877 self.lexer_.setDefaultFont(font) |
1879 self.lexer_.setDefaultFont(font) |
1878 self.lexer_.readSettings(Preferences.getSettings(), "Scintilla") |
1880 self.lexer_.readSettings(Preferences.getSettings(), "Scintilla") |
1879 if self.lexer_.hasSubstyles(): |
1881 if self.lexer_.hasSubstyles(): |
1880 self.lexer_.readSubstyles(self) |
1882 self.lexer_.readSubstyles(self) |
1881 |
1883 |
1882 # now set the lexer properties |
1884 # now set the lexer properties |
1883 self.lexer_.initProperties() |
1885 self.lexer_.initProperties() |
1884 |
1886 |
1885 # initialize the lexer APIs settings |
1887 # initialize the lexer APIs settings |
1886 projectType = ( |
1888 projectType = ( |
1887 self.project.getProjectType() |
1889 self.project.getProjectType() |
1888 if self.project.isOpen() and self.project.isProjectFile(filename) |
1890 if self.project.isOpen() and self.project.isProjectFile(filename) |
1889 else "" |
1891 else "" |
1890 ) |
1892 ) |
1891 api = self.vm.getAPIsManager().getAPIs(self.apiLanguage, |
1893 api = self.vm.getAPIsManager().getAPIs( |
1892 projectType=projectType) |
1894 self.apiLanguage, projectType=projectType |
|
1895 ) |
1893 if api is not None and not api.isEmpty(): |
1896 if api is not None and not api.isEmpty(): |
1894 self.lexer_.setAPIs(api.getQsciAPIs()) |
1897 self.lexer_.setAPIs(api.getQsciAPIs()) |
1895 self.acAPI = True |
1898 self.acAPI = True |
1896 else: |
1899 else: |
1897 self.acAPI = False |
1900 self.acAPI = False |
1898 self.autoCompletionAPIsAvailable.emit(self.acAPI) |
1901 self.autoCompletionAPIsAvailable.emit(self.acAPI) |
1899 |
1902 |
1900 self.__setAnnotationStyles() |
1903 self.__setAnnotationStyles() |
1901 |
1904 |
1902 self.lexer_.setDefaultColor(self.lexer_.color(0)) |
1905 self.lexer_.setDefaultColor(self.lexer_.color(0)) |
1903 self.lexer_.setDefaultPaper(self.lexer_.paper(0)) |
1906 self.lexer_.setDefaultPaper(self.lexer_.paper(0)) |
1904 |
1907 |
1905 def __styleNeeded(self, position): |
1908 def __styleNeeded(self, position): |
1906 """ |
1909 """ |
1907 Private slot to handle the need for more styling. |
1910 Private slot to handle the need for more styling. |
1908 |
1911 |
1909 @param position end position, that needs styling (integer) |
1912 @param position end position, that needs styling (integer) |
1910 """ |
1913 """ |
1911 self.lexer_.styleText(self.getEndStyled(), position) |
1914 self.lexer_.styleText(self.getEndStyled(), position) |
1912 |
1915 |
1913 def getLexer(self): |
1916 def getLexer(self): |
1914 """ |
1917 """ |
1915 Public method to retrieve a reference to the lexer object. |
1918 Public method to retrieve a reference to the lexer object. |
1916 |
1919 |
1917 @return the lexer object (Lexer) |
1920 @return the lexer object (Lexer) |
1918 """ |
1921 """ |
1919 return self.lexer_ |
1922 return self.lexer_ |
1920 |
1923 |
1921 def getLanguage(self, normalized=True, forPygments=False): |
1924 def getLanguage(self, normalized=True, forPygments=False): |
1922 """ |
1925 """ |
1923 Public method to retrieve the language of the editor. |
1926 Public method to retrieve the language of the editor. |
1924 |
1927 |
1925 @param normalized flag indicating to normalize some Pygments |
1928 @param normalized flag indicating to normalize some Pygments |
1926 lexer names (boolean) |
1929 lexer names (boolean) |
1927 @param forPygments flag indicating to normalize some lexer |
1930 @param forPygments flag indicating to normalize some lexer |
1928 names for Pygments (boolean) |
1931 names for Pygments (boolean) |
1929 @return language of the editor (string) |
1932 @return language of the editor (string) |
1930 """ |
1933 """ |
1931 if ( |
1934 if self.apiLanguage == "Guessed" or self.apiLanguage.startswith("Pygments|"): |
1932 self.apiLanguage == "Guessed" or |
|
1933 self.apiLanguage.startswith("Pygments|") |
|
1934 ): |
|
1935 lang = self.lexer_.name() |
1935 lang = self.lexer_.name() |
1936 if normalized: |
1936 if normalized: |
1937 # adjust some Pygments lexer names |
1937 # adjust some Pygments lexer names |
1938 if lang in ("Python 2.x", "Python"): |
1938 if lang in ("Python 2.x", "Python"): |
1939 lang = "Python3" |
1939 lang = "Python3" |
1940 elif lang == "Protocol Buffer": |
1940 elif lang == "Protocol Buffer": |
1941 lang = "Protocol" |
1941 lang = "Protocol" |
1942 |
1942 |
1943 else: |
1943 else: |
1944 lang = self.apiLanguage |
1944 lang = self.apiLanguage |
1945 if forPygments: |
1945 if forPygments: |
1946 # adjust some names to Pygments lexer names |
1946 # adjust some names to Pygments lexer names |
1947 if lang == "Python3": |
1947 if lang == "Python3": |
1948 lang = "Python" |
1948 lang = "Python" |
1949 elif lang == "Protocol": |
1949 elif lang == "Protocol": |
1950 lang = "Protocol Buffer" |
1950 lang = "Protocol Buffer" |
1951 return lang |
1951 return lang |
1952 |
1952 |
1953 def getApiLanguage(self): |
1953 def getApiLanguage(self): |
1954 """ |
1954 """ |
1955 Public method to get the API language of the editor. |
1955 Public method to get the API language of the editor. |
1956 |
1956 |
1957 @return API language |
1957 @return API language |
1958 @rtype str |
1958 @rtype str |
1959 """ |
1959 """ |
1960 return self.apiLanguage |
1960 return self.apiLanguage |
1961 |
1961 |
1962 def __bindCompleter(self, filename): |
1962 def __bindCompleter(self, filename): |
1963 """ |
1963 """ |
1964 Private slot to set the correct typing completer depending on language. |
1964 Private slot to set the correct typing completer depending on language. |
1965 |
1965 |
1966 @param filename filename used to determine the associated typing |
1966 @param filename filename used to determine the associated typing |
1967 completer language (string) |
1967 completer language (string) |
1968 """ |
1968 """ |
1969 if self.completer is not None: |
1969 if self.completer is not None: |
1970 self.completer.setEnabled(False) |
1970 self.completer.setEnabled(False) |
1971 self.completer = None |
1971 self.completer = None |
1972 |
1972 |
1973 filename = os.path.basename(filename) |
1973 filename = os.path.basename(filename) |
1974 apiLanguage = Preferences.getEditorLexerAssoc(filename) |
1974 apiLanguage = Preferences.getEditorLexerAssoc(filename) |
1975 if apiLanguage == "": |
1975 if apiLanguage == "": |
1976 pyVer = self.__getPyVersion() |
1976 pyVer = self.__getPyVersion() |
1977 if pyVer: |
1977 if pyVer: |
1978 apiLanguage = "Python{0}".format(pyVer) |
1978 apiLanguage = "Python{0}".format(pyVer) |
1979 elif self.isRubyFile(): |
1979 elif self.isRubyFile(): |
1980 apiLanguage = "Ruby" |
1980 apiLanguage = "Ruby" |
1981 |
1981 |
1982 from . import TypingCompleters |
1982 from . import TypingCompleters |
|
1983 |
1983 self.completer = TypingCompleters.getCompleter(apiLanguage, self) |
1984 self.completer = TypingCompleters.getCompleter(apiLanguage, self) |
1984 |
1985 |
1985 def getCompleter(self): |
1986 def getCompleter(self): |
1986 """ |
1987 """ |
1987 Public method to retrieve a reference to the completer object. |
1988 Public method to retrieve a reference to the completer object. |
1988 |
1989 |
1989 @return the completer object (CompleterBase) |
1990 @return the completer object (CompleterBase) |
1990 """ |
1991 """ |
1991 return self.completer |
1992 return self.completer |
1992 |
1993 |
1993 def __modificationChanged(self, m): |
1994 def __modificationChanged(self, m): |
1994 """ |
1995 """ |
1995 Private slot to handle the modificationChanged signal. |
1996 Private slot to handle the modificationChanged signal. |
1996 |
1997 |
1997 It emits the signal modificationStatusChanged with parameters |
1998 It emits the signal modificationStatusChanged with parameters |
1998 m and self. |
1999 m and self. |
1999 |
2000 |
2000 @param m modification status |
2001 @param m modification status |
2001 """ |
2002 """ |
2002 if not m and bool(self.fileName) and pathlib.Path(self.fileName).exists(): |
2003 if not m and bool(self.fileName) and pathlib.Path(self.fileName).exists(): |
2003 self.lastModified = pathlib.Path(self.fileName).stat().st_mtime |
2004 self.lastModified = pathlib.Path(self.fileName).stat().st_mtime |
2004 self.modificationStatusChanged.emit(m, self) |
2005 self.modificationStatusChanged.emit(m, self) |
2005 self.undoAvailable.emit(self.isUndoAvailable()) |
2006 self.undoAvailable.emit(self.isUndoAvailable()) |
2006 self.redoAvailable.emit(self.isRedoAvailable()) |
2007 self.redoAvailable.emit(self.isRedoAvailable()) |
2007 |
2008 |
2008 def __cursorPositionChanged(self, line, index): |
2009 def __cursorPositionChanged(self, line, index): |
2009 """ |
2010 """ |
2010 Private slot to handle the cursorPositionChanged signal. |
2011 Private slot to handle the cursorPositionChanged signal. |
2011 |
2012 |
2012 It emits the signal cursorChanged with parameters fileName, |
2013 It emits the signal cursorChanged with parameters fileName, |
2013 line and pos. |
2014 line and pos. |
2014 |
2015 |
2015 @param line line number of the cursor |
2016 @param line line number of the cursor |
2016 @param index position in line of the cursor |
2017 @param index position in line of the cursor |
2017 """ |
2018 """ |
2018 self.cursorChanged.emit(self.fileName, line + 1, index) |
2019 self.cursorChanged.emit(self.fileName, line + 1, index) |
2019 |
2020 |
2020 if Preferences.getEditor("MarkOccurrencesEnabled"): |
2021 if Preferences.getEditor("MarkOccurrencesEnabled"): |
2021 self.__markOccurrencesTimer.stop() |
2022 self.__markOccurrencesTimer.stop() |
2022 self.__markOccurrencesTimer.start() |
2023 self.__markOccurrencesTimer.start() |
2023 |
2024 |
2024 if self.lastLine != line: |
2025 if self.lastLine != line: |
2025 self.cursorLineChanged.emit(line) |
2026 self.cursorLineChanged.emit(line) |
2026 |
2027 |
2027 if self.spell is not None: |
2028 if self.spell is not None: |
2028 # do spell checking |
2029 # do spell checking |
2029 doSpelling = True |
2030 doSpelling = True |
2030 if self.lastLine == line: |
2031 if self.lastLine == line: |
2031 start, end = self.getWordBoundaries( |
2032 start, end = self.getWordBoundaries(line, index, useWordChars=False) |
2032 line, index, useWordChars=False) |
|
2033 if start <= self.lastIndex and self.lastIndex <= end: |
2033 if start <= self.lastIndex and self.lastIndex <= end: |
2034 doSpelling = False |
2034 doSpelling = False |
2035 if doSpelling: |
2035 if doSpelling: |
2036 pos = self.positionFromLineIndex(self.lastLine, self.lastIndex) |
2036 pos = self.positionFromLineIndex(self.lastLine, self.lastIndex) |
2037 self.spell.checkWord(pos) |
2037 self.spell.checkWord(pos) |
2038 |
2038 |
2039 if self.lastLine != line: |
2039 if self.lastLine != line: |
2040 self.__markerMap.update() |
2040 self.__markerMap.update() |
2041 |
2041 |
2042 self.lastLine = line |
2042 self.lastLine = line |
2043 self.lastIndex = index |
2043 self.lastIndex = index |
2044 |
2044 |
2045 def __modificationReadOnly(self): |
2045 def __modificationReadOnly(self): |
2046 """ |
2046 """ |
2047 Private slot to handle the modificationAttempted signal. |
2047 Private slot to handle the modificationAttempted signal. |
2048 """ |
2048 """ |
2049 EricMessageBox.warning( |
2049 EricMessageBox.warning( |
2050 self, |
2050 self, |
2051 self.tr("Modification of Read Only file"), |
2051 self.tr("Modification of Read Only file"), |
2052 self.tr("""You are attempting to change a read only file. """ |
2052 self.tr( |
2053 """Please save to a different file first.""")) |
2053 """You are attempting to change a read only file. """ |
2054 |
2054 """Please save to a different file first.""" |
|
2055 ), |
|
2056 ) |
|
2057 |
2055 def setNoName(self, noName): |
2058 def setNoName(self, noName): |
2056 """ |
2059 """ |
2057 Public method to set the display string for an unnamed editor. |
2060 Public method to set the display string for an unnamed editor. |
2058 |
2061 |
2059 @param noName display string for this unnamed editor (string) |
2062 @param noName display string for this unnamed editor (string) |
2060 """ |
2063 """ |
2061 self.noName = noName |
2064 self.noName = noName |
2062 |
2065 |
2063 def getNoName(self): |
2066 def getNoName(self): |
2064 """ |
2067 """ |
2065 Public method to get the display string for an unnamed editor. |
2068 Public method to get the display string for an unnamed editor. |
2066 |
2069 |
2067 @return display string for this unnamed editor (string) |
2070 @return display string for this unnamed editor (string) |
2068 """ |
2071 """ |
2069 return self.noName |
2072 return self.noName |
2070 |
2073 |
2071 def getFileName(self): |
2074 def getFileName(self): |
2072 """ |
2075 """ |
2073 Public method to return the name of the file being displayed. |
2076 Public method to return the name of the file being displayed. |
2074 |
2077 |
2075 @return filename of the displayed file (string) |
2078 @return filename of the displayed file (string) |
2076 """ |
2079 """ |
2077 return self.fileName |
2080 return self.fileName |
2078 |
2081 |
2079 def getFileType(self): |
2082 def getFileType(self): |
2080 """ |
2083 """ |
2081 Public method to return the type of the file being displayed. |
2084 Public method to return the type of the file being displayed. |
2082 |
2085 |
2083 @return type of the displayed file (string) |
2086 @return type of the displayed file (string) |
2084 """ |
2087 """ |
2085 return self.filetype |
2088 return self.filetype |
2086 |
2089 |
2087 def getFileTypeByFlag(self): |
2090 def getFileTypeByFlag(self): |
2088 """ |
2091 """ |
2089 Public method to return the type of the file, if it was set by an |
2092 Public method to return the type of the file, if it was set by an |
2090 eflag: marker. |
2093 eflag: marker. |
2091 |
2094 |
2092 @return type of the displayed file, if set by an eflag: marker or an |
2095 @return type of the displayed file, if set by an eflag: marker or an |
2093 empty string (string) |
2096 empty string (string) |
2094 """ |
2097 """ |
2095 if self.filetypeByFlag: |
2098 if self.filetypeByFlag: |
2096 return self.filetype |
2099 return self.filetype |
2097 else: |
2100 else: |
2098 return "" |
2101 return "" |
2099 |
2102 |
2100 def determineFileType(self): |
2103 def determineFileType(self): |
2101 """ |
2104 """ |
2102 Public method to determine the file type using various tests. |
2105 Public method to determine the file type using various tests. |
2103 |
2106 |
2104 @return type of the displayed file or an empty string (string) |
2107 @return type of the displayed file or an empty string (string) |
2105 """ |
2108 """ |
2106 ftype = self.filetype |
2109 ftype = self.filetype |
2107 if not ftype: |
2110 if not ftype: |
2108 pyVer = self.__getPyVersion() |
2111 pyVer = self.__getPyVersion() |
2290 @param token ??? |
2297 @param token ??? |
2291 @param annotationLinesAdded number of added/deleted annotation lines |
2298 @param annotationLinesAdded number of added/deleted annotation lines |
2292 (integer) |
2299 (integer) |
2293 """ |
2300 """ |
2294 if ( |
2301 if ( |
2295 mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) and |
2302 mtype & (self.SC_MOD_INSERTTEXT | self.SC_MOD_DELETETEXT) |
2296 linesAdded != 0 and |
2303 and linesAdded != 0 |
2297 self.breaks |
2304 and self.breaks |
2298 ): |
2305 ): |
2299 bps = [] # list of breakpoints |
2306 bps = [] # list of breakpoints |
2300 for handle, (ln, cond, temp, enabled, ignorecount) in ( |
2307 for handle, (ln, cond, temp, enabled, ignorecount) in self.breaks.items(): |
2301 self.breaks.items() |
|
2302 ): |
|
2303 line = self.markerLine(handle) + 1 |
2308 line = self.markerLine(handle) + 1 |
2304 if ln != line: |
2309 if ln != line: |
2305 bps.append((ln, line)) |
2310 bps.append((ln, line)) |
2306 self.breaks[handle] = (line, cond, temp, enabled, |
2311 self.breaks[handle] = (line, cond, temp, enabled, ignorecount) |
2307 ignorecount) |
|
2308 self.inLinesChanged = True |
2312 self.inLinesChanged = True |
2309 for ln, line in sorted(bps, reverse=linesAdded > 0): |
2313 for ln, line in sorted(bps, reverse=linesAdded > 0): |
2310 index1 = self.breakpointModel.getBreakPointIndex( |
2314 index1 = self.breakpointModel.getBreakPointIndex(self.fileName, ln) |
2311 self.fileName, ln) |
|
2312 index2 = self.breakpointModel.index(index1.row(), 1) |
2315 index2 = self.breakpointModel.index(index1.row(), 1) |
2313 self.breakpointModel.setData(index2, line) |
2316 self.breakpointModel.setData(index2, line) |
2314 self.inLinesChanged = False |
2317 self.inLinesChanged = False |
2315 |
2318 |
2316 def __restoreBreakpoints(self): |
2319 def __restoreBreakpoints(self): |
2317 """ |
2320 """ |
2318 Private method to restore the breakpoints. |
2321 Private method to restore the breakpoints. |
2319 """ |
2322 """ |
2320 for handle in list(self.breaks.keys()): |
2323 for handle in list(self.breaks.keys()): |
2321 self.markerDeleteHandle(handle) |
2324 self.markerDeleteHandle(handle) |
2322 self.__addBreakPoints( |
2325 self.__addBreakPoints(QModelIndex(), 0, self.breakpointModel.rowCount() - 1) |
2323 QModelIndex(), 0, self.breakpointModel.rowCount() - 1) |
|
2324 self.__markerMap.update() |
2326 self.__markerMap.update() |
2325 |
2327 |
2326 def __deleteBreakPoints(self, parentIndex, start, end): |
2328 def __deleteBreakPoints(self, parentIndex, start, end): |
2327 """ |
2329 """ |
2328 Private slot to delete breakpoints. |
2330 Private slot to delete breakpoints. |
2329 |
2331 |
2330 @param parentIndex index of parent item (QModelIndex) |
2332 @param parentIndex index of parent item (QModelIndex) |
2331 @param start start row (integer) |
2333 @param start start row (integer) |
2332 @param end end row (integer) |
2334 @param end end row (integer) |
2333 """ |
2335 """ |
2334 for row in range(start, end + 1): |
2336 for row in range(start, end + 1): |
2335 index = self.breakpointModel.index(row, 0, parentIndex) |
2337 index = self.breakpointModel.index(row, 0, parentIndex) |
2336 fn, lineno = self.breakpointModel.getBreakPointByIndex(index)[0:2] |
2338 fn, lineno = self.breakpointModel.getBreakPointByIndex(index)[0:2] |
2337 if fn == self.fileName: |
2339 if fn == self.fileName: |
2338 self.clearBreakpoint(lineno) |
2340 self.clearBreakpoint(lineno) |
2339 |
2341 |
2340 def __changeBreakPoints(self, startIndex, endIndex): |
2342 def __changeBreakPoints(self, startIndex, endIndex): |
2341 """ |
2343 """ |
2342 Private slot to set changed breakpoints. |
2344 Private slot to set changed breakpoints. |
2343 |
2345 |
2344 @param startIndex start index of the breakpoints being changed |
2346 @param startIndex start index of the breakpoints being changed |
2345 (QModelIndex) |
2347 (QModelIndex) |
2346 @param endIndex end index of the breakpoints being changed |
2348 @param endIndex end index of the breakpoints being changed |
2347 (QModelIndex) |
2349 (QModelIndex) |
2348 """ |
2350 """ |
2349 if not self.inLinesChanged: |
2351 if not self.inLinesChanged: |
2350 self.__addBreakPoints(QModelIndex(), startIndex.row(), |
2352 self.__addBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) |
2351 endIndex.row()) |
2353 |
2352 |
|
2353 def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): |
2354 def __breakPointDataAboutToBeChanged(self, startIndex, endIndex): |
2354 """ |
2355 """ |
2355 Private slot to handle the dataAboutToBeChanged signal of the |
2356 Private slot to handle the dataAboutToBeChanged signal of the |
2356 breakpoint model. |
2357 breakpoint model. |
2357 |
2358 |
2358 @param startIndex start index of the rows to be changed (QModelIndex) |
2359 @param startIndex start index of the rows to be changed (QModelIndex) |
2359 @param endIndex end index of the rows to be changed (QModelIndex) |
2360 @param endIndex end index of the rows to be changed (QModelIndex) |
2360 """ |
2361 """ |
2361 self.__deleteBreakPoints(QModelIndex(), startIndex.row(), |
2362 self.__deleteBreakPoints(QModelIndex(), startIndex.row(), endIndex.row()) |
2362 endIndex.row()) |
2363 |
2363 |
|
2364 def __addBreakPoints(self, parentIndex, start, end): |
2364 def __addBreakPoints(self, parentIndex, start, end): |
2365 """ |
2365 """ |
2366 Private slot to add breakpoints. |
2366 Private slot to add breakpoints. |
2367 |
2367 |
2368 @param parentIndex index of parent item (QModelIndex) |
2368 @param parentIndex index of parent item (QModelIndex) |
2369 @param start start row (integer) |
2369 @param start start row (integer) |
2370 @param end end row (integer) |
2370 @param end end row (integer) |
2371 """ |
2371 """ |
2372 for row in range(start, end + 1): |
2372 for row in range(start, end + 1): |
2373 index = self.breakpointModel.index(row, 0, parentIndex) |
2373 index = self.breakpointModel.index(row, 0, parentIndex) |
2374 fn, line, cond, temp, enabled, ignorecount = ( |
2374 ( |
2375 self.breakpointModel.getBreakPointByIndex(index)[:6] |
2375 fn, |
2376 ) |
2376 line, |
|
2377 cond, |
|
2378 temp, |
|
2379 enabled, |
|
2380 ignorecount, |
|
2381 ) = self.breakpointModel.getBreakPointByIndex(index)[:6] |
2377 if fn == self.fileName: |
2382 if fn == self.fileName: |
2378 self.newBreakpointWithProperties( |
2383 self.newBreakpointWithProperties( |
2379 line, (cond, temp, enabled, ignorecount)) |
2384 line, (cond, temp, enabled, ignorecount) |
2380 |
2385 ) |
|
2386 |
2381 def clearBreakpoint(self, line): |
2387 def clearBreakpoint(self, line): |
2382 """ |
2388 """ |
2383 Public method to clear a breakpoint. |
2389 Public method to clear a breakpoint. |
2384 |
2390 |
2385 Note: This doesn't clear the breakpoint in the debugger, |
2391 Note: This doesn't clear the breakpoint in the debugger, |
2386 it just deletes it from the editor internal list of breakpoints. |
2392 it just deletes it from the editor internal list of breakpoints. |
2387 |
2393 |
2388 @param line line number of the breakpoint (integer) |
2394 @param line line number of the breakpoint (integer) |
2389 """ |
2395 """ |
2390 if self.inLinesChanged: |
2396 if self.inLinesChanged: |
2391 return |
2397 return |
2392 |
2398 |
2393 for handle in self.breaks: |
2399 for handle in self.breaks: |
2394 if self.markerLine(handle) == line - 1: |
2400 if self.markerLine(handle) == line - 1: |
2395 break |
2401 break |
2396 else: |
2402 else: |
2397 # not found, simply ignore it |
2403 # not found, simply ignore it |
2398 return |
2404 return |
2399 |
2405 |
2400 del self.breaks[handle] |
2406 del self.breaks[handle] |
2401 self.markerDeleteHandle(handle) |
2407 self.markerDeleteHandle(handle) |
2402 self.__markerMap.update() |
2408 self.__markerMap.update() |
2403 |
2409 |
2404 def newBreakpointWithProperties(self, line, properties): |
2410 def newBreakpointWithProperties(self, line, properties): |
2405 """ |
2411 """ |
2406 Public method to set a new breakpoint and its properties. |
2412 Public method to set a new breakpoint and its properties. |
2407 |
2413 |
2408 @param line line number of the breakpoint (integer) |
2414 @param line line number of the breakpoint (integer) |
2409 @param properties properties for the breakpoint (tuple) |
2415 @param properties properties for the breakpoint (tuple) |
2410 (condition, temporary flag, enabled flag, ignore count) |
2416 (condition, temporary flag, enabled flag, ignore count) |
2411 """ |
2417 """ |
2412 if not properties[2]: |
2418 if not properties[2]: |
2413 marker = self.dbreakpoint |
2419 marker = self.dbreakpoint |
2414 elif properties[0]: |
2420 elif properties[0]: |
2415 marker = properties[1] and self.tcbreakpoint or self.cbreakpoint |
2421 marker = properties[1] and self.tcbreakpoint or self.cbreakpoint |
2416 else: |
2422 else: |
2417 marker = properties[1] and self.tbreakpoint or self.breakpoint |
2423 marker = properties[1] and self.tbreakpoint or self.breakpoint |
2418 |
2424 |
2419 if self.markersAtLine(line - 1) & self.breakpointMask == 0: |
2425 if self.markersAtLine(line - 1) & self.breakpointMask == 0: |
2420 handle = self.markerAdd(line - 1, marker) |
2426 handle = self.markerAdd(line - 1, marker) |
2421 self.breaks[handle] = (line,) + properties |
2427 self.breaks[handle] = (line,) + properties |
2422 self.breakpointToggled.emit(self) |
2428 self.breakpointToggled.emit(self) |
2423 self.__markerMap.update() |
2429 self.__markerMap.update() |
2424 |
2430 |
2425 def __toggleBreakpoint(self, line, temporary=False): |
2431 def __toggleBreakpoint(self, line, temporary=False): |
2426 """ |
2432 """ |
2427 Private method to toggle a breakpoint. |
2433 Private method to toggle a breakpoint. |
2428 |
2434 |
2429 @param line line number of the breakpoint (integer) |
2435 @param line line number of the breakpoint (integer) |
2430 @param temporary flag indicating a temporary breakpoint (boolean) |
2436 @param temporary flag indicating a temporary breakpoint (boolean) |
2431 """ |
2437 """ |
2432 for handle in self.breaks: |
2438 for handle in self.breaks: |
2433 if self.markerLine(handle) == line - 1: |
2439 if self.markerLine(handle) == line - 1: |
2434 # delete breakpoint or toggle it to the next state |
2440 # delete breakpoint or toggle it to the next state |
2435 index = self.breakpointModel.getBreakPointIndex( |
2441 index = self.breakpointModel.getBreakPointIndex(self.fileName, line) |
2436 self.fileName, line) |
2442 if Preferences.getDebugger( |
2437 if ( |
2443 "ThreeStateBreakPoints" |
2438 Preferences.getDebugger("ThreeStateBreakPoints") and |
2444 ) and not self.breakpointModel.isBreakPointTemporaryByIndex(index): |
2439 not self.breakpointModel.isBreakPointTemporaryByIndex( |
|
2440 index) |
|
2441 ): |
|
2442 self.breakpointModel.deleteBreakPointByIndex(index) |
2445 self.breakpointModel.deleteBreakPointByIndex(index) |
2443 self.__addBreakPoint(line, True) |
2446 self.__addBreakPoint(line, True) |
2444 else: |
2447 else: |
2445 self.breakpointModel.deleteBreakPointByIndex(index) |
2448 self.breakpointModel.deleteBreakPointByIndex(index) |
2446 self.breakpointToggled.emit(self) |
2449 self.breakpointToggled.emit(self) |
2906 else: |
2910 else: |
2907 line -= 1 |
2911 line -= 1 |
2908 taskline = self.markerFindPrevious(line, 1 << self.taskmarker) |
2912 taskline = self.markerFindPrevious(line, 1 << self.taskmarker) |
2909 if taskline < 0: |
2913 if taskline < 0: |
2910 # wrap around |
2914 # wrap around |
2911 taskline = self.markerFindPrevious( |
2915 taskline = self.markerFindPrevious(self.lines() - 1, 1 << self.taskmarker) |
2912 self.lines() - 1, 1 << self.taskmarker) |
|
2913 if taskline >= 0: |
2916 if taskline >= 0: |
2914 self.setCursorPosition(taskline, 0) |
2917 self.setCursorPosition(taskline, 0) |
2915 self.ensureLineVisible(taskline) |
2918 self.ensureLineVisible(taskline) |
2916 |
2919 |
2917 def extractTasks(self): |
2920 def extractTasks(self): |
2918 """ |
2921 """ |
2919 Public slot to extract all tasks. |
2922 Public slot to extract all tasks. |
2920 """ |
2923 """ |
2921 from Tasks.Task import Task |
2924 from Tasks.Task import Task |
|
2925 |
2922 markers = { |
2926 markers = { |
2923 taskType: Preferences.getTasks(markersName).split() |
2927 taskType: Preferences.getTasks(markersName).split() |
2924 for taskType, markersName in Task.TaskType2MarkersName.items() |
2928 for taskType, markersName in Task.TaskType2MarkersName.items() |
2925 } |
2929 } |
2926 txtList = self.text().split(self.getLineSeparator()) |
2930 txtList = self.text().split(self.getLineSeparator()) |
2927 |
2931 |
2928 # clear all task markers and tasks |
2932 # clear all task markers and tasks |
2929 self.markerDeleteAll(self.taskmarker) |
2933 self.markerDeleteAll(self.taskmarker) |
2930 self.taskViewer.clearFileTasks(self.fileName) |
2934 self.taskViewer.clearFileTasks(self.fileName) |
2931 self.__hasTaskMarkers = False |
2935 self.__hasTaskMarkers = False |
2932 |
2936 |
2933 # now search tasks and record them |
2937 # now search tasks and record them |
2934 for lineIndex, line in enumerate(txtList): |
2938 for lineIndex, line in enumerate(txtList): |
2935 shouldBreak = False |
2939 shouldBreak = False |
2936 |
2940 |
2937 if line.endswith("__NO-TASK__"): |
2941 if line.endswith("__NO-TASK__"): |
2938 # ignore potential task marker |
2942 # ignore potential task marker |
2939 continue |
2943 continue |
2940 |
2944 |
2941 for taskType, taskMarkers in markers.items(): |
2945 for taskType, taskMarkers in markers.items(): |
2942 for taskMarker in taskMarkers: |
2946 for taskMarker in taskMarkers: |
2943 index = line.find(taskMarker) |
2947 index = line.find(taskMarker) |
2944 if index > -1: |
2948 if index > -1: |
2945 task = line[index:] |
2949 task = line[index:] |
2946 self.markerAdd(lineIndex, self.taskmarker) |
2950 self.markerAdd(lineIndex, self.taskmarker) |
2947 self.taskViewer.addFileTask( |
2951 self.taskViewer.addFileTask( |
2948 task, self.fileName, lineIndex + 1, taskType) |
2952 task, self.fileName, lineIndex + 1, taskType |
|
2953 ) |
2949 self.__hasTaskMarkers = True |
2954 self.__hasTaskMarkers = True |
2950 shouldBreak = True |
2955 shouldBreak = True |
2951 break |
2956 break |
2952 if shouldBreak: |
2957 if shouldBreak: |
2953 break |
2958 break |
2954 self.taskMarkersUpdated.emit(self) |
2959 self.taskMarkersUpdated.emit(self) |
2955 self.__markerMap.update() |
2960 self.__markerMap.update() |
2956 |
2961 |
2957 ########################################################################### |
2962 ########################################################################### |
2958 ## Change tracing methods below |
2963 ## Change tracing methods below |
2959 ########################################################################### |
2964 ########################################################################### |
2960 |
2965 |
2961 def __createChangeMarkerPixmap(self, key, size=16, width=4): |
2966 def __createChangeMarkerPixmap(self, key, size=16, width=4): |
2962 """ |
2967 """ |
2963 Private method to create a pixmap for the change markers. |
2968 Private method to create a pixmap for the change markers. |
2964 |
2969 |
2965 @param key key of the color to use (string) |
2970 @param key key of the color to use (string) |
2966 @param size size of the pixmap (integer) |
2971 @param size size of the pixmap (integer) |
2967 @param width width of the marker line (integer) |
2972 @param width width of the marker line (integer) |
2968 @return create pixmap (QPixmap) |
2973 @return create pixmap (QPixmap) |
2969 """ |
2974 """ |
2970 pixmap = QPixmap(size, size) |
2975 pixmap = QPixmap(size, size) |
2971 pixmap.fill(Qt.GlobalColor.transparent) |
2976 pixmap.fill(Qt.GlobalColor.transparent) |
2972 painter = QPainter(pixmap) |
2977 painter = QPainter(pixmap) |
2973 painter.fillRect(size - 4, 0, 4, size, |
2978 painter.fillRect(size - 4, 0, 4, size, Preferences.getEditorColour(key)) |
2974 Preferences.getEditorColour(key)) |
|
2975 painter.end() |
2979 painter.end() |
2976 return pixmap |
2980 return pixmap |
2977 |
2981 |
2978 def __initOnlineChangeTrace(self): |
2982 def __initOnlineChangeTrace(self): |
2979 """ |
2983 """ |
2980 Private slot to initialize the online change trace. |
2984 Private slot to initialize the online change trace. |
2981 """ |
2985 """ |
2982 self.__hasChangeMarkers = False |
2986 self.__hasChangeMarkers = False |
2983 self.__oldText = self.text() |
2987 self.__oldText = self.text() |
2984 self.__lastSavedText = self.text() |
2988 self.__lastSavedText = self.text() |
2985 self.__onlineChangeTraceTimer = QTimer(self) |
2989 self.__onlineChangeTraceTimer = QTimer(self) |
2986 self.__onlineChangeTraceTimer.setSingleShot(True) |
2990 self.__onlineChangeTraceTimer.setSingleShot(True) |
2987 self.__onlineChangeTraceTimer.setInterval( |
2991 self.__onlineChangeTraceTimer.setInterval( |
2988 Preferences.getEditor("OnlineChangeTraceInterval")) |
2992 Preferences.getEditor("OnlineChangeTraceInterval") |
|
2993 ) |
2989 self.__onlineChangeTraceTimer.timeout.connect( |
2994 self.__onlineChangeTraceTimer.timeout.connect( |
2990 self.__onlineChangeTraceTimerTimeout) |
2995 self.__onlineChangeTraceTimerTimeout |
|
2996 ) |
2991 self.textChanged.connect(self.__resetOnlineChangeTraceTimer) |
2997 self.textChanged.connect(self.__resetOnlineChangeTraceTimer) |
2992 |
2998 |
2993 def __reinitOnlineChangeTrace(self): |
2999 def __reinitOnlineChangeTrace(self): |
2994 """ |
3000 """ |
2995 Private slot to re-initialize the online change trace. |
3001 Private slot to re-initialize the online change trace. |
2996 """ |
3002 """ |
2997 self.__oldText = self.text() |
3003 self.__oldText = self.text() |
2998 self.__lastSavedText = self.text() |
3004 self.__lastSavedText = self.text() |
2999 self.__deleteAllChangeMarkers() |
3005 self.__deleteAllChangeMarkers() |
3000 |
3006 |
3001 def __resetOnlineChangeTraceTimer(self): |
3007 def __resetOnlineChangeTraceTimer(self): |
3002 """ |
3008 """ |
3003 Private method to reset the online syntax check timer. |
3009 Private method to reset the online syntax check timer. |
3004 """ |
3010 """ |
3005 if Preferences.getEditor("OnlineChangeTrace"): |
3011 if Preferences.getEditor("OnlineChangeTrace"): |
3006 self.__onlineChangeTraceTimer.stop() |
3012 self.__onlineChangeTraceTimer.stop() |
3007 self.__onlineChangeTraceTimer.start() |
3013 self.__onlineChangeTraceTimer.start() |
3008 |
3014 |
3009 def __onlineChangeTraceTimerTimeout(self): |
3015 def __onlineChangeTraceTimerTimeout(self): |
3010 """ |
3016 """ |
3011 Private slot to mark added and changed lines. |
3017 Private slot to mark added and changed lines. |
3012 """ |
3018 """ |
3013 self.__deleteAllChangeMarkers() |
3019 self.__deleteAllChangeMarkers() |
3014 |
3020 |
3015 # step 1: mark saved changes |
3021 # step 1: mark saved changes |
3016 oldL = self.__oldText.splitlines() |
3022 oldL = self.__oldText.splitlines() |
3017 newL = self.__lastSavedText.splitlines() |
3023 newL = self.__lastSavedText.splitlines() |
3018 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3024 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3019 |
3025 |
3020 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3026 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3021 if token in ["insert", "replace"]: |
3027 if token in ["insert", "replace"]: |
3022 for lineNo in range(j1, j2): |
3028 for lineNo in range(j1, j2): |
3023 self.markerAdd(lineNo, self.__changeMarkerSaved) |
3029 self.markerAdd(lineNo, self.__changeMarkerSaved) |
3024 self.__hasChangeMarkers = True |
3030 self.__hasChangeMarkers = True |
3025 |
3031 |
3026 # step 2: mark unsaved changes |
3032 # step 2: mark unsaved changes |
3027 oldL = self.__lastSavedText.splitlines() |
3033 oldL = self.__lastSavedText.splitlines() |
3028 newL = self.text().splitlines() |
3034 newL = self.text().splitlines() |
3029 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3035 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3030 |
3036 |
3031 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3037 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3032 if token in ["insert", "replace"]: |
3038 if token in ["insert", "replace"]: |
3033 for lineNo in range(j1, j2): |
3039 for lineNo in range(j1, j2): |
3034 self.markerAdd(lineNo, self.__changeMarkerUnsaved) |
3040 self.markerAdd(lineNo, self.__changeMarkerUnsaved) |
3035 self.__hasChangeMarkers = True |
3041 self.__hasChangeMarkers = True |
3036 |
3042 |
3037 if self.__hasChangeMarkers: |
3043 if self.__hasChangeMarkers: |
3038 self.changeMarkersUpdated.emit(self) |
3044 self.changeMarkersUpdated.emit(self) |
3039 self.__markerMap.update() |
3045 self.__markerMap.update() |
3040 |
3046 |
3041 def __resetOnlineChangeTraceInfo(self): |
3047 def __resetOnlineChangeTraceInfo(self): |
3042 """ |
3048 """ |
3043 Private slot to reset the online change trace info. |
3049 Private slot to reset the online change trace info. |
3044 """ |
3050 """ |
3045 self.__lastSavedText = self.text() |
3051 self.__lastSavedText = self.text() |
3046 self.__deleteAllChangeMarkers() |
3052 self.__deleteAllChangeMarkers() |
3047 |
3053 |
3048 # mark saved changes |
3054 # mark saved changes |
3049 oldL = self.__oldText.splitlines() |
3055 oldL = self.__oldText.splitlines() |
3050 newL = self.__lastSavedText.splitlines() |
3056 newL = self.__lastSavedText.splitlines() |
3051 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3057 matcher = difflib.SequenceMatcher(None, oldL, newL) |
3052 |
3058 |
3053 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3059 for token, _, _, j1, j2 in matcher.get_opcodes(): |
3054 if token in ["insert", "replace"]: |
3060 if token in ["insert", "replace"]: |
3055 for lineNo in range(j1, j2): |
3061 for lineNo in range(j1, j2): |
3056 self.markerAdd(lineNo, self.__changeMarkerSaved) |
3062 self.markerAdd(lineNo, self.__changeMarkerSaved) |
3057 self.__hasChangeMarkers = True |
3063 self.__hasChangeMarkers = True |
3058 |
3064 |
3059 if self.__hasChangeMarkers: |
3065 if self.__hasChangeMarkers: |
3060 self.changeMarkersUpdated.emit(self) |
3066 self.changeMarkersUpdated.emit(self) |
3061 self.__markerMap.update() |
3067 self.__markerMap.update() |
3062 |
3068 |
3063 def __deleteAllChangeMarkers(self): |
3069 def __deleteAllChangeMarkers(self): |
3064 """ |
3070 """ |
3065 Private slot to delete all change markers. |
3071 Private slot to delete all change markers. |
3066 """ |
3072 """ |
3067 self.markerDeleteAll(self.__changeMarkerUnsaved) |
3073 self.markerDeleteAll(self.__changeMarkerUnsaved) |
3068 self.markerDeleteAll(self.__changeMarkerSaved) |
3074 self.markerDeleteAll(self.__changeMarkerSaved) |
3069 self.__hasChangeMarkers = False |
3075 self.__hasChangeMarkers = False |
3070 self.changeMarkersUpdated.emit(self) |
3076 self.changeMarkersUpdated.emit(self) |
3071 self.__markerMap.update() |
3077 self.__markerMap.update() |
3072 |
3078 |
3073 def getChangeLines(self): |
3079 def getChangeLines(self): |
3074 """ |
3080 """ |
3075 Public method to get the lines containing a change. |
3081 Public method to get the lines containing a change. |
3076 |
3082 |
3077 @return list of lines containing a change (list of integer) |
3083 @return list of lines containing a change (list of integer) |
3078 """ |
3084 """ |
3079 lines = [] |
3085 lines = [] |
3080 line = -1 |
3086 line = -1 |
3081 while True: |
3087 while True: |
3204 if self.isRedoAvailable(): |
3211 if self.isRedoAvailable(): |
3205 self.redo() |
3212 self.redo() |
3206 else: |
3213 else: |
3207 break |
3214 break |
3208 # Couldn't find the unmodified state |
3215 # Couldn't find the unmodified state |
3209 |
3216 |
3210 def readFile(self, fn, createIt=False, encoding=""): |
3217 def readFile(self, fn, createIt=False, encoding=""): |
3211 """ |
3218 """ |
3212 Public slot to read the text from a file. |
3219 Public slot to read the text from a file. |
3213 |
3220 |
3214 @param fn filename to read from (string) |
3221 @param fn filename to read from (string) |
3215 @param createIt flag indicating the creation of a new file, if the |
3222 @param createIt flag indicating the creation of a new file, if the |
3216 given one doesn't exist (boolean) |
3223 given one doesn't exist (boolean) |
3217 @param encoding encoding to be used to read the file (string) |
3224 @param encoding encoding to be used to read the file (string) |
3218 (Note: this parameter overrides encoding detection) |
3225 (Note: this parameter overrides encoding detection) |
3219 """ |
3226 """ |
3220 self.__loadEditorConfig(fileName=fn) |
3227 self.__loadEditorConfig(fileName=fn) |
3221 |
3228 |
3222 try: |
3229 try: |
3223 with EricOverrideCursor(): |
3230 with EricOverrideCursor(): |
3224 if createIt and not os.path.exists(fn): |
3231 if createIt and not os.path.exists(fn): |
3225 with open(fn, "w"): |
3232 with open(fn, "w"): |
3226 pass |
3233 pass |
3227 if encoding == "": |
3234 if encoding == "": |
3228 encoding = self.__getEditorConfig("DefaultEncoding", |
3235 encoding = self.__getEditorConfig("DefaultEncoding", nodefault=True) |
3229 nodefault=True) |
|
3230 if encoding: |
3236 if encoding: |
3231 txt, self.encoding = Utilities.readEncodedFileWithEncoding( |
3237 txt, self.encoding = Utilities.readEncodedFileWithEncoding( |
3232 fn, encoding) |
3238 fn, encoding |
|
3239 ) |
3233 else: |
3240 else: |
3234 txt, self.encoding = Utilities.readEncodedFile(fn) |
3241 txt, self.encoding = Utilities.readEncodedFile(fn) |
3235 except (UnicodeDecodeError, OSError) as why: |
3242 except (UnicodeDecodeError, OSError) as why: |
3236 EricMessageBox.critical( |
3243 EricMessageBox.critical( |
3237 self.vm, |
3244 self.vm, |
3238 self.tr('Open File'), |
3245 self.tr("Open File"), |
3239 self.tr('<p>The file <b>{0}</b> could not be opened.</p>' |
3246 self.tr( |
3240 '<p>Reason: {1}</p>') |
3247 "<p>The file <b>{0}</b> could not be opened.</p>" |
3241 .format(fn, str(why))) |
3248 "<p>Reason: {1}</p>" |
|
3249 ).format(fn, str(why)), |
|
3250 ) |
3242 raise |
3251 raise |
3243 |
3252 |
3244 with EricOverrideCursor(): |
3253 with EricOverrideCursor(): |
3245 modified = False |
3254 modified = False |
3246 |
3255 |
3247 self.setText(txt) |
3256 self.setText(txt) |
3248 |
3257 |
3249 # get eric specific flags |
3258 # get eric specific flags |
3250 self.__processFlags() |
3259 self.__processFlags() |
3251 |
3260 |
3252 # perform automatic EOL conversion |
3261 # perform automatic EOL conversion |
3253 if ( |
3262 if self.__getEditorConfig( |
3254 self.__getEditorConfig("EOLMode", nodefault=True) or |
3263 "EOLMode", nodefault=True |
3255 Preferences.getEditor("AutomaticEOLConversion") |
3264 ) or Preferences.getEditor("AutomaticEOLConversion"): |
3256 ): |
|
3257 self.convertEols(self.eolMode()) |
3265 self.convertEols(self.eolMode()) |
3258 else: |
3266 else: |
3259 fileEol = self.detectEolString(txt) |
3267 fileEol = self.detectEolString(txt) |
3260 self.setEolModeByEolString(fileEol) |
3268 self.setEolModeByEolString(fileEol) |
3261 |
3269 |
3262 self.extractTasks() |
3270 self.extractTasks() |
3263 |
3271 |
3264 self.setModified(modified) |
3272 self.setModified(modified) |
3265 self.lastModified = pathlib.Path(fn).stat().st_mtime |
3273 self.lastModified = pathlib.Path(fn).stat().st_mtime |
3266 |
3274 |
3267 def __convertTabs(self): |
3275 def __convertTabs(self): |
3268 """ |
3276 """ |
3269 Private slot to convert tabulators to spaces. |
3277 Private slot to convert tabulators to spaces. |
3270 """ |
3278 """ |
3271 if ( |
3279 if ( |
3272 (not self.__getEditorConfig("TabForIndentation")) and |
3280 (not self.__getEditorConfig("TabForIndentation")) |
3273 Preferences.getEditor("ConvertTabsOnLoad") and |
3281 and Preferences.getEditor("ConvertTabsOnLoad") |
3274 not (self.lexer_ and |
3282 and not (self.lexer_ and self.lexer_.alwaysKeepTabs()) |
3275 self.lexer_.alwaysKeepTabs()) |
|
3276 ): |
3283 ): |
3277 txt = self.text() |
3284 txt = self.text() |
3278 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth")) |
3285 txtExpanded = txt.expandtabs(self.__getEditorConfig("TabWidth")) |
3279 if txtExpanded != txt: |
3286 if txtExpanded != txt: |
3280 self.beginUndoAction() |
3287 self.beginUndoAction() |
3281 self.setText(txt) |
3288 self.setText(txt) |
3282 self.endUndoAction() |
3289 self.endUndoAction() |
3283 |
3290 |
3284 self.setModified(True) |
3291 self.setModified(True) |
3285 |
3292 |
3286 def __removeTrailingWhitespace(self): |
3293 def __removeTrailingWhitespace(self): |
3287 """ |
3294 """ |
3288 Private method to remove trailing whitespace. |
3295 Private method to remove trailing whitespace. |
3289 """ |
3296 """ |
3290 searchRE = r"[ \t]+$" # whitespace at the end of a line |
3297 searchRE = r"[ \t]+$" # whitespace at the end of a line |
3291 |
3298 |
3292 ok = self.findFirstTarget(searchRE, True, False, False, 0, 0) |
3299 ok = self.findFirstTarget(searchRE, True, False, False, 0, 0) |
3293 self.beginUndoAction() |
3300 self.beginUndoAction() |
3294 while ok: |
3301 while ok: |
3295 self.replaceTarget("") |
3302 self.replaceTarget("") |
3296 ok = self.findNextTarget() |
3303 ok = self.findNextTarget() |
3297 self.endUndoAction() |
3304 self.endUndoAction() |
3298 |
3305 |
3299 def writeFile(self, fn, backup=True): |
3306 def writeFile(self, fn, backup=True): |
3300 """ |
3307 """ |
3301 Public slot to write the text to a file. |
3308 Public slot to write the text to a file. |
3302 |
3309 |
3303 @param fn filename to write to (string) |
3310 @param fn filename to write to (string) |
3304 @param backup flag indicating to save a backup (boolean) |
3311 @param backup flag indicating to save a backup (boolean) |
3305 @return flag indicating success (boolean) |
3312 @return flag indicating success (boolean) |
3306 """ |
3313 """ |
3307 config = self.__loadEditorConfigObject(fn) |
3314 config = self.__loadEditorConfigObject(fn) |
3308 |
3315 |
3309 eol = self.__getEditorConfig("EOLMode", nodefault=True, config=config) |
3316 eol = self.__getEditorConfig("EOLMode", nodefault=True, config=config) |
3310 if eol is not None: |
3317 if eol is not None: |
3311 self.convertEols(eol) |
3318 self.convertEols(eol) |
3312 |
3319 |
3313 if self.__getEditorConfig("StripTrailingWhitespace", config=config): |
3320 if self.__getEditorConfig("StripTrailingWhitespace", config=config): |
3314 self.__removeTrailingWhitespace() |
3321 self.__removeTrailingWhitespace() |
3315 |
3322 |
3316 txt = self.text() |
3323 txt = self.text() |
3317 |
3324 |
3318 if self.__getEditorConfig("InsertFinalNewline", config=config): |
3325 if self.__getEditorConfig("InsertFinalNewline", config=config): |
3319 eol = self.getLineSeparator() |
3326 eol = self.getLineSeparator() |
3320 if eol: |
3327 if eol: |
3321 if len(txt) >= len(eol): |
3328 if len(txt) >= len(eol): |
3322 if txt[-len(eol):] != eol: |
3329 if txt[-len(eol) :] != eol: |
3323 txt += eol |
3330 txt += eol |
3324 else: |
3331 else: |
3325 txt += eol |
3332 txt += eol |
3326 |
3333 |
3327 # create a backup file, if the option is set |
3334 # create a backup file, if the option is set |
3328 createBackup = backup and Preferences.getEditor("CreateBackupFile") |
3335 createBackup = backup and Preferences.getEditor("CreateBackupFile") |
3329 if createBackup: |
3336 if createBackup: |
3330 if os.path.islink(fn): |
3337 if os.path.islink(fn): |
3331 fn = os.path.realpath(fn) |
3338 fn = os.path.realpath(fn) |
3332 bfn = '{0}~'.format(fn) |
3339 bfn = "{0}~".format(fn) |
3333 try: |
3340 try: |
3334 permissions = os.stat(fn).st_mode |
3341 permissions = os.stat(fn).st_mode |
3335 perms_valid = True |
3342 perms_valid = True |
3336 except OSError: |
3343 except OSError: |
3337 # if there was an error, ignore it |
3344 # if there was an error, ignore it |
3338 perms_valid = False |
3345 perms_valid = False |
3339 with contextlib.suppress(OSError): |
3346 with contextlib.suppress(OSError): |
3340 os.remove(bfn) |
3347 os.remove(bfn) |
3341 with contextlib.suppress(OSError): |
3348 with contextlib.suppress(OSError): |
3342 os.rename(fn, bfn) |
3349 os.rename(fn, bfn) |
3343 |
3350 |
3344 # now write text to the file fn |
3351 # now write text to the file fn |
3345 try: |
3352 try: |
3346 editorConfigEncoding = self.__getEditorConfig( |
3353 editorConfigEncoding = self.__getEditorConfig( |
3347 "DefaultEncoding", nodefault=True, config=config) |
3354 "DefaultEncoding", nodefault=True, config=config |
|
3355 ) |
3348 self.encoding = Utilities.writeEncodedFile( |
3356 self.encoding = Utilities.writeEncodedFile( |
3349 fn, txt, self.encoding, forcedEncoding=editorConfigEncoding) |
3357 fn, txt, self.encoding, forcedEncoding=editorConfigEncoding |
|
3358 ) |
3350 if createBackup and perms_valid: |
3359 if createBackup and perms_valid: |
3351 os.chmod(fn, permissions) |
3360 os.chmod(fn, permissions) |
3352 return True |
3361 return True |
3353 except (OSError, Utilities.CodingError, UnicodeError) as why: |
3362 except (OSError, Utilities.CodingError, UnicodeError) as why: |
3354 EricMessageBox.critical( |
3363 EricMessageBox.critical( |
3355 self, |
3364 self, |
3356 self.tr('Save File'), |
3365 self.tr("Save File"), |
3357 self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' |
3366 self.tr( |
3358 'Reason: {1}</p>') |
3367 "<p>The file <b>{0}</b> could not be saved.<br/>" "Reason: {1}</p>" |
3359 .format(fn, str(why))) |
3368 ).format(fn, str(why)), |
|
3369 ) |
3360 return False |
3370 return False |
3361 |
3371 |
3362 def __getSaveFileName(self, path=None): |
3372 def __getSaveFileName(self, path=None): |
3363 """ |
3373 """ |
3364 Private method to get the name of the file to be saved. |
3374 Private method to get the name of the file to be saved. |
3365 |
3375 |
3366 @param path directory to save the file in (string) |
3376 @param path directory to save the file in (string) |
3367 @return file name (string) |
3377 @return file name (string) |
3368 """ |
3378 """ |
3369 # save to project, if a project is loaded |
3379 # save to project, if a project is loaded |
3370 if self.project.isOpen(): |
3380 if self.project.isOpen(): |
3371 if ( |
3381 if self.fileName and self.project.startswithProjectPath(self.fileName): |
3372 self.fileName and |
|
3373 self.project.startswithProjectPath(self.fileName) |
|
3374 ): |
|
3375 path = os.path.dirname(self.fileName) |
3382 path = os.path.dirname(self.fileName) |
3376 elif not self.fileName: |
3383 elif not self.fileName: |
3377 path = self.project.getProjectPath() |
3384 path = self.project.getProjectPath() |
3378 |
3385 |
3379 if not path and self.fileName: |
3386 if not path and self.fileName: |
3380 path = os.path.dirname(self.fileName) |
3387 path = os.path.dirname(self.fileName) |
3381 if not path: |
3388 if not path: |
3382 path = ( |
3389 path = Preferences.getMultiProject("Workspace") or Utilities.getHomeDir() |
3383 Preferences.getMultiProject("Workspace") or |
3390 |
3384 Utilities.getHomeDir() |
|
3385 ) |
|
3386 |
|
3387 from . import Lexers |
3391 from . import Lexers |
|
3392 |
3388 if self.fileName: |
3393 if self.fileName: |
3389 filterPattern = "(*{0})".format( |
3394 filterPattern = "(*{0})".format(os.path.splitext(self.fileName)[1]) |
3390 os.path.splitext(self.fileName)[1]) |
|
3391 for fileFilter in Lexers.getSaveFileFiltersList(True): |
3395 for fileFilter in Lexers.getSaveFileFiltersList(True): |
3392 if filterPattern in fileFilter: |
3396 if filterPattern in fileFilter: |
3393 defaultFilter = fileFilter |
3397 defaultFilter = fileFilter |
3394 break |
3398 break |
3395 else: |
3399 else: |
3696 start = index |
3696 start = index |
3697 if end > start: |
3697 if end > start: |
3698 text = self.text(line) |
3698 text = self.text(line) |
3699 word = text[start:end] |
3699 word = text[start:end] |
3700 else: |
3700 else: |
3701 word = '' |
3701 word = "" |
3702 return word |
3702 return word |
3703 |
3703 |
3704 def getWordLeft(self, line, index): |
3704 def getWordLeft(self, line, index): |
3705 """ |
3705 """ |
3706 Public method to get the word to the left of a position. |
3706 Public method to get the word to the left of a position. |
3707 |
3707 |
3708 @param line number of line to look at (int) |
3708 @param line number of line to look at (int) |
3709 @param index position to look at (int) |
3709 @param index position to look at (int) |
3710 @return the word to the left of that position (string) |
3710 @return the word to the left of that position (string) |
3711 """ |
3711 """ |
3712 return self.getWord(line, index, 1) |
3712 return self.getWord(line, index, 1) |
3713 |
3713 |
3714 def getWordRight(self, line, index): |
3714 def getWordRight(self, line, index): |
3715 """ |
3715 """ |
3716 Public method to get the word to the right of a position. |
3716 Public method to get the word to the right of a position. |
3717 |
3717 |
3718 @param line number of line to look at (int) |
3718 @param line number of line to look at (int) |
3719 @param index position to look at (int) |
3719 @param index position to look at (int) |
3720 @return the word to the right of that position (string) |
3720 @return the word to the right of that position (string) |
3721 """ |
3721 """ |
3722 return self.getWord(line, index, 2) |
3722 return self.getWord(line, index, 2) |
3723 |
3723 |
3724 def getCurrentWord(self): |
3724 def getCurrentWord(self): |
3725 """ |
3725 """ |
3726 Public method to get the word at the current position. |
3726 Public method to get the word at the current position. |
3727 |
3727 |
3728 @return the word at that current position (string) |
3728 @return the word at that current position (string) |
3729 """ |
3729 """ |
3730 line, index = self.getCursorPosition() |
3730 line, index = self.getCursorPosition() |
3731 return self.getWord(line, index) |
3731 return self.getWord(line, index) |
3732 |
3732 |
3733 def getCurrentWordBoundaries(self): |
3733 def getCurrentWordBoundaries(self): |
3734 """ |
3734 """ |
3735 Public method to get the word boundaries at the current position. |
3735 Public method to get the word boundaries at the current position. |
3736 |
3736 |
3737 @return tuple with start and end indexes of the current word |
3737 @return tuple with start and end indexes of the current word |
3738 (integer, integer) |
3738 (integer, integer) |
3739 """ |
3739 """ |
3740 line, index = self.getCursorPosition() |
3740 line, index = self.getCursorPosition() |
3741 return self.getWordBoundaries(line, index) |
3741 return self.getWordBoundaries(line, index) |
3742 |
3742 |
3743 def selectWord(self, line, index): |
3743 def selectWord(self, line, index): |
3744 """ |
3744 """ |
3745 Public method to select the word at a position. |
3745 Public method to select the word at a position. |
3746 |
3746 |
3747 @param line number of line to look at (int) |
3747 @param line number of line to look at (int) |
3748 @param index position to look at (int) |
3748 @param index position to look at (int) |
3749 """ |
3749 """ |
3750 start, end = self.getWordBoundaries(line, index) |
3750 start, end = self.getWordBoundaries(line, index) |
3751 self.setSelection(line, start, line, end) |
3751 self.setSelection(line, start, line, end) |
3752 |
3752 |
3753 def selectCurrentWord(self): |
3753 def selectCurrentWord(self): |
3754 """ |
3754 """ |
3755 Public method to select the current word. |
3755 Public method to select the current word. |
3756 """ |
3756 """ |
3757 line, index = self.getCursorPosition() |
3757 line, index = self.getCursorPosition() |
3758 self.selectWord(line, index) |
3758 self.selectWord(line, index) |
3759 |
3759 |
3760 def __getCharacter(self, pos): |
3760 def __getCharacter(self, pos): |
3761 """ |
3761 """ |
3762 Private method to get the character to the left of the current position |
3762 Private method to get the character to the left of the current position |
3763 in the current line. |
3763 in the current line. |
3764 |
3764 |
3765 @param pos position to get character at (integer) |
3765 @param pos position to get character at (integer) |
3766 @return requested character or "", if there are no more (string) and |
3766 @return requested character or "", if there are no more (string) and |
3767 the next position (i.e. pos - 1) |
3767 the next position (i.e. pos - 1) |
3768 """ |
3768 """ |
3769 if pos <= 0: |
3769 if pos <= 0: |
3770 return "", pos |
3770 return "", pos |
3771 |
3771 |
3772 pos = self.positionBefore(pos) |
3772 pos = self.positionBefore(pos) |
3773 ch = self.charAt(pos) |
3773 ch = self.charAt(pos) |
3774 |
3774 |
3775 # Don't go past the end of the previous line |
3775 # Don't go past the end of the previous line |
3776 if ch in ('\n', '\r'): |
3776 if ch in ("\n", "\r"): |
3777 return "", pos |
3777 return "", pos |
3778 |
3778 |
3779 return ch, pos |
3779 return ch, pos |
3780 |
3780 |
3781 def getSearchText(self, selectionOnly=False): |
3781 def getSearchText(self, selectionOnly=False): |
3782 """ |
3782 """ |
3783 Public method to determine the selection or the current word for the |
3783 Public method to determine the selection or the current word for the |
3784 next search operation. |
3784 next search operation. |
3785 |
3785 |
3786 @param selectionOnly flag indicating that only selected text should be |
3786 @param selectionOnly flag indicating that only selected text should be |
3787 returned (boolean) |
3787 returned (boolean) |
3788 @return selection or current word (string) |
3788 @return selection or current word (string) |
3789 """ |
3789 """ |
3790 if self.hasSelectedText(): |
3790 if self.hasSelectedText(): |
3791 text = self.selectedText() |
3791 text = self.selectedText() |
3792 if '\r' in text or '\n' in text: |
3792 if "\r" in text or "\n" in text: |
3793 # the selection contains at least a newline, it is |
3793 # the selection contains at least a newline, it is |
3794 # unlikely to be the expression to search for |
3794 # unlikely to be the expression to search for |
3795 return '' |
3795 return "" |
3796 |
3796 |
3797 return text |
3797 return text |
3798 |
3798 |
3799 if not selectionOnly: |
3799 if not selectionOnly: |
3800 # no selected text, determine the word at the current position |
3800 # no selected text, determine the word at the current position |
3801 return self.getCurrentWord() |
3801 return self.getCurrentWord() |
3802 |
3802 |
3803 return '' |
3803 return "" |
3804 |
3804 |
3805 def setSearchIndicator(self, startPos, indicLength): |
3805 def setSearchIndicator(self, startPos, indicLength): |
3806 """ |
3806 """ |
3807 Public method to set a search indicator for the given range. |
3807 Public method to set a search indicator for the given range. |
3808 |
3808 |
3809 @param startPos start position of the indicator (integer) |
3809 @param startPos start position of the indicator (integer) |
3810 @param indicLength length of the indicator (integer) |
3810 @param indicLength length of the indicator (integer) |
3811 """ |
3811 """ |
3812 self.setIndicatorRange(self.searchIndicator, startPos, indicLength) |
3812 self.setIndicatorRange(self.searchIndicator, startPos, indicLength) |
3813 line = self.lineIndexFromPosition(startPos)[0] |
3813 line = self.lineIndexFromPosition(startPos)[0] |
3814 if line not in self.__searchIndicatorLines: |
3814 if line not in self.__searchIndicatorLines: |
3815 self.__searchIndicatorLines.append(line) |
3815 self.__searchIndicatorLines.append(line) |
3816 |
3816 |
3817 def clearSearchIndicators(self): |
3817 def clearSearchIndicators(self): |
3818 """ |
3818 """ |
3819 Public method to clear all search indicators. |
3819 Public method to clear all search indicators. |
3820 """ |
3820 """ |
3821 self.clearAllIndicators(self.searchIndicator) |
3821 self.clearAllIndicators(self.searchIndicator) |
3822 self.__markedText = "" |
3822 self.__markedText = "" |
3823 self.__searchIndicatorLines = [] |
3823 self.__searchIndicatorLines = [] |
3824 self.__markerMap.update() |
3824 self.__markerMap.update() |
3825 |
3825 |
3826 def __markOccurrences(self): |
3826 def __markOccurrences(self): |
3827 """ |
3827 """ |
3828 Private method to mark all occurrences of the current word. |
3828 Private method to mark all occurrences of the current word. |
3829 """ |
3829 """ |
3830 word = self.getCurrentWord() |
3830 word = self.getCurrentWord() |
3831 if not word: |
3831 if not word: |
3832 self.clearSearchIndicators() |
3832 self.clearSearchIndicators() |
3833 return |
3833 return |
3834 |
3834 |
3835 if self.__markedText == word: |
3835 if self.__markedText == word: |
3836 return |
3836 return |
3837 |
3837 |
3838 self.clearSearchIndicators() |
3838 self.clearSearchIndicators() |
3839 ok = self.findFirstTarget(word, False, self.caseSensitive(), True, |
3839 ok = self.findFirstTarget(word, False, self.caseSensitive(), True, 0, 0) |
3840 0, 0) |
|
3841 while ok: |
3840 while ok: |
3842 tgtPos, tgtLen = self.getFoundTarget() |
3841 tgtPos, tgtLen = self.getFoundTarget() |
3843 self.setSearchIndicator(tgtPos, tgtLen) |
3842 self.setSearchIndicator(tgtPos, tgtLen) |
3844 ok = self.findNextTarget() |
3843 ok = self.findNextTarget() |
3845 self.__markedText = word |
3844 self.__markedText = word |
3846 self.__markerMap.update() |
3845 self.__markerMap.update() |
3847 |
3846 |
3848 def getSearchIndicatorLines(self): |
3847 def getSearchIndicatorLines(self): |
3849 """ |
3848 """ |
3850 Public method to get the lines containing a search indicator. |
3849 Public method to get the lines containing a search indicator. |
3851 |
3850 |
3852 @return list of lines containing a search indicator (list of integer) |
3851 @return list of lines containing a search indicator (list of integer) |
3853 """ |
3852 """ |
3854 return self.__searchIndicatorLines[:] |
3853 return self.__searchIndicatorLines[:] |
3855 |
3854 |
3856 def updateMarkerMap(self): |
3855 def updateMarkerMap(self): |
3857 """ |
3856 """ |
3858 Public method to initiate an update of the marker map. |
3857 Public method to initiate an update of the marker map. |
3859 """ |
3858 """ |
3860 self.__markerMap.update() |
3859 self.__markerMap.update() |
3861 |
3860 |
3862 ########################################################################### |
3861 ########################################################################### |
3863 ## Highlighting marker handling methods below |
3862 ## Highlighting marker handling methods below |
3864 ########################################################################### |
3863 ########################################################################### |
3865 |
3864 |
3866 def setHighlight(self, startLine, startIndex, endLine, endIndex): |
3865 def setHighlight(self, startLine, startIndex, endLine, endIndex): |
3867 """ |
3866 """ |
3868 Public method to set a text highlight. |
3867 Public method to set a text highlight. |
3869 |
3868 |
3870 @param startLine line of the highlight start |
3869 @param startLine line of the highlight start |
3871 @type int |
3870 @type int |
3872 @param startIndex index of the highlight start |
3871 @param startIndex index of the highlight start |
3873 @type int |
3872 @type int |
3874 @param endLine line of the highlight end |
3873 @param endLine line of the highlight end |
3875 @type int |
3874 @type int |
3876 @param endIndex index of the highlight end |
3875 @param endIndex index of the highlight end |
3877 @type int |
3876 @type int |
3878 """ |
3877 """ |
3879 self.setIndicator(self.highlightIndicator, startLine, startIndex, |
3878 self.setIndicator( |
3880 endLine, endIndex) |
3879 self.highlightIndicator, startLine, startIndex, endLine, endIndex |
3881 |
3880 ) |
|
3881 |
3882 def clearAllHighlights(self): |
3882 def clearAllHighlights(self): |
3883 """ |
3883 """ |
3884 Public method to clear all highlights. |
3884 Public method to clear all highlights. |
3885 """ |
3885 """ |
3886 self.clearAllIndicators(self.highlightIndicator) |
3886 self.clearAllIndicators(self.highlightIndicator) |
3887 |
3887 |
3888 def clearHighlight(self, startLine, startIndex, endLine, endIndex): |
3888 def clearHighlight(self, startLine, startIndex, endLine, endIndex): |
3889 """ |
3889 """ |
3890 Public method to clear a text highlight. |
3890 Public method to clear a text highlight. |
3891 |
3891 |
3892 @param startLine line of the highlight start |
3892 @param startLine line of the highlight start |
3893 @type int |
3893 @type int |
3894 @param startIndex index of the highlight start |
3894 @param startIndex index of the highlight start |
3895 @type int |
3895 @type int |
3896 @param endLine line of the highlight end |
3896 @param endLine line of the highlight end |
3897 @type int |
3897 @type int |
3898 @param endIndex index of the highlight end |
3898 @param endIndex index of the highlight end |
3899 @type int |
3899 @type int |
3900 """ |
3900 """ |
3901 self.clearIndicator(self.highlightIndicator, startLine, startIndex, |
3901 self.clearIndicator( |
3902 endLine, endIndex) |
3902 self.highlightIndicator, startLine, startIndex, endLine, endIndex |
3903 |
3903 ) |
|
3904 |
3904 ########################################################################### |
3905 ########################################################################### |
3905 ## Comment handling methods below |
3906 ## Comment handling methods below |
3906 ########################################################################### |
3907 ########################################################################### |
3907 |
3908 |
3908 def __isCommentedLine(self, line, commentStr): |
3909 def __isCommentedLine(self, line, commentStr): |
3909 """ |
3910 """ |
3910 Private method to check, if the given line is a comment line as |
3911 Private method to check, if the given line is a comment line as |
3911 produced by the configured comment rules. |
3912 produced by the configured comment rules. |
3912 |
3913 |
3913 @param line text of the line to check (string) |
3914 @param line text of the line to check (string) |
3914 @param commentStr comment string to check against (string) |
3915 @param commentStr comment string to check against (string) |
3915 @return flag indicating a commented line (boolean) |
3916 @return flag indicating a commented line (boolean) |
3916 """ |
3917 """ |
3917 if Preferences.getEditor("CommentColumn0"): |
3918 if Preferences.getEditor("CommentColumn0"): |
3918 return line.startswith(commentStr) |
3919 return line.startswith(commentStr) |
3919 else: |
3920 else: |
3920 return line.strip().startswith(commentStr) |
3921 return line.strip().startswith(commentStr) |
3921 |
3922 |
3922 def toggleCommentBlock(self): |
3923 def toggleCommentBlock(self): |
3923 """ |
3924 """ |
3924 Public slot to toggle the comment of a block. |
3925 Public slot to toggle the comment of a block. |
3925 |
3926 |
3926 If the line of the cursor or the selection is not commented, it will |
3927 If the line of the cursor or the selection is not commented, it will |
3927 be commented. If it is commented, the comment block will be removed. |
3928 be commented. If it is commented, the comment block will be removed. |
3928 The later works independent of the current selection. |
3929 The later works independent of the current selection. |
3929 """ |
3930 """ |
3930 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3931 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3931 return |
3932 return |
3932 |
3933 |
3933 commentStr = self.lexer_.commentStr() |
3934 commentStr = self.lexer_.commentStr() |
3934 line, index = self.getCursorPosition() |
3935 line, index = self.getCursorPosition() |
3935 |
3936 |
3936 # check if line starts with our comment string (i.e. was commented |
3937 # check if line starts with our comment string (i.e. was commented |
3937 # by our comment...() slots |
3938 # by our comment...() slots |
3938 if ( |
3939 if self.hasSelectedText() and self.__isCommentedLine( |
3939 self.hasSelectedText() and |
3940 self.text(self.getSelection()[0]), commentStr |
3940 self.__isCommentedLine(self.text(self.getSelection()[0]), |
|
3941 commentStr) |
|
3942 ): |
3941 ): |
3943 self.uncommentLineOrSelection() |
3942 self.uncommentLineOrSelection() |
3944 elif not self.__isCommentedLine(self.text(line), commentStr): |
3943 elif not self.__isCommentedLine(self.text(line), commentStr): |
3945 # it doesn't, so comment the line or selection |
3944 # it doesn't, so comment the line or selection |
3946 self.commentLineOrSelection() |
3945 self.commentLineOrSelection() |
3947 else: |
3946 else: |
3948 # determine the start of the comment block |
3947 # determine the start of the comment block |
3949 begline = line |
3948 begline = line |
3950 while ( |
3949 while begline > 0 and self.__isCommentedLine( |
3951 begline > 0 and |
3950 self.text(begline - 1), commentStr |
3952 self.__isCommentedLine(self.text(begline - 1), commentStr) |
|
3953 ): |
3951 ): |
3954 begline -= 1 |
3952 begline -= 1 |
3955 # determine the end of the comment block |
3953 # determine the end of the comment block |
3956 endline = line |
3954 endline = line |
3957 lines = self.lines() |
3955 lines = self.lines() |
3958 while ( |
3956 while endline < lines and self.__isCommentedLine( |
3959 endline < lines and |
3957 self.text(endline + 1), commentStr |
3960 self.__isCommentedLine(self.text(endline + 1), commentStr) |
|
3961 ): |
3958 ): |
3962 endline += 1 |
3959 endline += 1 |
3963 |
3960 |
3964 self.setSelection(begline, 0, endline, self.lineLength(endline)) |
3961 self.setSelection(begline, 0, endline, self.lineLength(endline)) |
3965 self.uncommentLineOrSelection() |
3962 self.uncommentLineOrSelection() |
3966 |
3963 |
3967 # reset the cursor |
3964 # reset the cursor |
3968 self.setCursorPosition(line, index - len(commentStr)) |
3965 self.setCursorPosition(line, index - len(commentStr)) |
3969 |
3966 |
3970 def commentLine(self): |
3967 def commentLine(self): |
3971 """ |
3968 """ |
3972 Public slot to comment the current line. |
3969 Public slot to comment the current line. |
3973 """ |
3970 """ |
3974 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3971 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3975 return |
3972 return |
3976 |
3973 |
3977 line, index = self.getCursorPosition() |
3974 line, index = self.getCursorPosition() |
3978 self.beginUndoAction() |
3975 self.beginUndoAction() |
3979 if Preferences.getEditor("CommentColumn0"): |
3976 if Preferences.getEditor("CommentColumn0"): |
3980 self.insertAt(self.lexer_.commentStr(), line, 0) |
3977 self.insertAt(self.lexer_.commentStr(), line, 0) |
3981 else: |
3978 else: |
3982 lineText = self.text(line) |
3979 lineText = self.text(line) |
3983 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
3980 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
3984 self.insertAt(self.lexer_.commentStr(), line, pos) |
3981 self.insertAt(self.lexer_.commentStr(), line, pos) |
3985 self.endUndoAction() |
3982 self.endUndoAction() |
3986 |
3983 |
3987 def uncommentLine(self): |
3984 def uncommentLine(self): |
3988 """ |
3985 """ |
3989 Public slot to uncomment the current line. |
3986 Public slot to uncomment the current line. |
3990 """ |
3987 """ |
3991 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3988 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
3992 return |
3989 return |
3993 |
3990 |
3994 commentStr = self.lexer_.commentStr() |
3991 commentStr = self.lexer_.commentStr() |
3995 line, index = self.getCursorPosition() |
3992 line, index = self.getCursorPosition() |
3996 |
3993 |
3997 # check if line starts with our comment string (i.e. was commented |
3994 # check if line starts with our comment string (i.e. was commented |
3998 # by our comment...() slots |
3995 # by our comment...() slots |
3999 if not self.__isCommentedLine(self.text(line), commentStr): |
3996 if not self.__isCommentedLine(self.text(line), commentStr): |
4000 return |
3997 return |
4001 |
3998 |
4002 # now remove the comment string |
3999 # now remove the comment string |
4003 self.beginUndoAction() |
4000 self.beginUndoAction() |
4004 if Preferences.getEditor("CommentColumn0"): |
4001 if Preferences.getEditor("CommentColumn0"): |
4005 self.setSelection(line, 0, line, len(commentStr)) |
4002 self.setSelection(line, 0, line, len(commentStr)) |
4006 else: |
4003 else: |
4007 lineText = self.text(line) |
4004 lineText = self.text(line) |
4008 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4005 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4009 self.setSelection(line, pos, line, pos + len(commentStr)) |
4006 self.setSelection(line, pos, line, pos + len(commentStr)) |
4010 self.removeSelectedText() |
4007 self.removeSelectedText() |
4011 self.endUndoAction() |
4008 self.endUndoAction() |
4012 |
4009 |
4013 def commentSelection(self): |
4010 def commentSelection(self): |
4014 """ |
4011 """ |
4015 Public slot to comment the current selection. |
4012 Public slot to comment the current selection. |
4016 """ |
4013 """ |
4017 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
4014 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
4018 return |
4015 return |
4019 |
4016 |
4020 if not self.hasSelectedText(): |
4017 if not self.hasSelectedText(): |
4021 return |
4018 return |
4022 |
4019 |
4023 commentStr = self.lexer_.commentStr() |
4020 commentStr = self.lexer_.commentStr() |
4024 |
4021 |
4025 # get the selection boundaries |
4022 # get the selection boundaries |
4026 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4023 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4027 endLine = lineTo if indexTo else lineTo - 1 |
4024 endLine = lineTo if indexTo else lineTo - 1 |
4028 |
4025 |
4029 self.beginUndoAction() |
4026 self.beginUndoAction() |
4030 # iterate over the lines |
4027 # iterate over the lines |
4031 for line in range(lineFrom, endLine + 1): |
4028 for line in range(lineFrom, endLine + 1): |
4032 if Preferences.getEditor("CommentColumn0"): |
4029 if Preferences.getEditor("CommentColumn0"): |
4033 self.insertAt(commentStr, line, 0) |
4030 self.insertAt(commentStr, line, 0) |
4034 else: |
4031 else: |
4035 lineText = self.text(line) |
4032 lineText = self.text(line) |
4036 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4033 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4037 self.insertAt(commentStr, line, pos) |
4034 self.insertAt(commentStr, line, pos) |
4038 |
4035 |
4039 # change the selection accordingly |
4036 # change the selection accordingly |
4040 self.setSelection(lineFrom, 0, endLine + 1, 0) |
4037 self.setSelection(lineFrom, 0, endLine + 1, 0) |
4041 self.endUndoAction() |
4038 self.endUndoAction() |
4042 |
4039 |
4043 def uncommentSelection(self): |
4040 def uncommentSelection(self): |
4044 """ |
4041 """ |
4045 Public slot to uncomment the current selection. |
4042 Public slot to uncomment the current selection. |
4046 """ |
4043 """ |
4047 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
4044 if self.lexer_ is None or not self.lexer_.canBlockComment(): |
4048 return |
4045 return |
4049 |
4046 |
4050 if not self.hasSelectedText(): |
4047 if not self.hasSelectedText(): |
4051 return |
4048 return |
4052 |
4049 |
4053 commentStr = self.lexer_.commentStr() |
4050 commentStr = self.lexer_.commentStr() |
4054 |
4051 |
4055 # get the selection boundaries |
4052 # get the selection boundaries |
4056 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4053 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4057 endLine = lineTo if indexTo else lineTo - 1 |
4054 endLine = lineTo if indexTo else lineTo - 1 |
4058 |
4055 |
4059 self.beginUndoAction() |
4056 self.beginUndoAction() |
4060 # iterate over the lines |
4057 # iterate over the lines |
4061 for line in range(lineFrom, endLine + 1): |
4058 for line in range(lineFrom, endLine + 1): |
4062 # check if line starts with our comment string (i.e. was commented |
4059 # check if line starts with our comment string (i.e. was commented |
4063 # by our comment...() slots |
4060 # by our comment...() slots |
4064 if not self.__isCommentedLine(self.text(line), commentStr): |
4061 if not self.__isCommentedLine(self.text(line), commentStr): |
4065 continue |
4062 continue |
4066 |
4063 |
4067 if Preferences.getEditor("CommentColumn0"): |
4064 if Preferences.getEditor("CommentColumn0"): |
4068 self.setSelection(line, 0, line, len(commentStr)) |
4065 self.setSelection(line, 0, line, len(commentStr)) |
4069 else: |
4066 else: |
4070 lineText = self.text(line) |
4067 lineText = self.text(line) |
4071 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4068 pos = len(lineText.replace(lineText.lstrip(" \t"), "")) |
4072 self.setSelection(line, pos, line, pos + len(commentStr)) |
4069 self.setSelection(line, pos, line, pos + len(commentStr)) |
4073 self.removeSelectedText() |
4070 self.removeSelectedText() |
4074 |
4071 |
4075 # adjust selection start |
4072 # adjust selection start |
4076 if line == lineFrom: |
4073 if line == lineFrom: |
4077 indexFrom -= len(commentStr) |
4074 indexFrom -= len(commentStr) |
4078 if indexFrom < 0: |
4075 if indexFrom < 0: |
4079 indexFrom = 0 |
4076 indexFrom = 0 |
4080 |
4077 |
4081 # adjust selection end |
4078 # adjust selection end |
4082 if line == lineTo: |
4079 if line == lineTo: |
4083 indexTo -= len(commentStr) |
4080 indexTo -= len(commentStr) |
4084 if indexTo < 0: |
4081 if indexTo < 0: |
4085 indexTo = 0 |
4082 indexTo = 0 |
4086 |
4083 |
4087 # change the selection accordingly |
4084 # change the selection accordingly |
4088 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) |
4085 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) |
4089 self.endUndoAction() |
4086 self.endUndoAction() |
4090 |
4087 |
4091 def commentLineOrSelection(self): |
4088 def commentLineOrSelection(self): |
4092 """ |
4089 """ |
4093 Public slot to comment the current line or current selection. |
4090 Public slot to comment the current line or current selection. |
4094 """ |
4091 """ |
4095 if self.hasSelectedText(): |
4092 if self.hasSelectedText(): |
4110 """ |
4107 """ |
4111 Public slot to stream comment the current line. |
4108 Public slot to stream comment the current line. |
4112 """ |
4109 """ |
4113 if self.lexer_ is None or not self.lexer_.canStreamComment(): |
4110 if self.lexer_ is None or not self.lexer_.canStreamComment(): |
4114 return |
4111 return |
4115 |
4112 |
4116 commentStr = self.lexer_.streamCommentStr() |
4113 commentStr = self.lexer_.streamCommentStr() |
4117 line, index = self.getCursorPosition() |
4114 line, index = self.getCursorPosition() |
4118 |
4115 |
4119 self.beginUndoAction() |
4116 self.beginUndoAction() |
4120 self.insertAt(commentStr['end'], line, self.lineLength(line)) |
4117 self.insertAt(commentStr["end"], line, self.lineLength(line)) |
4121 self.insertAt(commentStr['start'], line, 0) |
4118 self.insertAt(commentStr["start"], line, 0) |
4122 self.endUndoAction() |
4119 self.endUndoAction() |
4123 |
4120 |
4124 def streamCommentSelection(self): |
4121 def streamCommentSelection(self): |
4125 """ |
4122 """ |
4126 Public slot to comment the current selection. |
4123 Public slot to comment the current selection. |
4127 """ |
4124 """ |
4128 if self.lexer_ is None or not self.lexer_.canStreamComment(): |
4125 if self.lexer_ is None or not self.lexer_.canStreamComment(): |
4129 return |
4126 return |
4130 |
4127 |
4131 if not self.hasSelectedText(): |
4128 if not self.hasSelectedText(): |
4132 return |
4129 return |
4133 |
4130 |
4134 commentStr = self.lexer_.streamCommentStr() |
4131 commentStr = self.lexer_.streamCommentStr() |
4135 |
4132 |
4136 # get the selection boundaries |
4133 # get the selection boundaries |
4137 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4134 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4138 if indexTo == 0: |
4135 if indexTo == 0: |
4139 endLine = lineTo - 1 |
4136 endLine = lineTo - 1 |
4140 endIndex = self.lineLength(endLine) |
4137 endIndex = self.lineLength(endLine) |
4141 else: |
4138 else: |
4142 endLine = lineTo |
4139 endLine = lineTo |
4143 endIndex = indexTo |
4140 endIndex = indexTo |
4144 |
4141 |
4145 self.beginUndoAction() |
4142 self.beginUndoAction() |
4146 self.insertAt(commentStr['end'], endLine, endIndex) |
4143 self.insertAt(commentStr["end"], endLine, endIndex) |
4147 self.insertAt(commentStr['start'], lineFrom, indexFrom) |
4144 self.insertAt(commentStr["start"], lineFrom, indexFrom) |
4148 |
4145 |
4149 # change the selection accordingly |
4146 # change the selection accordingly |
4150 if indexTo > 0: |
4147 if indexTo > 0: |
4151 indexTo += len(commentStr['end']) |
4148 indexTo += len(commentStr["end"]) |
4152 if lineFrom == endLine: |
4149 if lineFrom == endLine: |
4153 indexTo += len(commentStr['start']) |
4150 indexTo += len(commentStr["start"]) |
4154 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) |
4151 self.setSelection(lineFrom, indexFrom, lineTo, indexTo) |
4155 self.endUndoAction() |
4152 self.endUndoAction() |
4156 |
4153 |
4157 def streamCommentLineOrSelection(self): |
4154 def streamCommentLineOrSelection(self): |
4158 """ |
4155 """ |
4159 Public slot to stream comment the current line or current selection. |
4156 Public slot to stream comment the current line or current selection. |
4160 """ |
4157 """ |
4161 if self.hasSelectedText(): |
4158 if self.hasSelectedText(): |
4162 self.streamCommentSelection() |
4159 self.streamCommentSelection() |
4163 else: |
4160 else: |
4164 self.streamCommentLine() |
4161 self.streamCommentLine() |
4165 |
4162 |
4166 def boxCommentLine(self): |
4163 def boxCommentLine(self): |
4167 """ |
4164 """ |
4168 Public slot to box comment the current line. |
4165 Public slot to box comment the current line. |
4169 """ |
4166 """ |
4170 if self.lexer_ is None or not self.lexer_.canBoxComment(): |
4167 if self.lexer_ is None or not self.lexer_.canBoxComment(): |
4171 return |
4168 return |
4172 |
4169 |
4173 commentStr = self.lexer_.boxCommentStr() |
4170 commentStr = self.lexer_.boxCommentStr() |
4174 line, index = self.getCursorPosition() |
4171 line, index = self.getCursorPosition() |
4175 |
4172 |
4176 eol = self.getLineSeparator() |
4173 eol = self.getLineSeparator() |
4177 self.beginUndoAction() |
4174 self.beginUndoAction() |
4178 self.insertAt(eol, line, self.lineLength(line)) |
4175 self.insertAt(eol, line, self.lineLength(line)) |
4179 self.insertAt(commentStr['end'], line + 1, 0) |
4176 self.insertAt(commentStr["end"], line + 1, 0) |
4180 self.insertAt(commentStr['middle'], line, 0) |
4177 self.insertAt(commentStr["middle"], line, 0) |
4181 self.insertAt(eol, line, 0) |
4178 self.insertAt(eol, line, 0) |
4182 self.insertAt(commentStr['start'], line, 0) |
4179 self.insertAt(commentStr["start"], line, 0) |
4183 self.endUndoAction() |
4180 self.endUndoAction() |
4184 |
4181 |
4185 def boxCommentSelection(self): |
4182 def boxCommentSelection(self): |
4186 """ |
4183 """ |
4187 Public slot to box comment the current selection. |
4184 Public slot to box comment the current selection. |
4188 """ |
4185 """ |
4189 if self.lexer_ is None or not self.lexer_.canBoxComment(): |
4186 if self.lexer_ is None or not self.lexer_.canBoxComment(): |
4190 return |
4187 return |
4191 |
4188 |
4192 if not self.hasSelectedText(): |
4189 if not self.hasSelectedText(): |
4193 return |
4190 return |
4194 |
4191 |
4195 commentStr = self.lexer_.boxCommentStr() |
4192 commentStr = self.lexer_.boxCommentStr() |
4196 |
4193 |
4197 # get the selection boundaries |
4194 # get the selection boundaries |
4198 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4195 lineFrom, indexFrom, lineTo, indexTo = self.getSelection() |
4199 endLine = lineTo if indexTo else lineTo - 1 |
4196 endLine = lineTo if indexTo else lineTo - 1 |
4200 |
4197 |
4201 self.beginUndoAction() |
4198 self.beginUndoAction() |
4202 # iterate over the lines |
4199 # iterate over the lines |
4203 for line in range(lineFrom, endLine + 1): |
4200 for line in range(lineFrom, endLine + 1): |
4204 self.insertAt(commentStr['middle'], line, 0) |
4201 self.insertAt(commentStr["middle"], line, 0) |
4205 |
4202 |
4206 # now do the comments before and after the selection |
4203 # now do the comments before and after the selection |
4207 eol = self.getLineSeparator() |
4204 eol = self.getLineSeparator() |
4208 self.insertAt(eol, endLine, self.lineLength(endLine)) |
4205 self.insertAt(eol, endLine, self.lineLength(endLine)) |
4209 self.insertAt(commentStr['end'], endLine + 1, 0) |
4206 self.insertAt(commentStr["end"], endLine + 1, 0) |
4210 self.insertAt(eol, lineFrom, 0) |
4207 self.insertAt(eol, lineFrom, 0) |
4211 self.insertAt(commentStr['start'], lineFrom, 0) |
4208 self.insertAt(commentStr["start"], lineFrom, 0) |
4212 |
4209 |
4213 # change the selection accordingly |
4210 # change the selection accordingly |
4214 self.setSelection(lineFrom, 0, endLine + 3, 0) |
4211 self.setSelection(lineFrom, 0, endLine + 3, 0) |
4215 self.endUndoAction() |
4212 self.endUndoAction() |
4216 |
4213 |
4217 def boxCommentLineOrSelection(self): |
4214 def boxCommentLineOrSelection(self): |
4218 """ |
4215 """ |
4219 Public slot to box comment the current line or current selection. |
4216 Public slot to box comment the current line or current selection. |
4220 """ |
4217 """ |
4221 if self.hasSelectedText(): |
4218 if self.hasSelectedText(): |
4222 self.boxCommentSelection() |
4219 self.boxCommentSelection() |
4223 else: |
4220 else: |
4224 self.boxCommentLine() |
4221 self.boxCommentLine() |
4225 |
4222 |
4226 ########################################################################### |
4223 ########################################################################### |
4227 ## Indentation handling methods below |
4224 ## Indentation handling methods below |
4228 ########################################################################### |
4225 ########################################################################### |
4229 |
4226 |
4230 def __indentLine(self, indent=True): |
4227 def __indentLine(self, indent=True): |
4231 """ |
4228 """ |
4232 Private method to indent or unindent the current line. |
4229 Private method to indent or unindent the current line. |
4233 |
4230 |
4234 @param indent flag indicating an indent operation (boolean) |
4231 @param indent flag indicating an indent operation (boolean) |
4235 <br />If the flag is true, an indent operation is performed. |
4232 <br />If the flag is true, an indent operation is performed. |
4236 Otherwise the current line is unindented. |
4233 Otherwise the current line is unindented. |
4237 """ |
4234 """ |
4238 line, index = self.getCursorPosition() |
4235 line, index = self.getCursorPosition() |
4436 if self.lexer_ is not None: |
4436 if self.lexer_ is not None: |
4437 self.lexer_.readSettings(Preferences.getSettings(), "Scintilla") |
4437 self.lexer_.readSettings(Preferences.getSettings(), "Scintilla") |
4438 if self.lexer_.hasSubstyles(): |
4438 if self.lexer_.hasSubstyles(): |
4439 self.lexer_.readSubstyles(self) |
4439 self.lexer_.readSubstyles(self) |
4440 self.lexer_.initProperties() |
4440 self.lexer_.initProperties() |
4441 |
4441 |
4442 self.lexer_.setDefaultColor(self.lexer_.color(0)) |
4442 self.lexer_.setDefaultColor(self.lexer_.color(0)) |
4443 self.lexer_.setDefaultPaper(self.lexer_.paper(0)) |
4443 self.lexer_.setDefaultPaper(self.lexer_.paper(0)) |
4444 |
4444 |
4445 self.__bindLexer(self.fileName) |
4445 self.__bindLexer(self.fileName) |
4446 self.recolor() |
4446 self.recolor() |
4447 |
4447 |
4448 # read the typing completer settings |
4448 # read the typing completer settings |
4449 if self.completer is not None: |
4449 if self.completer is not None: |
4450 self.completer.readSettings() |
4450 self.completer.readSettings() |
4451 |
4451 |
4452 # set the line marker colours or pixmap |
4452 # set the line marker colours or pixmap |
4453 if Preferences.getEditor("LineMarkersBackground"): |
4453 if Preferences.getEditor("LineMarkersBackground"): |
4454 self.markerDefine(QsciScintilla.MarkerSymbol.Background, |
4454 self.markerDefine(QsciScintilla.MarkerSymbol.Background, self.currentline) |
4455 self.currentline) |
4455 self.markerDefine(QsciScintilla.MarkerSymbol.Background, self.errorline) |
4456 self.markerDefine(QsciScintilla.MarkerSymbol.Background, |
|
4457 self.errorline) |
|
4458 self.__setLineMarkerColours() |
4456 self.__setLineMarkerColours() |
4459 else: |
4457 else: |
4460 self.markerDefine( |
4458 self.markerDefine( |
4461 UI.PixmapCache.getPixmap("currentLineMarker"), |
4459 UI.PixmapCache.getPixmap("currentLineMarker"), self.currentline |
4462 self.currentline) |
4460 ) |
4463 self.markerDefine( |
4461 self.markerDefine( |
4464 UI.PixmapCache.getPixmap("errorLineMarker"), |
4462 UI.PixmapCache.getPixmap("errorLineMarker"), self.errorline |
4465 self.errorline) |
4463 ) |
4466 |
4464 |
4467 # set the text display |
4465 # set the text display |
4468 self.__setTextDisplay() |
4466 self.__setTextDisplay() |
4469 |
4467 |
4470 # set margin 0 and 2 configuration |
4468 # set margin 0 and 2 configuration |
4471 self.__setMarginsDisplay() |
4469 self.__setMarginsDisplay() |
4472 |
4470 |
4473 # set the auto-completion function |
4471 # set the auto-completion function |
4474 self.__acCache.setSize( |
4472 self.__acCache.setSize(Preferences.getEditor("AutoCompletionCacheSize")) |
4475 Preferences.getEditor("AutoCompletionCacheSize")) |
|
4476 self.__acCache.setMaximumCacheTime( |
4473 self.__acCache.setMaximumCacheTime( |
4477 Preferences.getEditor("AutoCompletionCacheTime")) |
4474 Preferences.getEditor("AutoCompletionCacheTime") |
4478 self.__acCacheEnabled = Preferences.getEditor( |
4475 ) |
4479 "AutoCompletionCacheEnabled") |
4476 self.__acCacheEnabled = Preferences.getEditor("AutoCompletionCacheEnabled") |
4480 acTimeout = Preferences.getEditor("AutoCompletionTimeout") |
4477 acTimeout = Preferences.getEditor("AutoCompletionTimeout") |
4481 if acTimeout != self.__acTimer.interval: |
4478 if acTimeout != self.__acTimer.interval: |
4482 self.__acTimer.setInterval(acTimeout) |
4479 self.__acTimer.setInterval(acTimeout) |
4483 self.__setAutoCompletion() |
4480 self.__setAutoCompletion() |
4484 |
4481 |
4485 # set the calltips function |
4482 # set the calltips function |
4486 self.__setCallTips() |
4483 self.__setCallTips() |
4487 |
4484 |
4488 # set the autosave flags |
4485 # set the autosave flags |
4489 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0 |
4486 self.autosaveEnabled = Preferences.getEditor("AutosaveInterval") > 0 |
4490 |
4487 |
4491 if Preferences.getEditor("MiniContextMenu") != self.miniMenu: |
4488 if Preferences.getEditor("MiniContextMenu") != self.miniMenu: |
4492 # regenerate context menu |
4489 # regenerate context menu |
4493 self.__initContextMenu() |
4490 self.__initContextMenu() |
4494 else: |
4491 else: |
4495 # set checked context menu items |
4492 # set checked context menu items |
4496 self.menuActs["AutoCompletionEnable"].setChecked( |
4493 self.menuActs["AutoCompletionEnable"].setChecked( |
4497 self.autoCompletionThreshold() != -1) |
4494 self.autoCompletionThreshold() != -1 |
4498 self.menuActs["MonospacedFont"].setChecked( |
4495 ) |
4499 self.useMonospaced) |
4496 self.menuActs["MonospacedFont"].setChecked(self.useMonospaced) |
4500 self.menuActs["AutosaveEnable"].setChecked( |
4497 self.menuActs["AutosaveEnable"].setChecked( |
4501 self.autosaveEnabled and not self.autosaveManuallyDisabled) |
4498 self.autosaveEnabled and not self.autosaveManuallyDisabled |
4502 |
4499 ) |
|
4500 |
4503 # regenerate the margins context menu(s) |
4501 # regenerate the margins context menu(s) |
4504 self.__initContextMenuMargins() |
4502 self.__initContextMenuMargins() |
4505 |
4503 |
4506 if Preferences.getEditor("MarkOccurrencesEnabled"): |
4504 if Preferences.getEditor("MarkOccurrencesEnabled"): |
4507 self.__markOccurrencesTimer.setInterval( |
4505 self.__markOccurrencesTimer.setInterval( |
4508 Preferences.getEditor("MarkOccurrencesTimeout")) |
4506 Preferences.getEditor("MarkOccurrencesTimeout") |
|
4507 ) |
4509 else: |
4508 else: |
4510 self.__markOccurrencesTimer.stop() |
4509 self.__markOccurrencesTimer.stop() |
4511 self.clearSearchIndicators() |
4510 self.clearSearchIndicators() |
4512 |
4511 |
4513 if Preferences.getEditor("OnlineSyntaxCheck"): |
4512 if Preferences.getEditor("OnlineSyntaxCheck"): |
4514 self.__onlineSyntaxCheckTimer.setInterval( |
4513 self.__onlineSyntaxCheckTimer.setInterval( |
4515 Preferences.getEditor("OnlineSyntaxCheckInterval") * 1000) |
4514 Preferences.getEditor("OnlineSyntaxCheckInterval") * 1000 |
|
4515 ) |
4516 else: |
4516 else: |
4517 self.__onlineSyntaxCheckTimer.stop() |
4517 self.__onlineSyntaxCheckTimer.stop() |
4518 |
4518 |
4519 if Preferences.getEditor("OnlineChangeTrace"): |
4519 if Preferences.getEditor("OnlineChangeTrace"): |
4520 self.__onlineChangeTraceTimer.setInterval( |
4520 self.__onlineChangeTraceTimer.setInterval( |
4521 Preferences.getEditor("OnlineChangeTraceInterval")) |
4521 Preferences.getEditor("OnlineChangeTraceInterval") |
|
4522 ) |
4522 else: |
4523 else: |
4523 self.__onlineChangeTraceTimer.stop() |
4524 self.__onlineChangeTraceTimer.stop() |
4524 self.__deleteAllChangeMarkers() |
4525 self.__deleteAllChangeMarkers() |
4525 self.markerDefine(self.__createChangeMarkerPixmap( |
4526 self.markerDefine( |
4526 "OnlineChangeTraceMarkerUnsaved"), self.__changeMarkerUnsaved) |
4527 self.__createChangeMarkerPixmap("OnlineChangeTraceMarkerUnsaved"), |
4527 self.markerDefine(self.__createChangeMarkerPixmap( |
4528 self.__changeMarkerUnsaved, |
4528 "OnlineChangeTraceMarkerSaved"), self.__changeMarkerSaved) |
4529 ) |
4529 |
4530 self.markerDefine( |
|
4531 self.__createChangeMarkerPixmap("OnlineChangeTraceMarkerSaved"), |
|
4532 self.__changeMarkerSaved, |
|
4533 ) |
|
4534 |
4530 # refresh the annotations display |
4535 # refresh the annotations display |
4531 self.__refreshAnnotations() |
4536 self.__refreshAnnotations() |
4532 |
4537 |
4533 self.__markerMap.setMapPosition( |
4538 self.__markerMap.setMapPosition(Preferences.getEditor("ShowMarkerMapOnRight")) |
4534 Preferences.getEditor("ShowMarkerMapOnRight")) |
|
4535 self.__markerMap.initColors() |
4539 self.__markerMap.initColors() |
4536 |
4540 |
4537 self.setLanguage(self.fileName, propagate=False) |
4541 self.setLanguage(self.fileName, propagate=False) |
4538 |
4542 |
4539 self.settingsRead.emit() |
4543 self.settingsRead.emit() |
4540 |
4544 |
4541 def __setLineMarkerColours(self): |
4545 def __setLineMarkerColours(self): |
4542 """ |
4546 """ |
4543 Private method to set the line marker colours. |
4547 Private method to set the line marker colours. |
4544 """ |
4548 """ |
4545 self.setMarkerForegroundColor( |
4549 self.setMarkerForegroundColor( |
4546 Preferences.getEditorColour("CurrentMarker"), self.currentline) |
4550 Preferences.getEditorColour("CurrentMarker"), self.currentline |
|
4551 ) |
4547 self.setMarkerBackgroundColor( |
4552 self.setMarkerBackgroundColor( |
4548 Preferences.getEditorColour("CurrentMarker"), self.currentline) |
4553 Preferences.getEditorColour("CurrentMarker"), self.currentline |
|
4554 ) |
4549 self.setMarkerForegroundColor( |
4555 self.setMarkerForegroundColor( |
4550 Preferences.getEditorColour("ErrorMarker"), self.errorline) |
4556 Preferences.getEditorColour("ErrorMarker"), self.errorline |
|
4557 ) |
4551 self.setMarkerBackgroundColor( |
4558 self.setMarkerBackgroundColor( |
4552 Preferences.getEditorColour("ErrorMarker"), self.errorline) |
4559 Preferences.getEditorColour("ErrorMarker"), self.errorline |
4553 |
4560 ) |
|
4561 |
4554 def __setMarginsDisplay(self): |
4562 def __setMarginsDisplay(self): |
4555 """ |
4563 """ |
4556 Private method to configure margins 0 and 2. |
4564 Private method to configure margins 0 and 2. |
4557 """ |
4565 """ |
4558 # set the settings for all margins |
4566 # set the settings for all margins |
4559 self.setMarginsFont(Preferences.getEditorOtherFonts("MarginsFont")) |
4567 self.setMarginsFont(Preferences.getEditorOtherFonts("MarginsFont")) |
4560 self.setMarginsForegroundColor( |
4568 self.setMarginsForegroundColor(Preferences.getEditorColour("MarginsForeground")) |
4561 Preferences.getEditorColour("MarginsForeground")) |
4569 self.setMarginsBackgroundColor(Preferences.getEditorColour("MarginsBackground")) |
4562 self.setMarginsBackgroundColor( |
4570 |
4563 Preferences.getEditorColour("MarginsBackground")) |
|
4564 |
|
4565 # reset standard margins settings |
4571 # reset standard margins settings |
4566 for margin in range(5): |
4572 for margin in range(5): |
4567 self.setMarginLineNumbers(margin, False) |
4573 self.setMarginLineNumbers(margin, False) |
4568 self.setMarginMarkerMask(margin, 0) |
4574 self.setMarginMarkerMask(margin, 0) |
4569 self.setMarginWidth(margin, 0) |
4575 self.setMarginWidth(margin, 0) |
4570 self.setMarginSensitivity(margin, False) |
4576 self.setMarginSensitivity(margin, False) |
4571 |
4577 |
4572 # set marker margin(s) settings |
4578 # set marker margin(s) settings |
4573 self.__bmMargin = 0 |
4579 self.__bmMargin = 0 |
4574 self.__linenoMargin = 1 |
4580 self.__linenoMargin = 1 |
4575 self.__bpMargin = 2 |
4581 self.__bpMargin = 2 |
4576 self.__foldMargin = 3 |
4582 self.__foldMargin = 3 |
4577 self.__indicMargin = 4 |
4583 self.__indicMargin = 4 |
4578 |
4584 |
4579 marginBmMask = (1 << self.bookmark) |
4585 marginBmMask = 1 << self.bookmark |
4580 self.setMarginWidth(self.__bmMargin, 16) |
4586 self.setMarginWidth(self.__bmMargin, 16) |
4581 self.setMarginSensitivity(self.__bmMargin, True) |
4587 self.setMarginSensitivity(self.__bmMargin, True) |
4582 self.setMarginMarkerMask(self.__bmMargin, marginBmMask) |
4588 self.setMarginMarkerMask(self.__bmMargin, marginBmMask) |
4583 |
4589 |
4584 marginBpMask = ( |
4590 marginBpMask = ( |
4585 (1 << self.breakpoint) | |
4591 (1 << self.breakpoint) |
4586 (1 << self.cbreakpoint) | |
4592 | (1 << self.cbreakpoint) |
4587 (1 << self.tbreakpoint) | |
4593 | (1 << self.tbreakpoint) |
4588 (1 << self.tcbreakpoint) | |
4594 | (1 << self.tcbreakpoint) |
4589 (1 << self.dbreakpoint) |
4595 | (1 << self.dbreakpoint) |
4590 ) |
4596 ) |
4591 self.setMarginWidth(self.__bpMargin, 16) |
4597 self.setMarginWidth(self.__bpMargin, 16) |
4592 self.setMarginSensitivity(self.__bpMargin, True) |
4598 self.setMarginSensitivity(self.__bpMargin, True) |
4593 self.setMarginMarkerMask(self.__bpMargin, marginBpMask) |
4599 self.setMarginMarkerMask(self.__bpMargin, marginBpMask) |
4594 |
4600 |
4595 marginIndicMask = ( |
4601 marginIndicMask = ( |
4596 (1 << self.syntaxerror) | |
4602 (1 << self.syntaxerror) |
4597 (1 << self.notcovered) | |
4603 | (1 << self.notcovered) |
4598 (1 << self.taskmarker) | |
4604 | (1 << self.taskmarker) |
4599 (1 << self.warning) | |
4605 | (1 << self.warning) |
4600 (1 << self.__changeMarkerUnsaved) | |
4606 | (1 << self.__changeMarkerUnsaved) |
4601 (1 << self.__changeMarkerSaved) | |
4607 | (1 << self.__changeMarkerSaved) |
4602 (1 << self.currentline) | |
4608 | (1 << self.currentline) |
4603 (1 << self.errorline) |
4609 | (1 << self.errorline) |
4604 ) |
4610 ) |
4605 self.setMarginWidth(self.__indicMargin, 16) |
4611 self.setMarginWidth(self.__indicMargin, 16) |
4606 self.setMarginSensitivity(self.__indicMargin, True) |
4612 self.setMarginSensitivity(self.__indicMargin, True) |
4607 self.setMarginMarkerMask(self.__indicMargin, marginIndicMask) |
4613 self.setMarginMarkerMask(self.__indicMargin, marginIndicMask) |
4608 |
4614 |
4609 # set linenumber margin settings |
4615 # set linenumber margin settings |
4610 linenoMargin = Preferences.getEditor("LinenoMargin") |
4616 linenoMargin = Preferences.getEditor("LinenoMargin") |
4611 self.setMarginLineNumbers(self.__linenoMargin, linenoMargin) |
4617 self.setMarginLineNumbers(self.__linenoMargin, linenoMargin) |
4612 if linenoMargin: |
4618 if linenoMargin: |
4613 self.__resizeLinenoMargin() |
4619 self.__resizeLinenoMargin() |
4614 else: |
4620 else: |
4615 self.setMarginWidth(self.__linenoMargin, 0) |
4621 self.setMarginWidth(self.__linenoMargin, 0) |
4616 |
4622 |
4617 # set folding margin settings |
4623 # set folding margin settings |
4618 if Preferences.getEditor("FoldingMargin"): |
4624 if Preferences.getEditor("FoldingMargin"): |
4619 self.setMarginWidth(self.__foldMargin, 16) |
4625 self.setMarginWidth(self.__foldMargin, 16) |
4620 folding = Preferences.getEditor("FoldingStyle") |
4626 folding = Preferences.getEditor("FoldingStyle") |
4621 self.setFolding(folding, self.__foldMargin) |
4627 self.setFolding(folding, self.__foldMargin) |
4622 self.setFoldMarginColors( |
4628 self.setFoldMarginColors( |
4623 Preferences.getEditorColour("FoldmarginBackground"), |
4629 Preferences.getEditorColour("FoldmarginBackground"), |
4624 Preferences.getEditorColour("FoldmarginBackground")) |
4630 Preferences.getEditorColour("FoldmarginBackground"), |
|
4631 ) |
4625 self.setFoldMarkersColors( |
4632 self.setFoldMarkersColors( |
4626 Preferences.getEditorColour("FoldMarkersForeground"), |
4633 Preferences.getEditorColour("FoldMarkersForeground"), |
4627 Preferences.getEditorColour("FoldMarkersBackground")) |
4634 Preferences.getEditorColour("FoldMarkersBackground"), |
|
4635 ) |
4628 else: |
4636 else: |
4629 self.setMarginWidth(self.__foldMargin, 0) |
4637 self.setMarginWidth(self.__foldMargin, 0) |
4630 self.setFolding(QsciScintilla.FoldStyle.NoFoldStyle.value, |
4638 self.setFolding( |
4631 self.__foldMargin) |
4639 QsciScintilla.FoldStyle.NoFoldStyle.value, self.__foldMargin |
4632 |
4640 ) |
|
4641 |
4633 def __resizeLinenoMargin(self): |
4642 def __resizeLinenoMargin(self): |
4634 """ |
4643 """ |
4635 Private slot to resize the line numbers margin. |
4644 Private slot to resize the line numbers margin. |
4636 """ |
4645 """ |
4637 linenoMargin = Preferences.getEditor("LinenoMargin") |
4646 linenoMargin = Preferences.getEditor("LinenoMargin") |
4638 if linenoMargin: |
4647 if linenoMargin: |
4639 self.setMarginWidth( |
4648 self.setMarginWidth(self.__linenoMargin, "8" * (len(str(self.lines())) + 1)) |
4640 self.__linenoMargin, '8' * (len(str(self.lines())) + 1)) |
4649 |
4641 |
|
4642 def __setTabAndIndent(self): |
4650 def __setTabAndIndent(self): |
4643 """ |
4651 """ |
4644 Private method to set indentation size and style and tab width. |
4652 Private method to set indentation size and style and tab width. |
4645 """ |
4653 """ |
4646 self.setTabWidth(self.__getEditorConfig("TabWidth")) |
4654 self.setTabWidth(self.__getEditorConfig("TabWidth")) |
4647 self.setIndentationWidth(self.__getEditorConfig("IndentWidth")) |
4655 self.setIndentationWidth(self.__getEditorConfig("IndentWidth")) |
4648 if self.lexer_ and self.lexer_.alwaysKeepTabs(): |
4656 if self.lexer_ and self.lexer_.alwaysKeepTabs(): |
4649 self.setIndentationsUseTabs(True) |
4657 self.setIndentationsUseTabs(True) |
4650 else: |
4658 else: |
4651 self.setIndentationsUseTabs( |
4659 self.setIndentationsUseTabs(self.__getEditorConfig("TabForIndentation")) |
4652 self.__getEditorConfig("TabForIndentation")) |
4660 |
4653 |
|
4654 def __setTextDisplay(self): |
4661 def __setTextDisplay(self): |
4655 """ |
4662 """ |
4656 Private method to configure the text display. |
4663 Private method to configure the text display. |
4657 """ |
4664 """ |
4658 self.__setTabAndIndent() |
4665 self.__setTabAndIndent() |
4659 |
4666 |
4660 self.setTabIndents(Preferences.getEditor("TabIndents")) |
4667 self.setTabIndents(Preferences.getEditor("TabIndents")) |
4661 self.setBackspaceUnindents(Preferences.getEditor("TabIndents")) |
4668 self.setBackspaceUnindents(Preferences.getEditor("TabIndents")) |
4662 self.setIndentationGuides(Preferences.getEditor("IndentationGuides")) |
4669 self.setIndentationGuides(Preferences.getEditor("IndentationGuides")) |
4663 self.setIndentationGuidesBackgroundColor( |
4670 self.setIndentationGuidesBackgroundColor( |
4664 Preferences.getEditorColour("IndentationGuidesBackground")) |
4671 Preferences.getEditorColour("IndentationGuidesBackground") |
|
4672 ) |
4665 self.setIndentationGuidesForegroundColor( |
4673 self.setIndentationGuidesForegroundColor( |
4666 Preferences.getEditorColour("IndentationGuidesForeground")) |
4674 Preferences.getEditorColour("IndentationGuidesForeground") |
|
4675 ) |
4667 if Preferences.getEditor("ShowWhitespace"): |
4676 if Preferences.getEditor("ShowWhitespace"): |
4668 self.setWhitespaceVisibility( |
4677 self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsVisible) |
4669 QsciScintilla.WhitespaceVisibility.WsVisible) |
|
4670 with contextlib.suppress(AttributeError): |
4678 with contextlib.suppress(AttributeError): |
4671 self.setWhitespaceForegroundColor( |
4679 self.setWhitespaceForegroundColor( |
4672 Preferences.getEditorColour("WhitespaceForeground")) |
4680 Preferences.getEditorColour("WhitespaceForeground") |
|
4681 ) |
4673 self.setWhitespaceBackgroundColor( |
4682 self.setWhitespaceBackgroundColor( |
4674 Preferences.getEditorColour("WhitespaceBackground")) |
4683 Preferences.getEditorColour("WhitespaceBackground") |
4675 self.setWhitespaceSize( |
4684 ) |
4676 Preferences.getEditor("WhitespaceSize")) |
4685 self.setWhitespaceSize(Preferences.getEditor("WhitespaceSize")) |
4677 else: |
4686 else: |
4678 self.setWhitespaceVisibility( |
4687 self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsInvisible) |
4679 QsciScintilla.WhitespaceVisibility.WsInvisible) |
|
4680 self.setEolVisibility(Preferences.getEditor("ShowEOL")) |
4688 self.setEolVisibility(Preferences.getEditor("ShowEOL")) |
4681 self.setAutoIndent(Preferences.getEditor("AutoIndentation")) |
4689 self.setAutoIndent(Preferences.getEditor("AutoIndentation")) |
4682 if Preferences.getEditor("BraceHighlighting"): |
4690 if Preferences.getEditor("BraceHighlighting"): |
4683 self.setBraceMatching(QsciScintilla.BraceMatch.SloppyBraceMatch) |
4691 self.setBraceMatching(QsciScintilla.BraceMatch.SloppyBraceMatch) |
4684 else: |
4692 else: |
4685 self.setBraceMatching(QsciScintilla.BraceMatch.NoBraceMatch) |
4693 self.setBraceMatching(QsciScintilla.BraceMatch.NoBraceMatch) |
4686 self.setMatchedBraceForegroundColor( |
4694 self.setMatchedBraceForegroundColor( |
4687 Preferences.getEditorColour("MatchingBrace")) |
4695 Preferences.getEditorColour("MatchingBrace") |
|
4696 ) |
4688 self.setMatchedBraceBackgroundColor( |
4697 self.setMatchedBraceBackgroundColor( |
4689 Preferences.getEditorColour("MatchingBraceBack")) |
4698 Preferences.getEditorColour("MatchingBraceBack") |
|
4699 ) |
4690 self.setUnmatchedBraceForegroundColor( |
4700 self.setUnmatchedBraceForegroundColor( |
4691 Preferences.getEditorColour("NonmatchingBrace")) |
4701 Preferences.getEditorColour("NonmatchingBrace") |
|
4702 ) |
4692 self.setUnmatchedBraceBackgroundColor( |
4703 self.setUnmatchedBraceBackgroundColor( |
4693 Preferences.getEditorColour("NonmatchingBraceBack")) |
4704 Preferences.getEditorColour("NonmatchingBraceBack") |
|
4705 ) |
4694 if Preferences.getEditor("CustomSelectionColours"): |
4706 if Preferences.getEditor("CustomSelectionColours"): |
4695 self.setSelectionBackgroundColor( |
4707 self.setSelectionBackgroundColor( |
4696 Preferences.getEditorColour("SelectionBackground")) |
4708 Preferences.getEditorColour("SelectionBackground") |
|
4709 ) |
4697 else: |
4710 else: |
4698 self.setSelectionBackgroundColor( |
4711 self.setSelectionBackgroundColor( |
4699 QApplication.palette().color(QPalette.ColorRole.Highlight)) |
4712 QApplication.palette().color(QPalette.ColorRole.Highlight) |
|
4713 ) |
4700 if Preferences.getEditor("ColourizeSelText"): |
4714 if Preferences.getEditor("ColourizeSelText"): |
4701 self.resetSelectionForegroundColor() |
4715 self.resetSelectionForegroundColor() |
4702 elif Preferences.getEditor("CustomSelectionColours"): |
4716 elif Preferences.getEditor("CustomSelectionColours"): |
4703 self.setSelectionForegroundColor( |
4717 self.setSelectionForegroundColor( |
4704 Preferences.getEditorColour("SelectionForeground")) |
4718 Preferences.getEditorColour("SelectionForeground") |
|
4719 ) |
4705 else: |
4720 else: |
4706 self.setSelectionForegroundColor( |
4721 self.setSelectionForegroundColor( |
4707 QApplication.palette().color( |
4722 QApplication.palette().color(QPalette.ColorRole.HighlightedText) |
4708 QPalette.ColorRole.HighlightedText)) |
4723 ) |
4709 self.setSelectionToEol(Preferences.getEditor("ExtendSelectionToEol")) |
4724 self.setSelectionToEol(Preferences.getEditor("ExtendSelectionToEol")) |
4710 self.setCaretForegroundColor( |
4725 self.setCaretForegroundColor(Preferences.getEditorColour("CaretForeground")) |
4711 Preferences.getEditorColour("CaretForeground")) |
|
4712 self.setCaretLineBackgroundColor( |
4726 self.setCaretLineBackgroundColor( |
4713 Preferences.getEditorColour("CaretLineBackground")) |
4727 Preferences.getEditorColour("CaretLineBackground") |
|
4728 ) |
4714 self.setCaretLineVisible(Preferences.getEditor("CaretLineVisible")) |
4729 self.setCaretLineVisible(Preferences.getEditor("CaretLineVisible")) |
4715 self.setCaretLineAlwaysVisible( |
4730 self.setCaretLineAlwaysVisible(Preferences.getEditor("CaretLineAlwaysVisible")) |
4716 Preferences.getEditor("CaretLineAlwaysVisible")) |
|
4717 self.caretWidth = Preferences.getEditor("CaretWidth") |
4731 self.caretWidth = Preferences.getEditor("CaretWidth") |
4718 self.setCaretWidth(self.caretWidth) |
4732 self.setCaretWidth(self.caretWidth) |
4719 self.caretLineFrameWidth = Preferences.getEditor("CaretLineFrameWidth") |
4733 self.caretLineFrameWidth = Preferences.getEditor("CaretLineFrameWidth") |
4720 self.setCaretLineFrameWidth(self.caretLineFrameWidth) |
4734 self.setCaretLineFrameWidth(self.caretLineFrameWidth) |
4721 self.useMonospaced = Preferences.getEditor("UseMonospacedFont") |
4735 self.useMonospaced = Preferences.getEditor("UseMonospacedFont") |
5040 is True |
5050 is True |
5041 @param asynchroneous flag indicating an asynchroneous function |
5051 @param asynchroneous flag indicating an asynchroneous function |
5042 @type bool |
5052 @type bool |
5043 """ |
5053 """ |
5044 if ( |
5054 if ( |
5045 key in self.__completionListHookFunctions or |
5055 key in self.__completionListHookFunctions |
5046 key in self.__completionListAsyncHookFunctions |
5056 or key in self.__completionListAsyncHookFunctions |
5047 ): |
5057 ): |
5048 # it was already registered |
5058 # it was already registered |
5049 EricMessageBox.warning( |
5059 EricMessageBox.warning( |
5050 self, |
5060 self, |
5051 self.tr("Auto-Completion Provider"), |
5061 self.tr("Auto-Completion Provider"), |
5052 self.tr("""The completion list provider '{0}' was already""" |
5062 self.tr( |
5053 """ registered. Ignoring duplicate request.""") |
5063 """The completion list provider '{0}' was already""" |
5054 .format(key)) |
5064 """ registered. Ignoring duplicate request.""" |
|
5065 ).format(key), |
|
5066 ) |
5055 return |
5067 return |
5056 |
5068 |
5057 if asynchroneous: |
5069 if asynchroneous: |
5058 self.__completionListAsyncHookFunctions[key] = func |
5070 self.__completionListAsyncHookFunctions[key] = func |
5059 else: |
5071 else: |
5060 self.__completionListHookFunctions[key] = func |
5072 self.__completionListHookFunctions[key] = func |
5061 |
5073 |
5062 def removeCompletionListHook(self, key): |
5074 def removeCompletionListHook(self, key): |
5063 """ |
5075 """ |
5064 Public method to remove a previously registered completion list |
5076 Public method to remove a previously registered completion list |
5065 provider. |
5077 provider. |
5066 |
5078 |
5067 @param key name of the provider |
5079 @param key name of the provider |
5068 @type str |
5080 @type str |
5069 """ |
5081 """ |
5070 if key in self.__completionListHookFunctions: |
5082 if key in self.__completionListHookFunctions: |
5071 del self.__completionListHookFunctions[key] |
5083 del self.__completionListHookFunctions[key] |
5072 elif key in self.__completionListAsyncHookFunctions: |
5084 elif key in self.__completionListAsyncHookFunctions: |
5073 del self.__completionListAsyncHookFunctions[key] |
5085 del self.__completionListAsyncHookFunctions[key] |
5074 |
5086 |
5075 def getCompletionListHook(self, key): |
5087 def getCompletionListHook(self, key): |
5076 """ |
5088 """ |
5077 Public method to get the registered completion list provider. |
5089 Public method to get the registered completion list provider. |
5078 |
5090 |
5079 @param key name of the provider |
5091 @param key name of the provider |
5080 @type str |
5092 @type str |
5081 @return function providing completion list |
5093 @return function providing completion list |
5082 @rtype function or None |
5094 @rtype function or None |
5083 """ |
5095 """ |
5084 return (self.__completionListHookFunctions.get(key) or |
5096 return self.__completionListHookFunctions.get( |
5085 self.__completionListAsyncHookFunctions.get(key)) |
5097 key |
5086 |
5098 ) or self.__completionListAsyncHookFunctions.get(key) |
|
5099 |
5087 def autoComplete(self, auto=False, context=True): |
5100 def autoComplete(self, auto=False, context=True): |
5088 """ |
5101 """ |
5089 Public method to start auto-completion. |
5102 Public method to start auto-completion. |
5090 |
5103 |
5091 @param auto flag indicating a call from the __charAdded method |
5104 @param auto flag indicating a call from the __charAdded method |
5092 (boolean) |
5105 (boolean) |
5093 @param context flag indicating to complete a context (boolean) |
5106 @param context flag indicating to complete a context (boolean) |
5094 """ |
5107 """ |
5095 if auto and not Preferences.getEditor("AutoCompletionEnabled"): |
5108 if auto and not Preferences.getEditor("AutoCompletionEnabled"): |
5096 # auto-completion is disabled |
5109 # auto-completion is disabled |
5097 return |
5110 return |
5098 |
5111 |
5099 if self.isListActive(): |
5112 if self.isListActive(): |
5100 self.cancelList() |
5113 self.cancelList() |
5101 |
5114 |
5102 if ( |
5115 if ( |
5103 self.__completionListHookFunctions or |
5116 self.__completionListHookFunctions |
5104 self.__completionListAsyncHookFunctions |
5117 or self.__completionListAsyncHookFunctions |
5105 ): |
5118 ): |
5106 # Avoid delayed auto-completion after cursor repositioning |
5119 # Avoid delayed auto-completion after cursor repositioning |
5107 self.__acText = self.__getAcText() |
5120 self.__acText = self.__getAcText() |
5108 if auto and Preferences.getEditor("AutoCompletionTimeout"): |
5121 if auto and Preferences.getEditor("AutoCompletionTimeout"): |
5109 self.__acTimer.stop() |
5122 self.__acTimer.stop() |
5110 self.__acContext = context |
5123 self.__acContext = context |
5111 self.__acTimer.start() |
5124 self.__acTimer.start() |
5112 else: |
5125 else: |
5113 self.__autoComplete(auto, context) |
5126 self.__autoComplete(auto, context) |
5114 elif ( |
5127 elif not auto or ( |
5115 not auto or |
5128 self.autoCompletionSource() != QsciScintilla.AutoCompletionSource.AcsNone |
5116 (self.autoCompletionSource() != |
|
5117 QsciScintilla.AutoCompletionSource.AcsNone) |
|
5118 ): |
5129 ): |
5119 self.autoCompleteQScintilla() |
5130 self.autoCompleteQScintilla() |
5120 |
5131 |
5121 def __getAcText(self): |
5132 def __getAcText(self): |
5122 """ |
5133 """ |
5123 Private method to get the text from cursor position for autocompleting. |
5134 Private method to get the text from cursor position for autocompleting. |
5124 |
5135 |
5125 @return text left of cursor position |
5136 @return text left of cursor position |
5126 @rtype str |
5137 @rtype str |
5127 """ |
5138 """ |
5128 line, col = self.getCursorPosition() |
5139 line, col = self.getCursorPosition() |
5129 text = self.text(line) |
5140 text = self.text(line) |
5130 try: |
5141 try: |
5131 acText = ( |
5142 acText = ( |
5132 self.getWordLeft(line, col - 1) + text[col - 1] |
5143 self.getWordLeft(line, col - 1) + text[col - 1] |
5133 if self.__isStartChar(text[col - 1]) else |
5144 if self.__isStartChar(text[col - 1]) |
5134 self.getWordLeft(line, col) |
5145 else self.getWordLeft(line, col) |
5135 ) |
5146 ) |
5136 except IndexError: |
5147 except IndexError: |
5137 acText = "" |
5148 acText = "" |
5138 |
5149 |
5139 return acText |
5150 return acText |
5140 |
5151 |
5141 def __autoComplete(self, auto=True, context=None): |
5152 def __autoComplete(self, auto=True, context=None): |
5142 """ |
5153 """ |
5143 Private method to start auto-completion via plug-ins. |
5154 Private method to start auto-completion via plug-ins. |
5144 |
5155 |
5145 @param auto flag indicating a call from the __charAdded method |
5156 @param auto flag indicating a call from the __charAdded method |
5146 (boolean) |
5157 (boolean) |
5147 @param context flag indicating to complete a context |
5158 @param context flag indicating to complete a context |
5148 @type bool or None |
5159 @type bool or None |
5149 """ |
5160 """ |
5150 self.__acCompletions.clear() |
5161 self.__acCompletions.clear() |
5151 self.__acCompletionsFinished = 0 |
5162 self.__acCompletionsFinished = 0 |
5152 |
5163 |
5153 # Suppress empty completions |
5164 # Suppress empty completions |
5154 if auto and self.__acText == '': |
5165 if auto and self.__acText == "": |
5155 return |
5166 return |
5156 |
5167 |
5157 completions = ( |
5168 completions = ( |
5158 self.__acCache.get(self.__acText) |
5169 self.__acCache.get(self.__acText) if self.__acCacheEnabled else None |
5159 if self.__acCacheEnabled else |
|
5160 None |
|
5161 ) |
5170 ) |
5162 if completions is not None: |
5171 if completions is not None: |
5163 # show list with cached entries |
5172 # show list with cached entries |
5164 if self.isListActive(): |
5173 if self.isListActive(): |
5165 self.cancelList() |
5174 self.cancelList() |
5166 |
5175 |
5167 self.__showCompletionsList(completions) |
5176 self.__showCompletionsList(completions) |
5168 else: |
5177 else: |
5169 if context is None: |
5178 if context is None: |
5170 context = self.__acContext |
5179 context = self.__acContext |
5171 |
5180 |
5172 for key in self.__completionListAsyncHookFunctions: |
5181 for key in self.__completionListAsyncHookFunctions: |
5173 self.__completionListAsyncHookFunctions[key]( |
5182 self.__completionListAsyncHookFunctions[key]( |
5174 self, context, self.__acText) |
5183 self, context, self.__acText |
5175 |
5184 ) |
|
5185 |
5176 for key in self.__completionListHookFunctions: |
5186 for key in self.__completionListHookFunctions: |
5177 completions = self.__completionListHookFunctions[key]( |
5187 completions = self.__completionListHookFunctions[key](self, context) |
5178 self, context) |
|
5179 self.completionsListReady(completions, self.__acText) |
5188 self.completionsListReady(completions, self.__acText) |
5180 |
5189 |
5181 if Preferences.getEditor("AutoCompletionScintillaOnFail"): |
5190 if Preferences.getEditor("AutoCompletionScintillaOnFail"): |
5182 self.__acWatchdog.start() |
5191 self.__acWatchdog.start() |
5183 |
5192 |
5184 def completionsListReady(self, completions, acText): |
5193 def completionsListReady(self, completions, acText): |
5185 """ |
5194 """ |
5186 Public method to show the completions determined by a completions |
5195 Public method to show the completions determined by a completions |
5187 provider. |
5196 provider. |
5188 |
5197 |
5189 @param completions list of possible completions |
5198 @param completions list of possible completions |
5190 @type list of str or set of str |
5199 @type list of str or set of str |
5191 @param acText text to be completed |
5200 @param acText text to be completed |
5192 @type str |
5201 @type str |
5193 """ |
5202 """ |
5194 currentWord = self.__getAcText() or ' ' |
5203 currentWord = self.__getAcText() or " " |
5195 # process the list only, if not already obsolete ... |
5204 # process the list only, if not already obsolete ... |
5196 if acText != self.__acText or not self.__acText.endswith(currentWord): |
5205 if acText != self.__acText or not self.__acText.endswith(currentWord): |
5197 # Suppress auto-completion done by QScintilla as fallback |
5206 # Suppress auto-completion done by QScintilla as fallback |
5198 self.__acWatchdog.stop() |
5207 self.__acWatchdog.stop() |
5199 return |
5208 return |
5200 |
5209 |
5201 self.__acCompletions.update(set(completions)) |
5210 self.__acCompletions.update(set(completions)) |
5202 |
5211 |
5203 self.__acCompletionsFinished += 1 |
5212 self.__acCompletionsFinished += 1 |
5204 # Got all results from auto completer? |
5213 # Got all results from auto completer? |
5205 if self.__acCompletionsFinished >= ( |
5214 if self.__acCompletionsFinished >= ( |
5206 len(self.__completionListAsyncHookFunctions) + |
5215 len(self.__completionListAsyncHookFunctions) |
5207 len(self.__completionListHookFunctions) |
5216 + len(self.__completionListHookFunctions) |
5208 ): |
5217 ): |
5209 self.__acWatchdog.stop() |
5218 self.__acWatchdog.stop() |
5210 |
5219 |
5211 # Autocomplete with QScintilla if no results present |
5220 # Autocomplete with QScintilla if no results present |
5212 if ( |
5221 if ( |
5213 Preferences.getEditor("AutoCompletionScintillaOnFail") and |
5222 Preferences.getEditor("AutoCompletionScintillaOnFail") |
5214 not self.__acCompletions |
5223 and not self.__acCompletions |
5215 ): |
5224 ): |
5216 self.autoCompleteQScintilla() |
5225 self.autoCompleteQScintilla() |
5217 return |
5226 return |
5218 |
5227 |
5219 # ... or completions are not empty |
5228 # ... or completions are not empty |
5220 if not bool(completions): |
5229 if not bool(completions): |
5221 return |
5230 return |
5222 |
5231 |
5223 if self.isListActive(): |
5232 if self.isListActive(): |
5224 self.cancelList() |
5233 self.cancelList() |
5225 |
5234 |
5226 if self.__acCompletions: |
5235 if self.__acCompletions: |
5227 if self.__acCacheEnabled: |
5236 if self.__acCacheEnabled: |
5228 self.__acCache.add(acText, set(self.__acCompletions)) |
5237 self.__acCache.add(acText, set(self.__acCompletions)) |
5229 self.__showCompletionsList(self.__acCompletions) |
5238 self.__showCompletionsList(self.__acCompletions) |
5230 |
5239 |
5231 def __showCompletionsList(self, completions): |
5240 def __showCompletionsList(self, completions): |
5232 """ |
5241 """ |
5233 Private method to show the completions list. |
5242 Private method to show the completions list. |
5234 |
5243 |
5235 @param completions completions to be shown |
5244 @param completions completions to be shown |
5236 @type list of str or set of str |
5245 @type list of str or set of str |
5237 """ |
5246 """ |
5238 acCompletions = ( |
5247 acCompletions = ( |
5239 sorted(completions, |
5248 sorted(completions, key=self.__replaceLeadingUnderscores) |
5240 key=self.__replaceLeadingUnderscores) |
5249 if Preferences.getEditor("AutoCompletionReversedList") |
5241 if Preferences.getEditor("AutoCompletionReversedList") else |
5250 else sorted(completions) |
5242 sorted(completions) |
|
5243 ) |
5251 ) |
5244 self.showUserList(EditorAutoCompletionListID, acCompletions) |
5252 self.showUserList(EditorAutoCompletionListID, acCompletions) |
5245 |
5253 |
5246 def __replaceLeadingUnderscores(self, txt): |
5254 def __replaceLeadingUnderscores(self, txt): |
5247 """ |
5255 """ |
5248 Private method to replace the first two underlines for invers sorting. |
5256 Private method to replace the first two underlines for invers sorting. |
5249 |
5257 |
5250 @param txt completion text |
5258 @param txt completion text |
5251 @type str |
5259 @type str |
5252 @return modified completion text |
5260 @return modified completion text |
5253 @rtype str |
5261 @rtype str |
5254 """ |
5262 """ |
5255 if txt.startswith('_'): |
5263 if txt.startswith("_"): |
5256 return txt[:2].replace('_', '~') + txt[2:] |
5264 return txt[:2].replace("_", "~") + txt[2:] |
5257 else: |
5265 else: |
5258 return txt |
5266 return txt |
5259 |
5267 |
5260 def __clearCompletionsCache(self): |
5268 def __clearCompletionsCache(self): |
5261 """ |
5269 """ |
5262 Private method to clear the auto-completions cache. |
5270 Private method to clear the auto-completions cache. |
5263 """ |
5271 """ |
5264 self.__acCache.clear() |
5272 self.__acCache.clear() |
5265 |
5273 |
5266 def __completionListSelected(self, listId, txt): |
5274 def __completionListSelected(self, listId, txt): |
5267 """ |
5275 """ |
5268 Private slot to handle the selection from the completion list. |
5276 Private slot to handle the selection from the completion list. |
5269 |
5277 |
5270 @param listId the ID of the user list (should be 1 or 2) (integer) |
5278 @param listId the ID of the user list (should be 1 or 2) (integer) |
5271 @param txt the selected text (string) |
5279 @param txt the selected text (string) |
5272 """ |
5280 """ |
5273 # custom completions via plug-ins |
5281 # custom completions via plug-ins |
5274 if listId == EditorAutoCompletionListID: |
5282 if listId == EditorAutoCompletionListID: |
5275 lst = txt.split() |
5283 lst = txt.split() |
5276 if len(lst) > 1: |
5284 if len(lst) > 1: |
5277 txt = lst[0] |
5285 txt = lst[0] |
5278 |
5286 |
5279 self.beginUndoAction() |
5287 self.beginUndoAction() |
5280 if Preferences.getEditor("AutoCompletionReplaceWord"): |
5288 if Preferences.getEditor("AutoCompletionReplaceWord"): |
5281 self.selectCurrentWord() |
5289 self.selectCurrentWord() |
5282 self.removeSelectedText() |
5290 self.removeSelectedText() |
5283 line, col = self.getCursorPosition() |
5291 line, col = self.getCursorPosition() |
5444 if len(callTips) == 0: |
5454 if len(callTips) == 0: |
5445 if Preferences.getEditor("CallTipsScintillaOnFail"): |
5455 if Preferences.getEditor("CallTipsScintillaOnFail"): |
5446 # try QScintilla calltips |
5456 # try QScintilla calltips |
5447 super().callTip() |
5457 super().callTip() |
5448 return |
5458 return |
5449 |
5459 |
5450 ctshift = 0 |
5460 ctshift = 0 |
5451 for ct in callTips: |
5461 for ct in callTips: |
5452 shift = ct.index("(") |
5462 shift = ct.index("(") |
5453 if ctshift < shift: |
5463 if ctshift < shift: |
5454 ctshift = shift |
5464 ctshift = shift |
5455 |
5465 |
5456 cv = self.callTipsVisible() |
5466 cv = self.callTipsVisible() |
5457 ct = ( |
5467 ct = ( |
5458 # this is just a safe guard |
5468 # this is just a safe guard |
5459 self._encodeString("\n".join(callTips[:cv])) |
5469 self._encodeString("\n".join(callTips[:cv])) |
5460 if cv > 0 else |
5470 if cv > 0 |
|
5471 else |
5461 # until here and unindent below |
5472 # until here and unindent below |
5462 self._encodeString("\n".join(callTips)) |
5473 self._encodeString("\n".join(callTips)) |
5463 ) |
5474 ) |
5464 |
5475 |
5465 self.SendScintilla(QsciScintilla.SCI_CALLTIPSHOW, |
5476 self.SendScintilla( |
5466 self.__adjustedCallTipPosition(ctshift, pos), ct) |
5477 QsciScintilla.SCI_CALLTIPSHOW, |
5467 if b'\n' in ct: |
5478 self.__adjustedCallTipPosition(ctshift, pos), |
|
5479 ct, |
|
5480 ) |
|
5481 if b"\n" in ct: |
5468 return |
5482 return |
5469 |
5483 |
5470 # Highlight the current argument |
5484 # Highlight the current argument |
5471 if commas == 0: |
5485 if commas == 0: |
5472 astart = ct.find(b'(') |
5486 astart = ct.find(b"(") |
5473 else: |
5487 else: |
5474 astart = ct.find(b',') |
5488 astart = ct.find(b",") |
5475 commas -= 1 |
5489 commas -= 1 |
5476 while astart != -1 and commas > 0: |
5490 while astart != -1 and commas > 0: |
5477 astart = ct.find(b',', astart + 1) |
5491 astart = ct.find(b",", astart + 1) |
5478 commas -= 1 |
5492 commas -= 1 |
5479 |
5493 |
5480 if astart == -1: |
5494 if astart == -1: |
5481 return |
5495 return |
5482 |
5496 |
5483 depth = 0 |
5497 depth = 0 |
5484 for aend in range(astart + 1, len(ct)): |
5498 for aend in range(astart + 1, len(ct)): |
5485 ch = ct[aend:aend + 1] |
5499 ch = ct[aend : aend + 1] |
5486 |
5500 |
5487 if ch == b',' and depth == 0: |
5501 if ch == b"," and depth == 0: |
5488 break |
5502 break |
5489 elif ch == b'(': |
5503 elif ch == b"(": |
5490 depth += 1 |
5504 depth += 1 |
5491 elif ch == b')': |
5505 elif ch == b")": |
5492 if depth == 0: |
5506 if depth == 0: |
5493 break |
5507 break |
5494 |
5508 |
5495 depth -= 1 |
5509 depth -= 1 |
5496 |
5510 |
5497 if astart != aend: |
5511 if astart != aend: |
5498 self.SendScintilla(QsciScintilla.SCI_CALLTIPSETHLT, |
5512 self.SendScintilla(QsciScintilla.SCI_CALLTIPSETHLT, astart + 1, aend) |
5499 astart + 1, aend) |
5513 |
5500 |
|
5501 def __adjustedCallTipPosition(self, ctshift, pos): |
5514 def __adjustedCallTipPosition(self, ctshift, pos): |
5502 """ |
5515 """ |
5503 Private method to calculate an adjusted position for showing calltips. |
5516 Private method to calculate an adjusted position for showing calltips. |
5504 |
5517 |
5505 @param ctshift amount the calltip shall be shifted (integer) |
5518 @param ctshift amount the calltip shall be shifted (integer) |
5506 @param pos position into the text (integer) |
5519 @param pos position into the text (integer) |
5507 @return new position for the calltip (integer) |
5520 @return new position for the calltip (integer) |
5508 """ |
5521 """ |
5509 ct = pos |
5522 ct = pos |
5510 if ctshift: |
5523 if ctshift: |
5511 ctmin = self.SendScintilla( |
5524 ctmin = self.SendScintilla( |
5512 QsciScintilla.SCI_POSITIONFROMLINE, |
5525 QsciScintilla.SCI_POSITIONFROMLINE, |
5513 self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, ct)) |
5526 self.SendScintilla(QsciScintilla.SCI_LINEFROMPOSITION, ct), |
|
5527 ) |
5514 if ct - ctshift < ctmin: |
5528 if ct - ctshift < ctmin: |
5515 ct = ctmin |
5529 ct = ctmin |
5516 else: |
5530 else: |
5517 ct -= ctshift |
5531 ct -= ctshift |
5518 return ct |
5532 return ct |
5519 |
5533 |
5520 ################################################################# |
5534 ################################################################# |
5521 ## Methods needed by the code documentation viewer |
5535 ## Methods needed by the code documentation viewer |
5522 ################################################################# |
5536 ################################################################# |
5523 |
5537 |
5524 def __showCodeInfo(self): |
5538 def __showCodeInfo(self): |
5525 """ |
5539 """ |
5526 Private slot to handle the context menu action to show code info. |
5540 Private slot to handle the context menu action to show code info. |
5527 """ |
5541 """ |
5528 self.vm.showEditorInfo(self) |
5542 self.vm.showEditorInfo(self) |
5529 |
5543 |
5530 ################################################################# |
5544 ################################################################# |
5531 ## Methods needed by the context menu |
5545 ## Methods needed by the context menu |
5532 ################################################################# |
5546 ################################################################# |
5533 |
5547 |
5534 def __marginNumber(self, xPos): |
5548 def __marginNumber(self, xPos): |
5535 """ |
5549 """ |
5536 Private method to calculate the margin number based on a x position. |
5550 Private method to calculate the margin number based on a x position. |
5537 |
5551 |
5538 @param xPos x position (integer) |
5552 @param xPos x position (integer) |
5539 @return margin number (integer, -1 for no margin) |
5553 @return margin number (integer, -1 for no margin) |
5540 """ |
5554 """ |
5541 width = 0 |
5555 width = 0 |
5542 for margin in range(5): |
5556 for margin in range(5): |
5543 width += self.marginWidth(margin) |
5557 width += self.marginWidth(margin) |
5544 if xPos <= width: |
5558 if xPos <= width: |
5545 return margin |
5559 return margin |
5546 return -1 |
5560 return -1 |
5547 |
5561 |
5548 def contextMenuEvent(self, evt): |
5562 def contextMenuEvent(self, evt): |
5549 """ |
5563 """ |
5550 Protected method implementing the context menu event. |
5564 Protected method implementing the context menu event. |
5551 |
5565 |
5552 @param evt the context menu event (QContextMenuEvent) |
5566 @param evt the context menu event (QContextMenuEvent) |
5553 """ |
5567 """ |
5554 evt.accept() |
5568 evt.accept() |
5555 if self.__marginNumber(evt.x()) == -1: |
5569 if self.__marginNumber(evt.x()) == -1: |
5556 self.spellingMenuPos = self.positionFromPoint(evt.pos()) |
5570 self.spellingMenuPos = self.positionFromPoint(evt.pos()) |
5557 if ( |
5571 if ( |
5558 self.spellingMenuPos >= 0 and |
5572 self.spellingMenuPos >= 0 |
5559 self.spell is not None and |
5573 and self.spell is not None |
5560 self.hasIndicator(self.spellingIndicator, |
5574 and self.hasIndicator(self.spellingIndicator, self.spellingMenuPos) |
5561 self.spellingMenuPos) |
|
5562 ): |
5575 ): |
5563 self.spellingMenu.popup(evt.globalPos()) |
5576 self.spellingMenu.popup(evt.globalPos()) |
5564 else: |
5577 else: |
5565 self.menu.popup(evt.globalPos()) |
5578 self.menu.popup(evt.globalPos()) |
5566 else: |
5579 else: |
5567 self.line = self.lineAt(evt.pos()) |
5580 self.line = self.lineAt(evt.pos()) |
5568 if self.__marginNumber(evt.x()) in [self.__bmMargin, |
5581 if self.__marginNumber(evt.x()) in [self.__bmMargin, self.__linenoMargin]: |
5569 self.__linenoMargin]: |
|
5570 self.bmMarginMenu.popup(evt.globalPos()) |
5582 self.bmMarginMenu.popup(evt.globalPos()) |
5571 elif self.__marginNumber(evt.x()) == self.__bpMargin: |
5583 elif self.__marginNumber(evt.x()) == self.__bpMargin: |
5572 self.bpMarginMenu.popup(evt.globalPos()) |
5584 self.bpMarginMenu.popup(evt.globalPos()) |
5573 elif self.__marginNumber(evt.x()) == self.__indicMargin: |
5585 elif self.__marginNumber(evt.x()) == self.__indicMargin: |
5574 self.indicMarginMenu.popup(evt.globalPos()) |
5586 self.indicMarginMenu.popup(evt.globalPos()) |
5575 elif self.__marginNumber(evt.x()) == self.__foldMargin: |
5587 elif self.__marginNumber(evt.x()) == self.__foldMargin: |
5576 self.foldMarginMenu.popup(evt.globalPos()) |
5588 self.foldMarginMenu.popup(evt.globalPos()) |
5577 |
5589 |
5578 def __showContextMenu(self): |
5590 def __showContextMenu(self): |
5579 """ |
5591 """ |
5580 Private slot handling the aboutToShow signal of the context menu. |
5592 Private slot handling the aboutToShow signal of the context menu. |
5581 """ |
5593 """ |
5582 self.menuActs["Reopen"].setEnabled( |
5594 self.menuActs["Reopen"].setEnabled( |
5583 not self.isModified() and bool(self.fileName)) |
5595 not self.isModified() and bool(self.fileName) |
|
5596 ) |
5584 self.menuActs["Save"].setEnabled(self.isModified()) |
5597 self.menuActs["Save"].setEnabled(self.isModified()) |
5585 self.menuActs["Undo"].setEnabled(self.isUndoAvailable()) |
5598 self.menuActs["Undo"].setEnabled(self.isUndoAvailable()) |
5586 self.menuActs["Redo"].setEnabled(self.isRedoAvailable()) |
5599 self.menuActs["Redo"].setEnabled(self.isRedoAvailable()) |
5587 self.menuActs["Revert"].setEnabled(self.isModified()) |
5600 self.menuActs["Revert"].setEnabled(self.isModified()) |
5588 self.menuActs["Cut"].setEnabled(self.hasSelectedText()) |
5601 self.menuActs["Cut"].setEnabled(self.hasSelectedText()) |
5589 self.menuActs["Copy"].setEnabled(self.hasSelectedText()) |
5602 self.menuActs["Copy"].setEnabled(self.hasSelectedText()) |
5590 if self.menuActs["ExecuteSelection"] is not None: |
5603 if self.menuActs["ExecuteSelection"] is not None: |
5591 self.menuActs["ExecuteSelection"].setEnabled( |
5604 self.menuActs["ExecuteSelection"].setEnabled(self.hasSelectedText()) |
5592 self.hasSelectedText()) |
|
5593 self.menuActs["Paste"].setEnabled(self.canPaste()) |
5605 self.menuActs["Paste"].setEnabled(self.canPaste()) |
5594 if not self.isResourcesFile: |
5606 if not self.isResourcesFile: |
5595 if self.fileName and self.isPyFile(): |
5607 if self.fileName and self.isPyFile(): |
5596 self.menuActs["Show"].setEnabled(True) |
5608 self.menuActs["Show"].setEnabled(True) |
5597 else: |
5609 else: |
5598 self.menuActs["Show"].setEnabled(False) |
5610 self.menuActs["Show"].setEnabled(False) |
5599 if ( |
5611 if self.fileName and (self.isPyFile() or self.isRubyFile()): |
5600 self.fileName and |
|
5601 (self.isPyFile() or self.isRubyFile()) |
|
5602 ): |
|
5603 self.menuActs["Diagrams"].setEnabled(True) |
5612 self.menuActs["Diagrams"].setEnabled(True) |
5604 else: |
5613 else: |
5605 self.menuActs["Diagrams"].setEnabled(False) |
5614 self.menuActs["Diagrams"].setEnabled(False) |
5606 if not self.miniMenu: |
5615 if not self.miniMenu: |
5607 if self.lexer_ is not None: |
5616 if self.lexer_ is not None: |
5608 self.menuActs["Comment"].setEnabled( |
5617 self.menuActs["Comment"].setEnabled(self.lexer_.canBlockComment()) |
5609 self.lexer_.canBlockComment()) |
5618 self.menuActs["Uncomment"].setEnabled(self.lexer_.canBlockComment()) |
5610 self.menuActs["Uncomment"].setEnabled( |
|
5611 self.lexer_.canBlockComment()) |
|
5612 else: |
5619 else: |
5613 self.menuActs["Comment"].setEnabled(False) |
5620 self.menuActs["Comment"].setEnabled(False) |
5614 self.menuActs["Uncomment"].setEnabled(False) |
5621 self.menuActs["Uncomment"].setEnabled(False) |
5615 |
5622 |
5616 cline = self.getCursorPosition()[0] |
5623 cline = self.getCursorPosition()[0] |
5617 line = self.text(cline) |
5624 line = self.text(cline) |
5618 self.menuActs["Docstring"].setEnabled( |
5625 self.menuActs["Docstring"].setEnabled( |
5619 self.getDocstringGenerator().isFunctionStart(line)) |
5626 self.getDocstringGenerator().isFunctionStart(line) |
5620 |
5627 ) |
5621 self.menuActs["TypingAidsEnabled"].setEnabled( |
5628 |
5622 self.completer is not None) |
5629 self.menuActs["TypingAidsEnabled"].setEnabled(self.completer is not None) |
5623 self.menuActs["TypingAidsEnabled"].setChecked( |
5630 self.menuActs["TypingAidsEnabled"].setChecked( |
5624 self.completer is not None and self.completer.isEnabled()) |
5631 self.completer is not None and self.completer.isEnabled() |
5625 |
5632 ) |
|
5633 |
5626 if not self.isResourcesFile: |
5634 if not self.isResourcesFile: |
5627 self.menuActs["calltip"].setEnabled(self.canProvideCallTipps()) |
5635 self.menuActs["calltip"].setEnabled(self.canProvideCallTipps()) |
5628 self.menuActs["codeInfo"].setEnabled( |
5636 self.menuActs["codeInfo"].setEnabled( |
5629 self.vm.isEditorInfoSupported(self.getLanguage())) |
5637 self.vm.isEditorInfoSupported(self.getLanguage()) |
5630 |
5638 ) |
|
5639 |
5631 self.menuActs["MonospacedFont"].setEnabled(self.lexer_ is None) |
5640 self.menuActs["MonospacedFont"].setEnabled(self.lexer_ is None) |
5632 |
5641 |
5633 splitOrientation = self.vm.getSplitOrientation() |
5642 splitOrientation = self.vm.getSplitOrientation() |
5634 if splitOrientation == Qt.Orientation.Horizontal: |
5643 if splitOrientation == Qt.Orientation.Horizontal: |
5635 self.menuActs["NewSplit"].setIcon( |
5644 self.menuActs["NewSplit"].setIcon(UI.PixmapCache.getIcon("splitHorizontal")) |
5636 UI.PixmapCache.getIcon("splitHorizontal")) |
5645 else: |
5637 else: |
5646 self.menuActs["NewSplit"].setIcon(UI.PixmapCache.getIcon("splitVertical")) |
5638 self.menuActs["NewSplit"].setIcon( |
5647 |
5639 UI.PixmapCache.getIcon("splitVertical")) |
|
5640 |
|
5641 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty()) |
5648 self.menuActs["Tools"].setEnabled(not self.toolsMenu.isEmpty()) |
5642 |
5649 |
5643 self.showMenu.emit("Main", self.menu, self) |
5650 self.showMenu.emit("Main", self.menu, self) |
5644 |
5651 |
5645 def __showContextMenuAutocompletion(self): |
5652 def __showContextMenuAutocompletion(self): |
5646 """ |
5653 """ |
5647 Private slot called before the autocompletion menu is shown. |
5654 Private slot called before the autocompletion menu is shown. |
5648 """ |
5655 """ |
5649 self.menuActs["acDynamic"].setEnabled( |
5656 self.menuActs["acDynamic"].setEnabled(self.canProvideDynamicAutoCompletion()) |
5650 self.canProvideDynamicAutoCompletion()) |
5657 self.menuActs["acClearCache"].setEnabled(self.canProvideDynamicAutoCompletion()) |
5651 self.menuActs["acClearCache"].setEnabled( |
|
5652 self.canProvideDynamicAutoCompletion()) |
|
5653 self.menuActs["acAPI"].setEnabled(self.acAPI) |
5658 self.menuActs["acAPI"].setEnabled(self.acAPI) |
5654 self.menuActs["acAPIDocument"].setEnabled(self.acAPI) |
5659 self.menuActs["acAPIDocument"].setEnabled(self.acAPI) |
5655 |
5660 |
5656 self.showMenu.emit("Autocompletion", self.autocompletionMenu, self) |
5661 self.showMenu.emit("Autocompletion", self.autocompletionMenu, self) |
5657 |
5662 |
5658 def __showContextMenuShow(self): |
5663 def __showContextMenuShow(self): |
5659 """ |
5664 """ |
5660 Private slot called before the show menu is shown. |
5665 Private slot called before the show menu is shown. |
5661 """ |
5666 """ |
5662 prEnable = False |
5667 prEnable = False |
5663 coEnable = False |
5668 coEnable = False |
5664 |
5669 |
5665 # first check if the file belongs to a project |
5670 # first check if the file belongs to a project |
5666 if ( |
5671 if self.project.isOpen() and self.project.isProjectSource(self.fileName): |
5667 self.project.isOpen() and |
|
5668 self.project.isProjectSource(self.fileName) |
|
5669 ): |
|
5670 fn = self.project.getMainScript(True) |
5672 fn = self.project.getMainScript(True) |
5671 if fn is not None: |
5673 if fn is not None: |
5672 prEnable = ( |
5674 prEnable = self.project.isPy3Project() and bool( |
5673 self.project.isPy3Project() and |
5675 Utilities.getProfileFileNames(fn) |
5674 bool(Utilities.getProfileFileNames(fn)) |
|
5675 ) |
5676 ) |
5676 coEnable = ( |
5677 coEnable = self.project.isPy3Project() and bool( |
5677 self.project.isPy3Project() and |
5678 Utilities.getCoverageFileNames(fn) |
5678 bool(Utilities.getCoverageFileNames(fn)) |
|
5679 ) |
5679 ) |
5680 |
5680 |
5681 # now check ourselves |
5681 # now check ourselves |
5682 fn = self.getFileName() |
5682 fn = self.getFileName() |
5683 if fn is not None: |
5683 if fn is not None: |
5684 prEnable |= ( |
5684 prEnable |= self.project.isPy3Project() and bool( |
5685 self.project.isPy3Project() and |
5685 Utilities.getProfileFileName(fn) |
5686 bool(Utilities.getProfileFileName(fn)) |
5686 ) |
5687 ) |
5687 coEnable |= self.project.isPy3Project() and bool( |
5688 coEnable |= ( |
5688 Utilities.getCoverageFileName(fn) |
5689 self.project.isPy3Project() and |
5689 ) |
5690 bool(Utilities.getCoverageFileName(fn)) |
5690 |
5691 ) |
|
5692 |
|
5693 coEnable |= bool(self.__coverageFile) |
5691 coEnable |= bool(self.__coverageFile) |
5694 |
5692 |
5695 # now check for syntax errors |
5693 # now check for syntax errors |
5696 if self.hasSyntaxErrors(): |
5694 if self.hasSyntaxErrors(): |
5697 coEnable = False |
5695 coEnable = False |
5698 |
5696 |
5699 self.profileMenuAct.setEnabled(prEnable) |
5697 self.profileMenuAct.setEnabled(prEnable) |
5700 self.coverageMenuAct.setEnabled(coEnable) |
5698 self.coverageMenuAct.setEnabled(coEnable) |
5701 self.coverageShowAnnotationMenuAct.setEnabled( |
5699 self.coverageShowAnnotationMenuAct.setEnabled( |
5702 coEnable and len(self.notcoveredMarkers) == 0) |
5700 coEnable and len(self.notcoveredMarkers) == 0 |
5703 self.coverageHideAnnotationMenuAct.setEnabled( |
5701 ) |
5704 len(self.notcoveredMarkers) > 0) |
5702 self.coverageHideAnnotationMenuAct.setEnabled(len(self.notcoveredMarkers) > 0) |
5705 |
5703 |
5706 self.showMenu.emit("Show", self.menuShow, self) |
5704 self.showMenu.emit("Show", self.menuShow, self) |
5707 |
5705 |
5708 def __showContextMenuGraphics(self): |
5706 def __showContextMenuGraphics(self): |
5709 """ |
5707 """ |
5710 Private slot handling the aboutToShow signal of the diagrams context |
5708 Private slot handling the aboutToShow signal of the diagrams context |
5711 menu. |
5709 menu. |
5712 """ |
5710 """ |
5713 if ( |
5711 if self.project.isOpen() and self.project.isProjectSource(self.fileName): |
5714 self.project.isOpen() and |
|
5715 self.project.isProjectSource(self.fileName) |
|
5716 ): |
|
5717 self.applicationDiagramMenuAct.setEnabled(True) |
5712 self.applicationDiagramMenuAct.setEnabled(True) |
5718 else: |
5713 else: |
5719 self.applicationDiagramMenuAct.setEnabled(False) |
5714 self.applicationDiagramMenuAct.setEnabled(False) |
5720 |
5715 |
5721 self.showMenu.emit("Graphics", self.graphicsMenu, self) |
5716 self.showMenu.emit("Graphics", self.graphicsMenu, self) |
5722 |
5717 |
5723 def __showContextMenuMargin(self, menu): |
5718 def __showContextMenuMargin(self, menu): |
5724 """ |
5719 """ |
5725 Private slot handling the aboutToShow signal of the margins context |
5720 Private slot handling the aboutToShow signal of the margins context |
5726 menu. |
5721 menu. |
5727 |
5722 |
5728 @param menu reference to the menu to be shown |
5723 @param menu reference to the menu to be shown |
5729 @type QMenu |
5724 @type QMenu |
5730 """ |
5725 """ |
5731 if menu is self.bpMarginMenu: |
5726 if menu is self.bpMarginMenu: |
5732 supportsDebugger = bool(self.fileName and self.isPyFile()) |
5727 supportsDebugger = bool(self.fileName and self.isPyFile()) |
5733 hasBreakpoints = bool(self.breaks) |
5728 hasBreakpoints = bool(self.breaks) |
5734 hasBreakpoint = bool( |
5729 hasBreakpoint = bool(self.markersAtLine(self.line) & self.breakpointMask) |
5735 self.markersAtLine(self.line) & self.breakpointMask) |
5730 |
5736 |
|
5737 self.marginMenuActs["Breakpoint"].setEnabled(supportsDebugger) |
5731 self.marginMenuActs["Breakpoint"].setEnabled(supportsDebugger) |
5738 self.marginMenuActs["TempBreakpoint"].setEnabled(supportsDebugger) |
5732 self.marginMenuActs["TempBreakpoint"].setEnabled(supportsDebugger) |
5739 self.marginMenuActs["NextBreakpoint"].setEnabled( |
5733 self.marginMenuActs["NextBreakpoint"].setEnabled( |
5740 supportsDebugger and hasBreakpoints) |
5734 supportsDebugger and hasBreakpoints |
|
5735 ) |
5741 self.marginMenuActs["PreviousBreakpoint"].setEnabled( |
5736 self.marginMenuActs["PreviousBreakpoint"].setEnabled( |
5742 supportsDebugger and hasBreakpoints) |
5737 supportsDebugger and hasBreakpoints |
|
5738 ) |
5743 self.marginMenuActs["ClearBreakpoint"].setEnabled( |
5739 self.marginMenuActs["ClearBreakpoint"].setEnabled( |
5744 supportsDebugger and hasBreakpoints) |
5740 supportsDebugger and hasBreakpoints |
|
5741 ) |
5745 self.marginMenuActs["EditBreakpoint"].setEnabled( |
5742 self.marginMenuActs["EditBreakpoint"].setEnabled( |
5746 supportsDebugger and hasBreakpoint) |
5743 supportsDebugger and hasBreakpoint |
|
5744 ) |
5747 self.marginMenuActs["EnableBreakpoint"].setEnabled( |
5745 self.marginMenuActs["EnableBreakpoint"].setEnabled( |
5748 supportsDebugger and hasBreakpoint) |
5746 supportsDebugger and hasBreakpoint |
|
5747 ) |
5749 if supportsDebugger: |
5748 if supportsDebugger: |
5750 if self.markersAtLine(self.line) & (1 << self.dbreakpoint): |
5749 if self.markersAtLine(self.line) & (1 << self.dbreakpoint): |
5751 self.marginMenuActs["EnableBreakpoint"].setText( |
5750 self.marginMenuActs["EnableBreakpoint"].setText( |
5752 self.tr('Enable breakpoint')) |
5751 self.tr("Enable breakpoint") |
|
5752 ) |
5753 else: |
5753 else: |
5754 self.marginMenuActs["EnableBreakpoint"].setText( |
5754 self.marginMenuActs["EnableBreakpoint"].setText( |
5755 self.tr('Disable breakpoint')) |
5755 self.tr("Disable breakpoint") |
5756 |
5756 ) |
|
5757 |
5757 if menu is self.bmMarginMenu: |
5758 if menu is self.bmMarginMenu: |
5758 hasBookmarks = bool(self.bookmarks) |
5759 hasBookmarks = bool(self.bookmarks) |
5759 |
5760 |
5760 self.marginMenuActs["NextBookmark"].setEnabled(hasBookmarks) |
5761 self.marginMenuActs["NextBookmark"].setEnabled(hasBookmarks) |
5761 self.marginMenuActs["PreviousBookmark"].setEnabled(hasBookmarks) |
5762 self.marginMenuActs["PreviousBookmark"].setEnabled(hasBookmarks) |
5762 self.marginMenuActs["ClearBookmark"].setEnabled(hasBookmarks) |
5763 self.marginMenuActs["ClearBookmark"].setEnabled(hasBookmarks) |
5763 |
5764 |
5764 if menu is self.foldMarginMenu: |
5765 if menu is self.foldMarginMenu: |
5765 isFoldHeader = bool(self.SendScintilla( |
5766 isFoldHeader = bool( |
5766 QsciScintilla.SCI_GETFOLDLEVEL, self.line) & |
5767 self.SendScintilla(QsciScintilla.SCI_GETFOLDLEVEL, self.line) |
5767 QsciScintilla.SC_FOLDLEVELHEADERFLAG) |
5768 & QsciScintilla.SC_FOLDLEVELHEADERFLAG |
5768 |
5769 ) |
|
5770 |
5769 self.marginMenuActs["ExpandChildren"].setEnabled(isFoldHeader) |
5771 self.marginMenuActs["ExpandChildren"].setEnabled(isFoldHeader) |
5770 self.marginMenuActs["CollapseChildren"].setEnabled(isFoldHeader) |
5772 self.marginMenuActs["CollapseChildren"].setEnabled(isFoldHeader) |
5771 |
5773 |
5772 if menu is self.indicMarginMenu: |
5774 if menu is self.indicMarginMenu: |
5773 hasSyntaxErrors = bool(self.syntaxerrors) |
5775 hasSyntaxErrors = bool(self.syntaxerrors) |
5774 hasWarnings = bool(self.warnings) |
5776 hasWarnings = bool(self.warnings) |
5775 hasNotCoveredMarkers = bool(self.notcoveredMarkers) |
5777 hasNotCoveredMarkers = bool(self.notcoveredMarkers) |
5776 |
5778 |
5777 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors) |
5779 self.marginMenuActs["GotoSyntaxError"].setEnabled(hasSyntaxErrors) |
5778 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors) |
5780 self.marginMenuActs["ClearSyntaxError"].setEnabled(hasSyntaxErrors) |
5779 if ( |
5781 if hasSyntaxErrors and self.markersAtLine(self.line) & ( |
5780 hasSyntaxErrors and |
5782 1 << self.syntaxerror |
5781 self.markersAtLine(self.line) & (1 << self.syntaxerror) |
|
5782 ): |
5783 ): |
5783 self.marginMenuActs["ShowSyntaxError"].setEnabled(True) |
5784 self.marginMenuActs["ShowSyntaxError"].setEnabled(True) |
5784 else: |
5785 else: |
5785 self.marginMenuActs["ShowSyntaxError"].setEnabled(False) |
5786 self.marginMenuActs["ShowSyntaxError"].setEnabled(False) |
5786 |
5787 |
5787 self.marginMenuActs["NextWarningMarker"].setEnabled(hasWarnings) |
5788 self.marginMenuActs["NextWarningMarker"].setEnabled(hasWarnings) |
5788 self.marginMenuActs["PreviousWarningMarker"].setEnabled( |
5789 self.marginMenuActs["PreviousWarningMarker"].setEnabled(hasWarnings) |
5789 hasWarnings) |
|
5790 self.marginMenuActs["ClearWarnings"].setEnabled(hasWarnings) |
5790 self.marginMenuActs["ClearWarnings"].setEnabled(hasWarnings) |
5791 if ( |
5791 if hasWarnings and self.markersAtLine(self.line) & (1 << self.warning): |
5792 hasWarnings and |
|
5793 self.markersAtLine(self.line) & (1 << self.warning) |
|
5794 ): |
|
5795 self.marginMenuActs["ShowWarning"].setEnabled(True) |
5792 self.marginMenuActs["ShowWarning"].setEnabled(True) |
5796 else: |
5793 else: |
5797 self.marginMenuActs["ShowWarning"].setEnabled(False) |
5794 self.marginMenuActs["ShowWarning"].setEnabled(False) |
5798 |
5795 |
5799 self.marginMenuActs["NextCoverageMarker"].setEnabled( |
5796 self.marginMenuActs["NextCoverageMarker"].setEnabled(hasNotCoveredMarkers) |
5800 hasNotCoveredMarkers) |
|
5801 self.marginMenuActs["PreviousCoverageMarker"].setEnabled( |
5797 self.marginMenuActs["PreviousCoverageMarker"].setEnabled( |
5802 hasNotCoveredMarkers) |
5798 hasNotCoveredMarkers |
5803 |
5799 ) |
5804 self.marginMenuActs["PreviousTaskMarker"].setEnabled( |
5800 |
5805 self.__hasTaskMarkers) |
5801 self.marginMenuActs["PreviousTaskMarker"].setEnabled(self.__hasTaskMarkers) |
5806 self.marginMenuActs["NextTaskMarker"].setEnabled( |
5802 self.marginMenuActs["NextTaskMarker"].setEnabled(self.__hasTaskMarkers) |
5807 self.__hasTaskMarkers) |
5803 |
5808 |
|
5809 self.marginMenuActs["PreviousChangeMarker"].setEnabled( |
5804 self.marginMenuActs["PreviousChangeMarker"].setEnabled( |
5810 self.__hasChangeMarkers) |
5805 self.__hasChangeMarkers |
5811 self.marginMenuActs["NextChangeMarker"].setEnabled( |
5806 ) |
5812 self.__hasChangeMarkers) |
5807 self.marginMenuActs["NextChangeMarker"].setEnabled(self.__hasChangeMarkers) |
5813 self.marginMenuActs["ClearChangeMarkers"].setEnabled( |
5808 self.marginMenuActs["ClearChangeMarkers"].setEnabled( |
5814 self.__hasChangeMarkers) |
5809 self.__hasChangeMarkers |
5815 |
5810 ) |
|
5811 |
5816 self.showMenu.emit("Margin", menu, self) |
5812 self.showMenu.emit("Margin", menu, self) |
5817 |
5813 |
5818 def __showContextMenuChecks(self): |
5814 def __showContextMenuChecks(self): |
5819 """ |
5815 """ |
5820 Private slot handling the aboutToShow signal of the checks context |
5816 Private slot handling the aboutToShow signal of the checks context |
5821 menu. |
5817 menu. |
5822 """ |
5818 """ |
5823 self.showMenu.emit("Checks", self.checksMenu, self) |
5819 self.showMenu.emit("Checks", self.checksMenu, self) |
5824 |
5820 |
5825 def __showContextMenuTools(self): |
5821 def __showContextMenuTools(self): |
5826 """ |
5822 """ |
5827 Private slot handling the aboutToShow signal of the tools context |
5823 Private slot handling the aboutToShow signal of the tools context |
5828 menu. |
5824 menu. |
5829 """ |
5825 """ |
5830 self.showMenu.emit("Tools", self.toolsMenu, self) |
5826 self.showMenu.emit("Tools", self.toolsMenu, self) |
5831 |
5827 |
5832 def __showContextMenuFormatting(self): |
5828 def __showContextMenuFormatting(self): |
5833 """ |
5829 """ |
5834 Private slot handling the aboutToShow signal of the code formatting context |
5830 Private slot handling the aboutToShow signal of the code formatting context |
5835 menu. |
5831 menu. |
5836 """ |
5832 """ |
5837 self.showMenu.emit("Formatting", self.codeFormattingMenu, self) |
5833 self.showMenu.emit("Formatting", self.codeFormattingMenu, self) |
5838 |
5834 |
5839 def __reopenWithEncodingMenuTriggered(self, act): |
5835 def __reopenWithEncodingMenuTriggered(self, act): |
5840 """ |
5836 """ |
5841 Private method to handle the rereading of the file with a selected |
5837 Private method to handle the rereading of the file with a selected |
5842 encoding. |
5838 encoding. |
5843 |
5839 |
5844 @param act reference to the action that was triggered (QAction) |
5840 @param act reference to the action that was triggered (QAction) |
5845 """ |
5841 """ |
5846 encoding = act.data() |
5842 encoding = act.data() |
5847 self.readFile(self.fileName, encoding=encoding) |
5843 self.readFile(self.fileName, encoding=encoding) |
5848 self.__convertTabs() |
5844 self.__convertTabs() |
5849 self.__checkEncoding() |
5845 self.__checkEncoding() |
5850 |
5846 |
5851 def __contextSave(self): |
5847 def __contextSave(self): |
5852 """ |
5848 """ |
5853 Private slot handling the save context menu entry. |
5849 Private slot handling the save context menu entry. |
5854 """ |
5850 """ |
5855 ok = self.saveFile() |
5851 ok = self.saveFile() |
5856 if ok: |
5852 if ok: |
5857 self.vm.setEditorName(self, self.fileName) |
5853 self.vm.setEditorName(self, self.fileName) |
5858 |
5854 |
5859 def __contextSaveAs(self): |
5855 def __contextSaveAs(self): |
5860 """ |
5856 """ |
5861 Private slot handling the save as context menu entry. |
5857 Private slot handling the save as context menu entry. |
5862 """ |
5858 """ |
5863 ok = self.saveFileAs() |
5859 ok = self.saveFileAs() |
5864 if ok: |
5860 if ok: |
5865 self.vm.setEditorName(self, self.fileName) |
5861 self.vm.setEditorName(self, self.fileName) |
5866 |
5862 |
5867 def __contextSaveCopy(self): |
5863 def __contextSaveCopy(self): |
5868 """ |
5864 """ |
5869 Private slot handling the save copy context menu entry. |
5865 Private slot handling the save copy context menu entry. |
5870 """ |
5866 """ |
5871 self.saveFileCopy() |
5867 self.saveFileCopy() |
5872 |
5868 |
5873 def __contextClose(self): |
5869 def __contextClose(self): |
5874 """ |
5870 """ |
5875 Private slot handling the close context menu entry. |
5871 Private slot handling the close context menu entry. |
5876 """ |
5872 """ |
5877 self.vm.closeEditor(self) |
5873 self.vm.closeEditor(self) |
5878 |
5874 |
5879 def __newView(self): |
5875 def __newView(self): |
5880 """ |
5876 """ |
5881 Private slot to create a new view to an open document. |
5877 Private slot to create a new view to an open document. |
5882 """ |
5878 """ |
5883 self.vm.newEditorView(self.fileName, self, self.filetype) |
5879 self.vm.newEditorView(self.fileName, self, self.filetype) |
5884 |
5880 |
5885 def __newViewNewSplit(self): |
5881 def __newViewNewSplit(self): |
5886 """ |
5882 """ |
5887 Private slot to create a new view to an open document. |
5883 Private slot to create a new view to an open document. |
5888 """ |
5884 """ |
5889 self.vm.addSplit() |
5885 self.vm.addSplit() |
5890 self.vm.newEditorView(self.fileName, self, self.filetype) |
5886 self.vm.newEditorView(self.fileName, self, self.filetype) |
5891 |
5887 |
5892 def __selectAll(self): |
5888 def __selectAll(self): |
5893 """ |
5889 """ |
5894 Private slot handling the select all context menu action. |
5890 Private slot handling the select all context menu action. |
5895 """ |
5891 """ |
5896 self.selectAll(True) |
5892 self.selectAll(True) |
5897 |
5893 |
5898 def __deselectAll(self): |
5894 def __deselectAll(self): |
5899 """ |
5895 """ |
5900 Private slot handling the deselect all context menu action. |
5896 Private slot handling the deselect all context menu action. |
5901 """ |
5897 """ |
5902 self.selectAll(False) |
5898 self.selectAll(False) |
5903 |
5899 |
5904 def joinLines(self): |
5900 def joinLines(self): |
5905 """ |
5901 """ |
5906 Public slot to join the current line with the next one. |
5902 Public slot to join the current line with the next one. |
5907 """ |
5903 """ |
5908 curLine = self.getCursorPosition()[0] |
5904 curLine = self.getCursorPosition()[0] |
5909 if curLine == self.lines() - 1: |
5905 if curLine == self.lines() - 1: |
5910 return |
5906 return |
5911 |
5907 |
5912 line0Text = self.text(curLine) |
5908 line0Text = self.text(curLine) |
5913 line1Text = self.text(curLine + 1) |
5909 line1Text = self.text(curLine + 1) |
5914 if line1Text in ["", "\r", "\n", "\r\n"]: |
5910 if line1Text in ["", "\r", "\n", "\r\n"]: |
5915 return |
5911 return |
5916 |
5912 |
5917 if ( |
5913 if line0Text.rstrip("\r\n\\ \t").endswith( |
5918 line0Text.rstrip("\r\n\\ \t").endswith(("'", '"')) and |
5914 ("'", '"') |
5919 line1Text.lstrip().startswith(("'", '"')) |
5915 ) and line1Text.lstrip().startswith(("'", '"')): |
5920 ): |
|
5921 # merging multi line strings |
5916 # merging multi line strings |
5922 startChars = "\r\n\\ \t'\"" |
5917 startChars = "\r\n\\ \t'\"" |
5923 endChars = " \t'\"" |
5918 endChars = " \t'\"" |
5924 else: |
5919 else: |
5925 startChars = "\r\n\\ \t" |
5920 startChars = "\r\n\\ \t" |
5926 endChars = " \t" |
5921 endChars = " \t" |
5927 |
5922 |
5928 # determine start index |
5923 # determine start index |
5929 startIndex = len(line0Text) |
5924 startIndex = len(line0Text) |
5930 while startIndex > 0 and line0Text[startIndex - 1] in startChars: |
5925 while startIndex > 0 and line0Text[startIndex - 1] in startChars: |
5931 startIndex -= 1 |
5926 startIndex -= 1 |
5932 if startIndex == 0: |
5927 if startIndex == 0: |
5933 return |
5928 return |
5934 |
5929 |
5935 # determine end index |
5930 # determine end index |
5936 endIndex = 0 |
5931 endIndex = 0 |
5937 while line1Text[endIndex] in endChars: |
5932 while line1Text[endIndex] in endChars: |
5938 endIndex += 1 |
5933 endIndex += 1 |
5939 |
5934 |
5940 self.setSelection(curLine, startIndex, curLine + 1, endIndex) |
5935 self.setSelection(curLine, startIndex, curLine + 1, endIndex) |
5941 self.beginUndoAction() |
5936 self.beginUndoAction() |
5942 self.removeSelectedText() |
5937 self.removeSelectedText() |
5943 self.insertAt(" ", curLine, startIndex) |
5938 self.insertAt(" ", curLine, startIndex) |
5944 self.endUndoAction() |
5939 self.endUndoAction() |
5945 |
5940 |
5946 def shortenEmptyLines(self): |
5941 def shortenEmptyLines(self): |
5947 """ |
5942 """ |
5948 Public slot to compress lines consisting solely of whitespace |
5943 Public slot to compress lines consisting solely of whitespace |
5949 characters. |
5944 characters. |
5950 """ |
5945 """ |
5951 searchRE = r"^[ \t]+$" |
5946 searchRE = r"^[ \t]+$" |
5952 |
5947 |
5953 ok = self.findFirstTarget(searchRE, True, False, False, 0, 0) |
5948 ok = self.findFirstTarget(searchRE, True, False, False, 0, 0) |
5954 self.beginUndoAction() |
5949 self.beginUndoAction() |
5955 while ok: |
5950 while ok: |
5956 self.replaceTarget("") |
5951 self.replaceTarget("") |
5957 ok = self.findNextTarget() |
5952 ok = self.findNextTarget() |
5958 self.endUndoAction() |
5953 self.endUndoAction() |
5959 |
5954 |
5960 def __autosaveEnable(self): |
5955 def __autosaveEnable(self): |
5961 """ |
5956 """ |
5962 Private slot handling the autosave enable context menu action. |
5957 Private slot handling the autosave enable context menu action. |
5963 """ |
5958 """ |
5964 if self.menuActs["AutosaveEnable"].isChecked(): |
5959 if self.menuActs["AutosaveEnable"].isChecked(): |
5965 self.autosaveManuallyDisabled = False |
5960 self.autosaveManuallyDisabled = False |
5966 else: |
5961 else: |
5967 self.autosaveManuallyDisabled = True |
5962 self.autosaveManuallyDisabled = True |
5968 |
5963 |
5969 def shouldAutosave(self): |
5964 def shouldAutosave(self): |
5970 """ |
5965 """ |
5971 Public slot to check the autosave flags. |
5966 Public slot to check the autosave flags. |
5972 |
5967 |
5973 @return flag indicating this editor should be saved (boolean) |
5968 @return flag indicating this editor should be saved (boolean) |
5974 """ |
5969 """ |
5975 return ( |
5970 return ( |
5976 bool(self.fileName) and |
5971 bool(self.fileName) |
5977 not self.autosaveManuallyDisabled and |
5972 and not self.autosaveManuallyDisabled |
5978 not self.isReadOnly() |
5973 and not self.isReadOnly() |
5979 ) |
5974 ) |
5980 |
5975 |
5981 def checkSyntax(self): |
5976 def checkSyntax(self): |
5982 """ |
5977 """ |
5983 Public method to perform an automatic syntax check of the file. |
5978 Public method to perform an automatic syntax check of the file. |
5984 """ |
5979 """ |
5985 fileType = self.filetype |
5980 fileType = self.filetype |
5986 if fileType == "MicroPython": |
5981 if fileType == "MicroPython": |
5987 # adjustment for MicroPython |
5982 # adjustment for MicroPython |
5988 fileType = "Python3" |
5983 fileType = "Python3" |
5989 |
5984 |
5990 if ( |
5985 if ( |
5991 self.syntaxCheckService is None or |
5986 self.syntaxCheckService is None |
5992 fileType not in self.syntaxCheckService.getLanguages() |
5987 or fileType not in self.syntaxCheckService.getLanguages() |
5993 ): |
5988 ): |
5994 return |
5989 return |
5995 |
5990 |
5996 if Preferences.getEditor("AutoCheckSyntax"): |
5991 if Preferences.getEditor("AutoCheckSyntax"): |
5997 if Preferences.getEditor("OnlineSyntaxCheck"): |
5992 if Preferences.getEditor("OnlineSyntaxCheck"): |
5998 self.__onlineSyntaxCheckTimer.stop() |
5993 self.__onlineSyntaxCheckTimer.stop() |
5999 |
5994 |
6000 self.syntaxCheckService.syntaxCheck( |
5995 self.syntaxCheckService.syntaxCheck( |
6001 fileType, self.fileName or "(Unnamed)", self.text()) |
5996 fileType, self.fileName or "(Unnamed)", self.text() |
|
5997 ) |
6002 |
5998 |
6003 def __processSyntaxCheckError(self, fn, msg): |
5999 def __processSyntaxCheckError(self, fn, msg): |
6004 """ |
6000 """ |
6005 Private slot to report an error message of a syntax check. |
6001 Private slot to report an error message of a syntax check. |
6006 |
6002 |
6007 @param fn filename of the file |
6003 @param fn filename of the file |
6008 @type str |
6004 @type str |
6009 @param msg error message |
6005 @param msg error message |
6010 @type str |
6006 @type str |
6011 """ |
6007 """ |
6012 if fn != self.fileName and ( |
6008 if fn != self.fileName and (bool(self.fileName) or fn != "(Unnamed)"): |
6013 bool(self.fileName) or fn != "(Unnamed)"): |
|
6014 return |
6009 return |
6015 |
6010 |
6016 self.clearSyntaxError() |
6011 self.clearSyntaxError() |
6017 self.clearFlakesWarnings() |
6012 self.clearFlakesWarnings() |
6018 |
6013 |
6019 self.toggleWarning(0, 0, True, msg) |
6014 self.toggleWarning(0, 0, True, msg) |
6020 |
6015 |
6021 self.updateVerticalScrollBar() |
6016 self.updateVerticalScrollBar() |
6022 |
6017 |
6023 def __processSyntaxCheckResult(self, fn, problems): |
6018 def __processSyntaxCheckResult(self, fn, problems): |
6024 """ |
6019 """ |
6025 Private slot to report the resulting messages of a syntax check. |
6020 Private slot to report the resulting messages of a syntax check. |
6026 |
6021 |
6027 @param fn filename of the checked file (str) |
6022 @param fn filename of the checked file (str) |
6028 @param problems dictionary with the keys 'error' and 'warnings' which |
6023 @param problems dictionary with the keys 'error' and 'warnings' which |
6029 hold a list containing details about the error/ warnings |
6024 hold a list containing details about the error/ warnings |
6030 (file name, line number, column, codestring (only at syntax |
6025 (file name, line number, column, codestring (only at syntax |
6031 errors), the message) (dict) |
6026 errors), the message) (dict) |
6032 """ |
6027 """ |
6033 # Check if it's the requested file, otherwise ignore signal |
6028 # Check if it's the requested file, otherwise ignore signal |
6034 if fn != self.fileName and ( |
6029 if fn != self.fileName and (bool(self.fileName) or fn != "(Unnamed)"): |
6035 bool(self.fileName) or fn != "(Unnamed)"): |
|
6036 return |
6030 return |
6037 |
6031 |
6038 self.clearSyntaxError() |
6032 self.clearSyntaxError() |
6039 self.clearFlakesWarnings() |
6033 self.clearFlakesWarnings() |
6040 |
6034 |
6041 error = problems.get('error') |
6035 error = problems.get("error") |
6042 if error: |
6036 if error: |
6043 _fn, lineno, col, code, msg = error |
6037 _fn, lineno, col, code, msg = error |
6044 self.toggleSyntaxError(lineno, col, True, msg) |
6038 self.toggleSyntaxError(lineno, col, True, msg) |
6045 |
6039 |
6046 warnings = problems.get('warnings', []) |
6040 warnings = problems.get("warnings", []) |
6047 for _fn, lineno, col, _code, msg in warnings: |
6041 for _fn, lineno, col, _code, msg in warnings: |
6048 self.toggleWarning(lineno, col, True, msg) |
6042 self.toggleWarning(lineno, col, True, msg) |
6049 |
6043 |
6050 self.updateVerticalScrollBar() |
6044 self.updateVerticalScrollBar() |
6051 |
6045 |
6052 def __initOnlineSyntaxCheck(self): |
6046 def __initOnlineSyntaxCheck(self): |
6053 """ |
6047 """ |
6054 Private slot to initialize the online syntax check. |
6048 Private slot to initialize the online syntax check. |
6055 """ |
6049 """ |
6056 self.__onlineSyntaxCheckTimer = QTimer(self) |
6050 self.__onlineSyntaxCheckTimer = QTimer(self) |
6057 self.__onlineSyntaxCheckTimer.setSingleShot(True) |
6051 self.__onlineSyntaxCheckTimer.setSingleShot(True) |
6058 self.__onlineSyntaxCheckTimer.setInterval( |
6052 self.__onlineSyntaxCheckTimer.setInterval( |
6059 Preferences.getEditor("OnlineSyntaxCheckInterval") * 1000) |
6053 Preferences.getEditor("OnlineSyntaxCheckInterval") * 1000 |
|
6054 ) |
6060 self.__onlineSyntaxCheckTimer.timeout.connect(self.checkSyntax) |
6055 self.__onlineSyntaxCheckTimer.timeout.connect(self.checkSyntax) |
6061 self.textChanged.connect(self.__resetOnlineSyntaxCheckTimer) |
6056 self.textChanged.connect(self.__resetOnlineSyntaxCheckTimer) |
6062 |
6057 |
6063 def __resetOnlineSyntaxCheckTimer(self): |
6058 def __resetOnlineSyntaxCheckTimer(self): |
6064 """ |
6059 """ |
6065 Private method to reset the online syntax check timer. |
6060 Private method to reset the online syntax check timer. |
6066 """ |
6061 """ |
6067 if Preferences.getEditor("OnlineSyntaxCheck"): |
6062 if Preferences.getEditor("OnlineSyntaxCheck"): |
6068 self.__onlineSyntaxCheckTimer.stop() |
6063 self.__onlineSyntaxCheckTimer.stop() |
6069 self.__onlineSyntaxCheckTimer.start() |
6064 self.__onlineSyntaxCheckTimer.start() |
6070 |
6065 |
6071 def __showCodeMetrics(self): |
6066 def __showCodeMetrics(self): |
6072 """ |
6067 """ |
6073 Private method to handle the code metrics context menu action. |
6068 Private method to handle the code metrics context menu action. |
6074 """ |
6069 """ |
6075 if not self.checkDirty(): |
6070 if not self.checkDirty(): |
6076 return |
6071 return |
6077 |
6072 |
6078 from DataViews.CodeMetricsDialog import CodeMetricsDialog |
6073 from DataViews.CodeMetricsDialog import CodeMetricsDialog |
|
6074 |
6079 self.codemetrics = CodeMetricsDialog() |
6075 self.codemetrics = CodeMetricsDialog() |
6080 self.codemetrics.show() |
6076 self.codemetrics.show() |
6081 self.codemetrics.start(self.fileName) |
6077 self.codemetrics.start(self.fileName) |
6082 |
6078 |
6083 def __getCodeCoverageFile(self): |
6079 def __getCodeCoverageFile(self): |
6084 """ |
6080 """ |
6085 Private method to get the file name of the file containing coverage |
6081 Private method to get the file name of the file containing coverage |
6086 info. |
6082 info. |
6087 |
6083 |
6088 @return file name of the coverage file |
6084 @return file name of the coverage file |
6089 @rtype str |
6085 @rtype str |
6090 """ |
6086 """ |
6091 files = set() |
6087 files = set() |
6092 |
6088 |
6093 if bool(self.__coverageFile): |
6089 if bool(self.__coverageFile): |
6094 # return the path of a previously used coverage file |
6090 # return the path of a previously used coverage file |
6095 return self.__coverageFile |
6091 return self.__coverageFile |
6096 |
6092 |
6097 # first check if the file belongs to a project and there is |
6093 # first check if the file belongs to a project and there is |
6098 # a project coverage file |
6094 # a project coverage file |
6099 if ( |
6095 if self.project.isOpen() and self.project.isProjectSource(self.fileName): |
6100 self.project.isOpen() and |
|
6101 self.project.isProjectSource(self.fileName) |
|
6102 ): |
|
6103 pfn = self.project.getMainScript(True) |
6096 pfn = self.project.getMainScript(True) |
6104 if pfn is not None: |
6097 if pfn is not None: |
6105 files |= set(Utilities.getCoverageFileNames(pfn)) |
6098 files |= set(Utilities.getCoverageFileNames(pfn)) |
6106 |
6099 |
6107 # now check, if there are coverage files belonging to ourselves |
6100 # now check, if there are coverage files belonging to ourselves |
6108 fn = self.getFileName() |
6101 fn = self.getFileName() |
6109 if fn is not None: |
6102 if fn is not None: |
6110 files |= set(Utilities.getCoverageFileNames(fn)) |
6103 files |= set(Utilities.getCoverageFileNames(fn)) |
6111 |
6104 |
6112 files = list(files) |
6105 files = list(files) |
6113 if files: |
6106 if files: |
6114 if len(files) > 1: |
6107 if len(files) > 1: |
6115 cfn, ok = QInputDialog.getItem( |
6108 cfn, ok = QInputDialog.getItem( |
6116 self, |
6109 self, |
6117 self.tr("Code Coverage"), |
6110 self.tr("Code Coverage"), |
6118 self.tr("Please select a coverage file"), |
6111 self.tr("Please select a coverage file"), |
6119 files, |
6112 files, |
6120 0, False) |
6113 0, |
|
6114 False, |
|
6115 ) |
6121 if not ok: |
6116 if not ok: |
6122 return "" |
6117 return "" |
6123 else: |
6118 else: |
6124 cfn = files[0] |
6119 cfn = files[0] |
6125 else: |
6120 else: |
6126 cfn = None |
6121 cfn = None |
6127 |
6122 |
6128 return cfn |
6123 return cfn |
6129 |
6124 |
6130 def __showCodeCoverage(self): |
6125 def __showCodeCoverage(self): |
6131 """ |
6126 """ |
6132 Private method to handle the code coverage context menu action. |
6127 Private method to handle the code coverage context menu action. |
6133 """ |
6128 """ |
6134 fn = self.__getCodeCoverageFile() |
6129 fn = self.__getCodeCoverageFile() |
6135 self.__coverageFile = fn |
6130 self.__coverageFile = fn |
6136 if fn: |
6131 if fn: |
6137 from DataViews.PyCoverageDialog import PyCoverageDialog |
6132 from DataViews.PyCoverageDialog import PyCoverageDialog |
|
6133 |
6138 self.codecoverage = PyCoverageDialog() |
6134 self.codecoverage = PyCoverageDialog() |
6139 self.codecoverage.show() |
6135 self.codecoverage.show() |
6140 self.codecoverage.start(fn, self.fileName) |
6136 self.codecoverage.start(fn, self.fileName) |
6141 |
6137 |
6142 def refreshCoverageAnnotations(self): |
6138 def refreshCoverageAnnotations(self): |
6143 """ |
6139 """ |
6144 Public method to refresh the code coverage annotations. |
6140 Public method to refresh the code coverage annotations. |
6145 """ |
6141 """ |
6146 if self.showingNotcoveredMarkers: |
6142 if self.showingNotcoveredMarkers: |
6147 self.codeCoverageShowAnnotations(silent=True) |
6143 self.codeCoverageShowAnnotations(silent=True) |
6148 |
6144 |
6149 def codeCoverageShowAnnotations(self, silent=False, coverageFile=None): |
6145 def codeCoverageShowAnnotations(self, silent=False, coverageFile=None): |
6150 """ |
6146 """ |
6151 Public method to handle the show code coverage annotations context |
6147 Public method to handle the show code coverage annotations context |
6152 menu action. |
6148 menu action. |
6153 |
6149 |
6154 @param silent flag indicating to not show any dialog (defaults to |
6150 @param silent flag indicating to not show any dialog (defaults to |
6155 False) |
6151 False) |
6156 @type bool (optional) |
6152 @type bool (optional) |
6157 @param coverageFile path of the file containing the code coverage data |
6153 @param coverageFile path of the file containing the code coverage data |
6158 (defaults to None) |
6154 (defaults to None) |
6159 @type str (optional) |
6155 @type str (optional) |
6160 """ |
6156 """ |
6161 self.__codeCoverageHideAnnotations() |
6157 self.__codeCoverageHideAnnotations() |
6162 |
6158 |
6163 fn = ( |
6159 fn = coverageFile if bool(coverageFile) else self.__getCodeCoverageFile() |
6164 coverageFile |
|
6165 if bool(coverageFile) else |
|
6166 self.__getCodeCoverageFile() |
|
6167 ) |
|
6168 self.__coverageFile = fn |
6160 self.__coverageFile = fn |
6169 |
6161 |
6170 if fn: |
6162 if fn: |
6171 from coverage import Coverage |
6163 from coverage import Coverage |
|
6164 |
6172 cover = Coverage(data_file=fn) |
6165 cover = Coverage(data_file=fn) |
6173 cover.load() |
6166 cover.load() |
6174 missing = cover.analysis2(self.fileName)[3] |
6167 missing = cover.analysis2(self.fileName)[3] |
6175 if missing: |
6168 if missing: |
6176 for line in missing: |
6169 for line in missing: |
6641 self.__setAnnotation(self.markerLine(handle)) |
6634 self.__setAnnotation(self.markerLine(handle)) |
6642 self.markerDeleteHandle(handle) |
6635 self.markerDeleteHandle(handle) |
6643 self.warnings.clear() |
6636 self.warnings.clear() |
6644 self.syntaxerrorToggled.emit(self) |
6637 self.syntaxerrorToggled.emit(self) |
6645 self.__markerMap.update() |
6638 self.__markerMap.update() |
6646 |
6639 |
6647 def __showWarning(self, line=-1): |
6640 def __showWarning(self, line=-1): |
6648 """ |
6641 """ |
6649 Private slot to handle the 'Show warning' context menu action. |
6642 Private slot to handle the 'Show warning' context menu action. |
6650 |
6643 |
6651 @param line line number to show the warning for (integer) |
6644 @param line line number to show the warning for (integer) |
6652 """ |
6645 """ |
6653 if line == -1: |
6646 if line == -1: |
6654 line = self.line |
6647 line = self.line |
6655 |
6648 |
6656 for handle in list(self.warnings.keys()): |
6649 for handle in list(self.warnings.keys()): |
6657 if self.markerLine(handle) == line: |
6650 if self.markerLine(handle) == line: |
6658 EricMessageBox.warning( |
6651 EricMessageBox.warning( |
6659 self, |
6652 self, |
6660 self.tr("Warning"), |
6653 self.tr("Warning"), |
6661 '\n'.join([w[0] for w in self.warnings[handle]])) |
6654 "\n".join([w[0] for w in self.warnings[handle]]), |
|
6655 ) |
6662 break |
6656 break |
6663 else: |
6657 else: |
6664 EricMessageBox.warning( |
6658 EricMessageBox.warning( |
6665 self, |
6659 self, self.tr("Warning"), self.tr("No warning messages available.") |
6666 self.tr("Warning"), |
6660 ) |
6667 self.tr("No warning messages available.")) |
6661 |
6668 |
|
6669 ########################################################################### |
6662 ########################################################################### |
6670 ## Annotation handling methods below |
6663 ## Annotation handling methods below |
6671 ########################################################################### |
6664 ########################################################################### |
6672 |
6665 |
6673 def __setAnnotationStyles(self): |
6666 def __setAnnotationStyles(self): |
6674 """ |
6667 """ |
6675 Private slot to define the style used by inline annotations. |
6668 Private slot to define the style used by inline annotations. |
6676 """ |
6669 """ |
6677 if hasattr(QsciScintilla, "annotate"): |
6670 if hasattr(QsciScintilla, "annotate"): |
6678 self.annotationWarningStyle = ( |
6671 self.annotationWarningStyle = QsciScintilla.STYLE_LASTPREDEFINED + 1 |
6679 QsciScintilla.STYLE_LASTPREDEFINED + 1 |
|
6680 ) |
|
6681 self.SendScintilla( |
6672 self.SendScintilla( |
6682 QsciScintilla.SCI_STYLESETFORE, |
6673 QsciScintilla.SCI_STYLESETFORE, |
6683 self.annotationWarningStyle, |
6674 self.annotationWarningStyle, |
6684 Preferences.getEditorColour("AnnotationsWarningForeground")) |
6675 Preferences.getEditorColour("AnnotationsWarningForeground"), |
|
6676 ) |
6685 self.SendScintilla( |
6677 self.SendScintilla( |
6686 QsciScintilla.SCI_STYLESETBACK, |
6678 QsciScintilla.SCI_STYLESETBACK, |
6687 self.annotationWarningStyle, |
6679 self.annotationWarningStyle, |
6688 Preferences.getEditorColour("AnnotationsWarningBackground")) |
6680 Preferences.getEditorColour("AnnotationsWarningBackground"), |
6689 |
6681 ) |
|
6682 |
6690 self.annotationErrorStyle = self.annotationWarningStyle + 1 |
6683 self.annotationErrorStyle = self.annotationWarningStyle + 1 |
6691 self.SendScintilla( |
6684 self.SendScintilla( |
6692 QsciScintilla.SCI_STYLESETFORE, |
6685 QsciScintilla.SCI_STYLESETFORE, |
6693 self.annotationErrorStyle, |
6686 self.annotationErrorStyle, |
6694 Preferences.getEditorColour("AnnotationsErrorForeground")) |
6687 Preferences.getEditorColour("AnnotationsErrorForeground"), |
|
6688 ) |
6695 self.SendScintilla( |
6689 self.SendScintilla( |
6696 QsciScintilla.SCI_STYLESETBACK, |
6690 QsciScintilla.SCI_STYLESETBACK, |
6697 self.annotationErrorStyle, |
6691 self.annotationErrorStyle, |
6698 Preferences.getEditorColour("AnnotationsErrorBackground")) |
6692 Preferences.getEditorColour("AnnotationsErrorBackground"), |
6699 |
6693 ) |
|
6694 |
6700 self.annotationStyleStyle = self.annotationErrorStyle + 1 |
6695 self.annotationStyleStyle = self.annotationErrorStyle + 1 |
6701 self.SendScintilla( |
6696 self.SendScintilla( |
6702 QsciScintilla.SCI_STYLESETFORE, |
6697 QsciScintilla.SCI_STYLESETFORE, |
6703 self.annotationStyleStyle, |
6698 self.annotationStyleStyle, |
6704 Preferences.getEditorColour("AnnotationsStyleForeground")) |
6699 Preferences.getEditorColour("AnnotationsStyleForeground"), |
|
6700 ) |
6705 self.SendScintilla( |
6701 self.SendScintilla( |
6706 QsciScintilla.SCI_STYLESETBACK, |
6702 QsciScintilla.SCI_STYLESETBACK, |
6707 self.annotationStyleStyle, |
6703 self.annotationStyleStyle, |
6708 Preferences.getEditorColour("AnnotationsStyleBackground")) |
6704 Preferences.getEditorColour("AnnotationsStyleBackground"), |
6709 |
6705 ) |
|
6706 |
6710 def __setAnnotation(self, line): |
6707 def __setAnnotation(self, line): |
6711 """ |
6708 """ |
6712 Private method to set the annotations for the given line. |
6709 Private method to set the annotations for the given line. |
6713 |
6710 |
6714 @param line number of the line that needs annotation (integer) |
6711 @param line number of the line that needs annotation (integer) |
6715 """ |
6712 """ |
6716 if hasattr(QsciScintilla, "annotate"): |
6713 if hasattr(QsciScintilla, "annotate"): |
6717 warningAnnotations = [] |
6714 warningAnnotations = [] |
6718 errorAnnotations = [] |
6715 errorAnnotations = [] |
6719 styleAnnotations = [] |
6716 styleAnnotations = [] |
6720 |
6717 |
6721 # step 1: do warnings |
6718 # step 1: do warnings |
6722 for handle in self.warnings: |
6719 for handle in self.warnings: |
6723 if self.markerLine(handle) == line: |
6720 if self.markerLine(handle) == line: |
6724 for msg, warningType in self.warnings[handle]: |
6721 for msg, warningType in self.warnings[handle]: |
6725 if warningType == self.WarningStyle: |
6722 if warningType == self.WarningStyle: |
6726 styleAnnotations.append( |
6723 styleAnnotations.append(self.tr("Style: {0}").format(msg)) |
6727 self.tr("Style: {0}").format(msg)) |
|
6728 else: |
6724 else: |
6729 warningAnnotations.append( |
6725 warningAnnotations.append( |
6730 self.tr("Warning: {0}").format(msg)) |
6726 self.tr("Warning: {0}").format(msg) |
6731 |
6727 ) |
|
6728 |
6732 # step 2: do syntax errors |
6729 # step 2: do syntax errors |
6733 for handle in self.syntaxerrors: |
6730 for handle in self.syntaxerrors: |
6734 if self.markerLine(handle) == line: |
6731 if self.markerLine(handle) == line: |
6735 for msg, _ in self.syntaxerrors[handle]: |
6732 for msg, _ in self.syntaxerrors[handle]: |
6736 errorAnnotations.append( |
6733 errorAnnotations.append(self.tr("Error: {0}").format(msg)) |
6737 self.tr("Error: {0}").format(msg)) |
6734 |
6738 |
|
6739 annotations = [] |
6735 annotations = [] |
6740 if styleAnnotations: |
6736 if styleAnnotations: |
6741 annotationStyleTxt = "\n".join(styleAnnotations) |
6737 annotationStyleTxt = "\n".join(styleAnnotations) |
6742 if warningAnnotations or errorAnnotations: |
6738 if warningAnnotations or errorAnnotations: |
6743 annotationStyleTxt += "\n" |
6739 annotationStyleTxt += "\n" |
6744 annotations.append(QsciStyledText( |
6740 annotations.append( |
6745 annotationStyleTxt, self.annotationStyleStyle)) |
6741 QsciStyledText(annotationStyleTxt, self.annotationStyleStyle) |
6746 |
6742 ) |
|
6743 |
6747 if warningAnnotations: |
6744 if warningAnnotations: |
6748 annotationWarningTxt = "\n".join(warningAnnotations) |
6745 annotationWarningTxt = "\n".join(warningAnnotations) |
6749 if errorAnnotations: |
6746 if errorAnnotations: |
6750 annotationWarningTxt += "\n" |
6747 annotationWarningTxt += "\n" |
6751 annotations.append(QsciStyledText( |
6748 annotations.append( |
6752 annotationWarningTxt, self.annotationWarningStyle)) |
6749 QsciStyledText(annotationWarningTxt, self.annotationWarningStyle) |
6753 |
6750 ) |
|
6751 |
6754 if errorAnnotations: |
6752 if errorAnnotations: |
6755 annotationErrorTxt = "\n".join(errorAnnotations) |
6753 annotationErrorTxt = "\n".join(errorAnnotations) |
6756 annotations.append(QsciStyledText( |
6754 annotations.append( |
6757 annotationErrorTxt, self.annotationErrorStyle)) |
6755 QsciStyledText(annotationErrorTxt, self.annotationErrorStyle) |
6758 |
6756 ) |
|
6757 |
6759 if annotations: |
6758 if annotations: |
6760 self.annotate(line, annotations) |
6759 self.annotate(line, annotations) |
6761 else: |
6760 else: |
6762 self.clearAnnotations(line) |
6761 self.clearAnnotations(line) |
6763 |
6762 |
6764 def __refreshAnnotations(self): |
6763 def __refreshAnnotations(self): |
6765 """ |
6764 """ |
6766 Private method to refresh the annotations. |
6765 Private method to refresh the annotations. |
6767 """ |
6766 """ |
6768 if hasattr(QsciScintilla, "annotate"): |
6767 if hasattr(QsciScintilla, "annotate"): |
6769 self.clearAnnotations() |
6768 self.clearAnnotations() |
6770 for handle in ( |
6769 for handle in list(self.warnings.keys()) + list(self.syntaxerrors.keys()): |
6771 list(self.warnings.keys()) + |
|
6772 list(self.syntaxerrors.keys()) |
|
6773 ): |
|
6774 line = self.markerLine(handle) |
6770 line = self.markerLine(handle) |
6775 self.__setAnnotation(line) |
6771 self.__setAnnotation(line) |
6776 |
6772 |
6777 ################################################################# |
6773 ################################################################# |
6778 ## Fold handling methods |
6774 ## Fold handling methods |
6779 ################################################################# |
6775 ################################################################# |
6780 |
6776 |
6781 def toggleCurrentFold(self): |
6777 def toggleCurrentFold(self): |
6782 """ |
6778 """ |
6783 Public slot to toggle the fold containing the current line. |
6779 Public slot to toggle the fold containing the current line. |
6784 """ |
6780 """ |
6785 line, index = self.getCursorPosition() |
6781 line, index = self.getCursorPosition() |
6786 self.foldLine(line) |
6782 self.foldLine(line) |
6787 |
6783 |
6788 def expandFoldWithChildren(self, line=-1): |
6784 def expandFoldWithChildren(self, line=-1): |
6789 """ |
6785 """ |
6790 Public slot to expand the current fold including its children. |
6786 Public slot to expand the current fold including its children. |
6791 |
6787 |
6792 @param line number of line to be expanded |
6788 @param line number of line to be expanded |
6793 @type int |
6789 @type int |
6794 """ |
6790 """ |
6795 if line == -1: |
6791 if line == -1: |
6796 line, index = self.getCursorPosition() |
6792 line, index = self.getCursorPosition() |
6797 |
6793 |
6798 self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line, |
6794 self.SendScintilla( |
6799 QsciScintilla.SC_FOLDACTION_EXPAND) |
6795 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_EXPAND |
6800 |
6796 ) |
|
6797 |
6801 def collapseFoldWithChildren(self, line=-1): |
6798 def collapseFoldWithChildren(self, line=-1): |
6802 """ |
6799 """ |
6803 Public slot to collapse the current fold including its children. |
6800 Public slot to collapse the current fold including its children. |
6804 |
6801 |
6805 @param line number of line to be expanded |
6802 @param line number of line to be expanded |
6806 @type int |
6803 @type int |
6807 """ |
6804 """ |
6808 if line == -1: |
6805 if line == -1: |
6809 line, index = self.getCursorPosition() |
6806 line, index = self.getCursorPosition() |
6810 |
6807 |
6811 self.SendScintilla(QsciScintilla.SCI_FOLDCHILDREN, line, |
6808 self.SendScintilla( |
6812 QsciScintilla.SC_FOLDACTION_CONTRACT) |
6809 QsciScintilla.SCI_FOLDCHILDREN, line, QsciScintilla.SC_FOLDACTION_CONTRACT |
6813 |
6810 ) |
|
6811 |
6814 def __contextMenuExpandFoldWithChildren(self): |
6812 def __contextMenuExpandFoldWithChildren(self): |
6815 """ |
6813 """ |
6816 Private slot to handle the context menu expand with children action. |
6814 Private slot to handle the context menu expand with children action. |
6817 """ |
6815 """ |
6818 self.expandFoldWithChildren(self.line) |
6816 self.expandFoldWithChildren(self.line) |
6819 |
6817 |
6820 def __contextMenuCollapseFoldWithChildren(self): |
6818 def __contextMenuCollapseFoldWithChildren(self): |
6821 """ |
6819 """ |
6822 Private slot to handle the context menu collapse with children action. |
6820 Private slot to handle the context menu collapse with children action. |
6823 """ |
6821 """ |
6824 self.collapseFoldWithChildren(self.line) |
6822 self.collapseFoldWithChildren(self.line) |
6825 |
6823 |
6826 ################################################################# |
6824 ################################################################# |
6827 ## Macro handling methods |
6825 ## Macro handling methods |
6828 ################################################################# |
6826 ################################################################# |
6829 |
6827 |
6830 def __getMacroName(self): |
6828 def __getMacroName(self): |
6831 """ |
6829 """ |
6832 Private method to select a macro name from the list of macros. |
6830 Private method to select a macro name from the list of macros. |
6833 |
6831 |
6834 @return Tuple of macro name and a flag, indicating, if the user |
6832 @return Tuple of macro name and a flag, indicating, if the user |
6835 pressed ok or canceled the operation. (string, boolean) |
6833 pressed ok or canceled the operation. (string, boolean) |
6836 """ |
6834 """ |
6837 qs = [] |
6835 qs = [] |
6838 for s in list(self.macros.keys()): |
6836 for s in list(self.macros.keys()): |
6839 qs.append(s) |
6837 qs.append(s) |
6840 qs.sort() |
6838 qs.sort() |
6841 return QInputDialog.getItem( |
6839 return QInputDialog.getItem( |
6842 self, |
6840 self, self.tr("Macro Name"), self.tr("Select a macro name:"), qs, 0, False |
6843 self.tr("Macro Name"), |
6841 ) |
6844 self.tr("Select a macro name:"), |
6842 |
6845 qs, |
|
6846 0, False) |
|
6847 |
|
6848 def macroRun(self): |
6843 def macroRun(self): |
6849 """ |
6844 """ |
6850 Public method to execute a macro. |
6845 Public method to execute a macro. |
6851 """ |
6846 """ |
6852 name, ok = self.__getMacroName() |
6847 name, ok = self.__getMacroName() |
6853 if ok and name: |
6848 if ok and name: |
6854 self.macros[name].play() |
6849 self.macros[name].play() |
6855 |
6850 |
6856 def macroDelete(self): |
6851 def macroDelete(self): |
6857 """ |
6852 """ |
6858 Public method to delete a macro. |
6853 Public method to delete a macro. |
6859 """ |
6854 """ |
6860 name, ok = self.__getMacroName() |
6855 name, ok = self.__getMacroName() |
6861 if ok and name: |
6856 if ok and name: |
6862 del self.macros[name] |
6857 del self.macros[name] |
6863 |
6858 |
6864 def macroLoad(self): |
6859 def macroLoad(self): |
6865 """ |
6860 """ |
6866 Public method to load a macro from a file. |
6861 Public method to load a macro from a file. |
6867 """ |
6862 """ |
6868 configDir = Utilities.getConfigDir() |
6863 configDir = Utilities.getConfigDir() |
6869 fname = EricFileDialog.getOpenFileName( |
6864 fname = EricFileDialog.getOpenFileName( |
6870 self, |
6865 self, |
6871 self.tr("Load macro file"), |
6866 self.tr("Load macro file"), |
6872 configDir, |
6867 configDir, |
6873 self.tr("Macro files (*.macro)")) |
6868 self.tr("Macro files (*.macro)"), |
6874 |
6869 ) |
|
6870 |
6875 if not fname: |
6871 if not fname: |
6876 return # user aborted |
6872 return # user aborted |
6877 |
6873 |
6878 try: |
6874 try: |
6879 with open(fname, "r", encoding="utf-8") as f: |
6875 with open(fname, "r", encoding="utf-8") as f: |
6880 lines = f.readlines() |
6876 lines = f.readlines() |
6881 except OSError: |
6877 except OSError: |
6882 EricMessageBox.critical( |
6878 EricMessageBox.critical( |
6883 self, |
6879 self, |
6884 self.tr("Error loading macro"), |
6880 self.tr("Error loading macro"), |
6885 self.tr( |
6881 self.tr("<p>The macro file <b>{0}</b> could not be read.</p>").format( |
6886 "<p>The macro file <b>{0}</b> could not be read.</p>") |
6882 fname |
6887 .format(fname)) |
6883 ), |
|
6884 ) |
6888 return |
6885 return |
6889 |
6886 |
6890 if len(lines) != 2: |
6887 if len(lines) != 2: |
6891 EricMessageBox.critical( |
6888 EricMessageBox.critical( |
6892 self, |
6889 self, |
6893 self.tr("Error loading macro"), |
6890 self.tr("Error loading macro"), |
6894 self.tr("<p>The macro file <b>{0}</b> is corrupt.</p>") |
6891 self.tr("<p>The macro file <b>{0}</b> is corrupt.</p>").format(fname), |
6895 .format(fname)) |
6892 ) |
6896 return |
6893 return |
6897 |
6894 |
6898 macro = QsciMacro(lines[1], self) |
6895 macro = QsciMacro(lines[1], self) |
6899 self.macros[lines[0].strip()] = macro |
6896 self.macros[lines[0].strip()] = macro |
6900 |
6897 |
6901 def macroSave(self): |
6898 def macroSave(self): |
6902 """ |
6899 """ |
6903 Public method to save a macro to a file. |
6900 Public method to save a macro to a file. |
6904 """ |
6901 """ |
6905 configDir = Utilities.getConfigDir() |
6902 configDir = Utilities.getConfigDir() |
6906 |
6903 |
6907 name, ok = self.__getMacroName() |
6904 name, ok = self.__getMacroName() |
6908 if not ok or not name: |
6905 if not ok or not name: |
6909 return # user abort |
6906 return # user abort |
6910 |
6907 |
6911 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
6908 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
6912 self, |
6909 self, |
6913 self.tr("Save macro file"), |
6910 self.tr("Save macro file"), |
6914 configDir, |
6911 configDir, |
6915 self.tr("Macro files (*.macro)"), |
6912 self.tr("Macro files (*.macro)"), |
6916 "", |
6913 "", |
6917 EricFileDialog.DontConfirmOverwrite) |
6914 EricFileDialog.DontConfirmOverwrite, |
6918 |
6915 ) |
|
6916 |
6919 if not fname: |
6917 if not fname: |
6920 return # user aborted |
6918 return # user aborted |
6921 |
6919 |
6922 fpath = pathlib.Path(fname) |
6920 fpath = pathlib.Path(fname) |
6923 if not fpath.suffix: |
6921 if not fpath.suffix: |
6924 ex = selectedFilter.split("(*")[1].split(")")[0] |
6922 ex = selectedFilter.split("(*")[1].split(")")[0] |
6925 if ex: |
6923 if ex: |
6926 fpath = fpath.with_suffix(ex) |
6924 fpath = fpath.with_suffix(ex) |
6927 if fpath.exists(): |
6925 if fpath.exists(): |
6928 res = EricMessageBox.yesNo( |
6926 res = EricMessageBox.yesNo( |
6929 self, |
6927 self, |
6930 self.tr("Save macro"), |
6928 self.tr("Save macro"), |
6931 self.tr("<p>The macro file <b>{0}</b> already exists." |
6929 self.tr( |
6932 " Overwrite it?</p>").format(fpath), |
6930 "<p>The macro file <b>{0}</b> already exists." " Overwrite it?</p>" |
6933 icon=EricMessageBox.Warning) |
6931 ).format(fpath), |
|
6932 icon=EricMessageBox.Warning, |
|
6933 ) |
6934 if not res: |
6934 if not res: |
6935 return |
6935 return |
6936 |
6936 |
6937 try: |
6937 try: |
6938 with fpath.open("w", encoding="utf-8") as f: |
6938 with fpath.open("w", encoding="utf-8") as f: |
6939 f.write("{0}{1}".format(name, "\n")) |
6939 f.write("{0}{1}".format(name, "\n")) |
6940 f.write(self.macros[name].save()) |
6940 f.write(self.macros[name].save()) |
6941 except OSError: |
6941 except OSError: |
6942 EricMessageBox.critical( |
6942 EricMessageBox.critical( |
6943 self, |
6943 self, |
6944 self.tr("Error saving macro"), |
6944 self.tr("Error saving macro"), |
6945 self.tr( |
6945 self.tr( |
6946 "<p>The macro file <b>{0}</b> could not be written.</p>") |
6946 "<p>The macro file <b>{0}</b> could not be written.</p>" |
6947 .format(fpath)) |
6947 ).format(fpath), |
|
6948 ) |
6948 return |
6949 return |
6949 |
6950 |
6950 def macroRecordingStart(self): |
6951 def macroRecordingStart(self): |
6951 """ |
6952 """ |
6952 Public method to start macro recording. |
6953 Public method to start macro recording. |
6953 """ |
6954 """ |
6954 if self.recording: |
6955 if self.recording: |
6955 res = EricMessageBox.yesNo( |
6956 res = EricMessageBox.yesNo( |
6956 self, |
6957 self, |
6957 self.tr("Start Macro Recording"), |
6958 self.tr("Start Macro Recording"), |
6958 self.tr("Macro recording is already active. Start new?"), |
6959 self.tr("Macro recording is already active. Start new?"), |
6959 icon=EricMessageBox.Warning, |
6960 icon=EricMessageBox.Warning, |
6960 yesDefault=True) |
6961 yesDefault=True, |
|
6962 ) |
6961 if res: |
6963 if res: |
6962 self.macroRecordingStop() |
6964 self.macroRecordingStop() |
6963 else: |
6965 else: |
6964 return |
6966 return |
6965 else: |
6967 else: |
6966 self.recording = True |
6968 self.recording = True |
6967 |
6969 |
6968 self.curMacro = QsciMacro(self) |
6970 self.curMacro = QsciMacro(self) |
6969 self.curMacro.startRecording() |
6971 self.curMacro.startRecording() |
6970 |
6972 |
6971 def macroRecordingStop(self): |
6973 def macroRecordingStop(self): |
6972 """ |
6974 """ |
6973 Public method to stop macro recording. |
6975 Public method to stop macro recording. |
6974 """ |
6976 """ |
6975 if not self.recording: |
6977 if not self.recording: |
6976 return # we are not recording |
6978 return # we are not recording |
6977 |
6979 |
6978 self.curMacro.endRecording() |
6980 self.curMacro.endRecording() |
6979 self.recording = False |
6981 self.recording = False |
6980 |
6982 |
6981 name, ok = QInputDialog.getText( |
6983 name, ok = QInputDialog.getText( |
6982 self, |
6984 self, |
6983 self.tr("Macro Recording"), |
6985 self.tr("Macro Recording"), |
6984 self.tr("Enter name of the macro:"), |
6986 self.tr("Enter name of the macro:"), |
6985 QLineEdit.EchoMode.Normal) |
6987 QLineEdit.EchoMode.Normal, |
6986 |
6988 ) |
|
6989 |
6987 if ok and name: |
6990 if ok and name: |
6988 self.macros[name] = self.curMacro |
6991 self.macros[name] = self.curMacro |
6989 |
6992 |
6990 self.curMacro = None |
6993 self.curMacro = None |
6991 |
6994 |
6992 ################################################################# |
6995 ################################################################# |
6993 ## Overwritten methods |
6996 ## Overwritten methods |
6994 ################################################################# |
6997 ################################################################# |
6995 |
6998 |
6996 def undo(self): |
6999 def undo(self): |
6997 """ |
7000 """ |
6998 Public method to undo the last recorded change. |
7001 Public method to undo the last recorded change. |
6999 """ |
7002 """ |
7000 super().undo() |
7003 super().undo() |
7001 self.undoAvailable.emit(self.isUndoAvailable()) |
7004 self.undoAvailable.emit(self.isUndoAvailable()) |
7002 self.redoAvailable.emit(self.isRedoAvailable()) |
7005 self.redoAvailable.emit(self.isRedoAvailable()) |
7003 |
7006 |
7004 def redo(self): |
7007 def redo(self): |
7005 """ |
7008 """ |
7006 Public method to redo the last recorded change. |
7009 Public method to redo the last recorded change. |
7007 """ |
7010 """ |
7008 super().redo() |
7011 super().redo() |
7009 self.undoAvailable.emit(self.isUndoAvailable()) |
7012 self.undoAvailable.emit(self.isUndoAvailable()) |
7010 self.redoAvailable.emit(self.isRedoAvailable()) |
7013 self.redoAvailable.emit(self.isRedoAvailable()) |
7011 |
7014 |
7012 def close(self, alsoDelete=False): |
7015 def close(self, alsoDelete=False): |
7013 """ |
7016 """ |
7014 Public method called when the window gets closed. |
7017 Public method called when the window gets closed. |
7015 |
7018 |
7016 This overwritten method redirects the action to our |
7019 This overwritten method redirects the action to our |
7017 ViewManager.closeEditor, which in turn calls our closeIt |
7020 ViewManager.closeEditor, which in turn calls our closeIt |
7018 method. |
7021 method. |
7019 |
7022 |
7020 @param alsoDelete ignored |
7023 @param alsoDelete ignored |
7021 @return flag indicating a successful close of the editor (boolean) |
7024 @return flag indicating a successful close of the editor (boolean) |
7022 """ |
7025 """ |
7023 return self.vm.closeEditor(self) |
7026 return self.vm.closeEditor(self) |
7024 |
7027 |
7025 def closeIt(self): |
7028 def closeIt(self): |
7026 """ |
7029 """ |
7027 Public method called by the viewmanager to finally get rid of us. |
7030 Public method called by the viewmanager to finally get rid of us. |
7028 """ |
7031 """ |
7029 if Preferences.getEditor("ClearBreaksOnClose") and not self.__clones: |
7032 if Preferences.getEditor("ClearBreaksOnClose") and not self.__clones: |
7030 self.__menuClearBreakpoints() |
7033 self.__menuClearBreakpoints() |
7031 |
7034 |
7032 for clone in self.__clones[:]: |
7035 for clone in self.__clones[:]: |
7033 self.removeClone(clone) |
7036 self.removeClone(clone) |
7034 clone.removeClone(self) |
7037 clone.removeClone(self) |
7035 |
7038 |
7036 self.breakpointModel.rowsAboutToBeRemoved.disconnect( |
7039 self.breakpointModel.rowsAboutToBeRemoved.disconnect(self.__deleteBreakPoints) |
7037 self.__deleteBreakPoints) |
|
7038 self.breakpointModel.dataAboutToBeChanged.disconnect( |
7040 self.breakpointModel.dataAboutToBeChanged.disconnect( |
7039 self.__breakPointDataAboutToBeChanged) |
7041 self.__breakPointDataAboutToBeChanged |
7040 self.breakpointModel.dataChanged.disconnect( |
7042 ) |
7041 self.__changeBreakPoints) |
7043 self.breakpointModel.dataChanged.disconnect(self.__changeBreakPoints) |
7042 self.breakpointModel.rowsInserted.disconnect( |
7044 self.breakpointModel.rowsInserted.disconnect(self.__addBreakPoints) |
7043 self.__addBreakPoints) |
7045 |
7044 |
|
7045 if self.syntaxCheckService is not None: |
7046 if self.syntaxCheckService is not None: |
7046 self.syntaxCheckService.syntaxChecked.disconnect( |
7047 self.syntaxCheckService.syntaxChecked.disconnect( |
7047 self.__processSyntaxCheckResult) |
7048 self.__processSyntaxCheckResult |
7048 self.syntaxCheckService.error.disconnect( |
7049 ) |
7049 self.__processSyntaxCheckError) |
7050 self.syntaxCheckService.error.disconnect(self.__processSyntaxCheckError) |
7050 |
7051 |
7051 if self.spell: |
7052 if self.spell: |
7052 self.spell.stopIncrementalCheck() |
7053 self.spell.stopIncrementalCheck() |
7053 |
7054 |
7054 with contextlib.suppress(TypeError): |
7055 with contextlib.suppress(TypeError): |
7055 self.project.projectPropertiesChanged.disconnect( |
7056 self.project.projectPropertiesChanged.disconnect( |
7056 self.__projectPropertiesChanged) |
7057 self.__projectPropertiesChanged |
7057 |
7058 ) |
|
7059 |
7058 if self.fileName: |
7060 if self.fileName: |
7059 self.taskViewer.clearFileTasks(self.fileName, True) |
7061 self.taskViewer.clearFileTasks(self.fileName, True) |
7060 |
7062 |
7061 super().close() |
7063 super().close() |
7062 |
7064 |
7063 def keyPressEvent(self, ev): |
7065 def keyPressEvent(self, ev): |
7064 """ |
7066 """ |
7065 Protected method to handle the user input a key at a time. |
7067 Protected method to handle the user input a key at a time. |
7066 |
7068 |
7067 @param ev key event |
7069 @param ev key event |
7068 @type QKeyEvent |
7070 @type QKeyEvent |
7069 """ |
7071 """ |
|
7072 |
7070 def encloseSelectedText(encString): |
7073 def encloseSelectedText(encString): |
7071 """ |
7074 """ |
7072 Local function to enclose the current selection with some |
7075 Local function to enclose the current selection with some |
7073 characters. |
7076 characters. |
7074 |
7077 |
7075 @param encString string to use to enclose the selection |
7078 @param encString string to use to enclose the selection |
7076 (one or two characters) |
7079 (one or two characters) |
7077 @type str |
7080 @type str |
7078 """ |
7081 """ |
7079 startChar = encString[0] |
7082 startChar = encString[0] |
7080 endChar = encString[1] if len(encString) == 2 else startChar |
7083 endChar = encString[1] if len(encString) == 2 else startChar |
7081 |
7084 |
7082 sline, sindex, eline, eindex = self.getSelection() |
7085 sline, sindex, eline, eindex = self.getSelection() |
7083 replaceText = startChar + self.selectedText() + endChar |
7086 replaceText = startChar + self.selectedText() + endChar |
7084 self.beginUndoAction() |
7087 self.beginUndoAction() |
7085 self.replaceSelectedText(replaceText) |
7088 self.replaceSelectedText(replaceText) |
7086 self.endUndoAction() |
7089 self.endUndoAction() |
7087 self.setSelection(sline, sindex + 1, eline, eindex + 1) |
7090 self.setSelection(sline, sindex + 1, eline, eindex + 1) |
7088 |
7091 |
7089 txt = ev.text() |
7092 txt = ev.text() |
7090 |
7093 |
7091 # See it is text to insert. |
7094 # See it is text to insert. |
7092 if len(txt) and txt >= " ": |
7095 if len(txt) and txt >= " ": |
7093 if ( |
7096 if self.hasSelectedText() and txt in Editor.EncloseChars: |
7094 self.hasSelectedText() and |
|
7095 txt in Editor.EncloseChars |
|
7096 ): |
|
7097 encloseSelectedText(Editor.EncloseChars[txt]) |
7097 encloseSelectedText(Editor.EncloseChars[txt]) |
7098 ev.accept() |
7098 ev.accept() |
7099 return |
7099 return |
7100 |
7100 |
7101 super().keyPressEvent(ev) |
7101 super().keyPressEvent(ev) |
7102 else: |
7102 else: |
7103 ev.ignore() |
7103 ev.ignore() |
7104 |
7104 |
7105 def focusInEvent(self, event): |
7105 def focusInEvent(self, event): |
7106 """ |
7106 """ |
7107 Protected method called when the editor receives focus. |
7107 Protected method called when the editor receives focus. |
7108 |
7108 |
7109 This method checks for modifications of the current file and |
7109 This method checks for modifications of the current file and |
7110 rereads it upon request. The cursor is placed at the current position |
7110 rereads it upon request. The cursor is placed at the current position |
7111 assuming, that it is in the vicinity of the old position after the |
7111 assuming, that it is in the vicinity of the old position after the |
7112 reread. |
7112 reread. |
7113 |
7113 |
7114 @param event the event object |
7114 @param event the event object |
7115 @type QFocusEvent |
7115 @type QFocusEvent |
7116 """ |
7116 """ |
7117 self.recolor() |
7117 self.recolor() |
7118 self.vm.editActGrp.setEnabled(True) |
7118 self.vm.editActGrp.setEnabled(True) |
7494 self.vm.openSourceFile(fname) |
7487 self.vm.openSourceFile(fname) |
7495 else: |
7488 else: |
7496 EricMessageBox.information( |
7489 EricMessageBox.information( |
7497 self, |
7490 self, |
7498 self.tr("Drop Error"), |
7491 self.tr("Drop Error"), |
7499 self.tr("""<p><b>{0}</b> is not a file.</p>""") |
7492 self.tr("""<p><b>{0}</b> is not a file.</p>""").format( |
7500 .format(fname)) |
7493 fname |
|
7494 ), |
|
7495 ) |
7501 event.acceptProposedAction() |
7496 event.acceptProposedAction() |
7502 else: |
7497 else: |
7503 super().dropEvent(event) |
7498 super().dropEvent(event) |
7504 |
7499 |
7505 self.inDragDrop = False |
7500 self.inDragDrop = False |
7506 |
7501 |
7507 ################################################################# |
7502 ################################################################# |
7508 ## Support for Qt resources files |
7503 ## Support for Qt resources files |
7509 ################################################################# |
7504 ################################################################# |
7510 |
7505 |
7511 def __initContextMenuResources(self): |
7506 def __initContextMenuResources(self): |
7512 """ |
7507 """ |
7513 Private method used to setup the Resources context sub menu. |
7508 Private method used to setup the Resources context sub menu. |
7514 |
7509 |
7515 @return reference to the generated menu (QMenu) |
7510 @return reference to the generated menu (QMenu) |
7516 """ |
7511 """ |
7517 menu = QMenu(self.tr('Resources')) |
7512 menu = QMenu(self.tr("Resources")) |
7518 |
7513 |
|
7514 menu.addAction(self.tr("Add file..."), self.__addFileResource) |
|
7515 menu.addAction(self.tr("Add files..."), self.__addFileResources) |
|
7516 menu.addAction(self.tr("Add aliased file..."), self.__addFileAliasResource) |
7519 menu.addAction( |
7517 menu.addAction( |
7520 self.tr('Add file...'), self.__addFileResource) |
7518 self.tr("Add localized resource..."), self.__addLocalizedResource |
7521 menu.addAction( |
7519 ) |
7522 self.tr('Add files...'), self.__addFileResources) |
|
7523 menu.addAction( |
|
7524 self.tr('Add aliased file...'), |
|
7525 self.__addFileAliasResource) |
|
7526 menu.addAction( |
|
7527 self.tr('Add localized resource...'), |
|
7528 self.__addLocalizedResource) |
|
7529 menu.addSeparator() |
7520 menu.addSeparator() |
7530 menu.addAction( |
7521 menu.addAction(self.tr("Add resource frame"), self.__addResourceFrame) |
7531 self.tr('Add resource frame'), self.__addResourceFrame) |
7522 |
7532 |
|
7533 menu.aboutToShow.connect(self.__showContextMenuResources) |
7523 menu.aboutToShow.connect(self.__showContextMenuResources) |
7534 |
7524 |
7535 return menu |
7525 return menu |
7536 |
7526 |
7537 def __showContextMenuResources(self): |
7527 def __showContextMenuResources(self): |
7538 """ |
7528 """ |
7539 Private slot handling the aboutToShow signal of the resources context |
7529 Private slot handling the aboutToShow signal of the resources context |
7540 menu. |
7530 menu. |
7541 """ |
7531 """ |
7542 self.showMenu.emit("Resources", self.resourcesMenu, self) |
7532 self.showMenu.emit("Resources", self.resourcesMenu, self) |
7543 |
7533 |
7544 def __addFileResource(self): |
7534 def __addFileResource(self): |
7545 """ |
7535 """ |
7546 Private method to handle the Add file context menu action. |
7536 Private method to handle the Add file context menu action. |
7547 """ |
7537 """ |
7548 dirStr = os.path.dirname(self.fileName) |
7538 dirStr = os.path.dirname(self.fileName) |
7549 file = EricFileDialog.getOpenFileName( |
7539 file = EricFileDialog.getOpenFileName( |
7550 self, |
7540 self, self.tr("Add file resource"), dirStr, "" |
7551 self.tr("Add file resource"), |
7541 ) |
7552 dirStr, |
|
7553 "") |
|
7554 if file: |
7542 if file: |
7555 relFile = QDir(dirStr).relativeFilePath(file) |
7543 relFile = QDir(dirStr).relativeFilePath(file) |
7556 line, index = self.getCursorPosition() |
7544 line, index = self.getCursorPosition() |
7557 self.insert(" <file>{0}</file>\n".format(relFile)) |
7545 self.insert(" <file>{0}</file>\n".format(relFile)) |
7558 self.setCursorPosition(line + 1, index) |
7546 self.setCursorPosition(line + 1, index) |
7559 |
7547 |
7560 def __addFileResources(self): |
7548 def __addFileResources(self): |
7561 """ |
7549 """ |
7562 Private method to handle the Add files context menu action. |
7550 Private method to handle the Add files context menu action. |
7563 """ |
7551 """ |
7564 dirStr = os.path.dirname(self.fileName) |
7552 dirStr = os.path.dirname(self.fileName) |
7565 files = EricFileDialog.getOpenFileNames( |
7553 files = EricFileDialog.getOpenFileNames( |
7566 self, |
7554 self, self.tr("Add file resources"), dirStr, "" |
7567 self.tr("Add file resources"), |
7555 ) |
7568 dirStr, |
|
7569 "") |
|
7570 if files: |
7556 if files: |
7571 myDir = QDir(dirStr) |
7557 myDir = QDir(dirStr) |
7572 filesText = "" |
7558 filesText = "" |
7573 for file in files: |
7559 for file in files: |
7574 relFile = myDir.relativeFilePath(file) |
7560 relFile = myDir.relativeFilePath(file) |
7575 filesText += " <file>{0}</file>\n".format(relFile) |
7561 filesText += " <file>{0}</file>\n".format(relFile) |
7576 line, index = self.getCursorPosition() |
7562 line, index = self.getCursorPosition() |
7577 self.insert(filesText) |
7563 self.insert(filesText) |
7578 self.setCursorPosition(line + len(files), index) |
7564 self.setCursorPosition(line + len(files), index) |
7579 |
7565 |
7580 def __addFileAliasResource(self): |
7566 def __addFileAliasResource(self): |
7581 """ |
7567 """ |
7582 Private method to handle the Add aliased file context menu action. |
7568 Private method to handle the Add aliased file context menu action. |
7583 """ |
7569 """ |
7584 dirStr = os.path.dirname(self.fileName) |
7570 dirStr = os.path.dirname(self.fileName) |
7585 file = EricFileDialog.getOpenFileName( |
7571 file = EricFileDialog.getOpenFileName( |
7586 self, |
7572 self, self.tr("Add aliased file resource"), dirStr, "" |
7587 self.tr("Add aliased file resource"), |
7573 ) |
7588 dirStr, |
|
7589 "") |
|
7590 if file: |
7574 if file: |
7591 relFile = QDir(dirStr).relativeFilePath(file) |
7575 relFile = QDir(dirStr).relativeFilePath(file) |
7592 alias, ok = QInputDialog.getText( |
7576 alias, ok = QInputDialog.getText( |
7593 self, |
7577 self, |
7594 self.tr("Add aliased file resource"), |
7578 self.tr("Add aliased file resource"), |
7595 self.tr("Alias for file <b>{0}</b>:").format(relFile), |
7579 self.tr("Alias for file <b>{0}</b>:").format(relFile), |
7596 QLineEdit.EchoMode.Normal, |
7580 QLineEdit.EchoMode.Normal, |
7597 relFile) |
7581 relFile, |
|
7582 ) |
7598 if ok and alias: |
7583 if ok and alias: |
7599 line, index = self.getCursorPosition() |
7584 line, index = self.getCursorPosition() |
7600 self.insert(' <file alias="{1}">{0}</file>\n' |
7585 self.insert(' <file alias="{1}">{0}</file>\n'.format(relFile, alias)) |
7601 .format(relFile, alias)) |
|
7602 self.setCursorPosition(line + 1, index) |
7586 self.setCursorPosition(line + 1, index) |
7603 |
7587 |
7604 def __addLocalizedResource(self): |
7588 def __addLocalizedResource(self): |
7605 """ |
7589 """ |
7606 Private method to handle the Add localized resource context menu |
7590 Private method to handle the Add localized resource context menu |
7607 action. |
7591 action. |
7608 """ |
7592 """ |
7609 from Project.AddLanguageDialog import AddLanguageDialog |
7593 from Project.AddLanguageDialog import AddLanguageDialog |
|
7594 |
7610 dlg = AddLanguageDialog(self) |
7595 dlg = AddLanguageDialog(self) |
7611 if dlg.exec() == QDialog.DialogCode.Accepted: |
7596 if dlg.exec() == QDialog.DialogCode.Accepted: |
7612 lang = dlg.getSelectedLanguage() |
7597 lang = dlg.getSelectedLanguage() |
7613 line, index = self.getCursorPosition() |
7598 line, index = self.getCursorPosition() |
7614 self.insert('<qresource lang="{0}">\n</qresource>\n'.format(lang)) |
7599 self.insert('<qresource lang="{0}">\n</qresource>\n'.format(lang)) |
7615 self.setCursorPosition(line + 2, index) |
7600 self.setCursorPosition(line + 2, index) |
7616 |
7601 |
7617 def __addResourceFrame(self): |
7602 def __addResourceFrame(self): |
7618 """ |
7603 """ |
7619 Private method to handle the Add resource frame context menu action. |
7604 Private method to handle the Add resource frame context menu action. |
7620 """ |
7605 """ |
7621 line, index = self.getCursorPosition() |
7606 line, index = self.getCursorPosition() |
7622 self.insert('<!DOCTYPE RCC>\n' |
7607 self.insert( |
7623 '<RCC version="1.0">\n' |
7608 "<!DOCTYPE RCC>\n" |
7624 '<qresource>\n' |
7609 '<RCC version="1.0">\n' |
7625 '</qresource>\n' |
7610 "<qresource>\n" |
7626 '</RCC>\n') |
7611 "</qresource>\n" |
|
7612 "</RCC>\n" |
|
7613 ) |
7627 self.setCursorPosition(line + 5, index) |
7614 self.setCursorPosition(line + 5, index) |
7628 |
7615 |
7629 ################################################################# |
7616 ################################################################# |
7630 ## Support for diagrams below |
7617 ## Support for diagrams below |
7631 ################################################################# |
7618 ################################################################# |
7632 |
7619 |
7633 def __showClassDiagram(self): |
7620 def __showClassDiagram(self): |
7634 """ |
7621 """ |
7635 Private method to handle the Class Diagram context menu action. |
7622 Private method to handle the Class Diagram context menu action. |
7636 """ |
7623 """ |
7637 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
7624 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
7625 |
7638 if not self.checkDirty(): |
7626 if not self.checkDirty(): |
7639 return |
7627 return |
7640 |
7628 |
7641 self.classDiagram = UMLDialog( |
7629 self.classDiagram = UMLDialog( |
7642 UMLDialogType.CLASS_DIAGRAM, self.project, self.fileName, |
7630 UMLDialogType.CLASS_DIAGRAM, |
7643 self, noAttrs=False) |
7631 self.project, |
|
7632 self.fileName, |
|
7633 self, |
|
7634 noAttrs=False, |
|
7635 ) |
7644 self.classDiagram.show() |
7636 self.classDiagram.show() |
7645 |
7637 |
7646 def __showPackageDiagram(self): |
7638 def __showPackageDiagram(self): |
7647 """ |
7639 """ |
7648 Private method to handle the Package Diagram context menu action. |
7640 Private method to handle the Package Diagram context menu action. |
7649 """ |
7641 """ |
7650 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
7642 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
7643 |
7651 if not self.checkDirty(): |
7644 if not self.checkDirty(): |
7652 return |
7645 return |
7653 |
7646 |
7654 package = ( |
7647 package = ( |
7655 os.path.isdir(self.fileName) and |
7648 os.path.isdir(self.fileName) |
7656 self.fileName or os.path.dirname(self.fileName) |
7649 and self.fileName |
|
7650 or os.path.dirname(self.fileName) |
7657 ) |
7651 ) |
7658 res = EricMessageBox.yesNo( |
7652 res = EricMessageBox.yesNo( |
7659 self, |
7653 self, |
7660 self.tr("Package Diagram"), |
7654 self.tr("Package Diagram"), |
7661 self.tr("""Include class attributes?"""), |
7655 self.tr("""Include class attributes?"""), |
7662 yesDefault=True) |
7656 yesDefault=True, |
|
7657 ) |
7663 self.packageDiagram = UMLDialog( |
7658 self.packageDiagram = UMLDialog( |
7664 UMLDialogType.PACKAGE_DIAGRAM, self.project, package, |
7659 UMLDialogType.PACKAGE_DIAGRAM, self.project, package, self, noAttrs=not res |
7665 self, noAttrs=not res) |
7660 ) |
7666 self.packageDiagram.show() |
7661 self.packageDiagram.show() |
7667 |
7662 |
7668 def __showImportsDiagram(self): |
7663 def __showImportsDiagram(self): |
7669 """ |
7664 """ |
7670 Private method to handle the Imports Diagram context menu action. |
7665 Private method to handle the Imports Diagram context menu action. |
7671 """ |
7666 """ |
7672 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
7667 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
7668 |
7673 if not self.checkDirty(): |
7669 if not self.checkDirty(): |
7674 return |
7670 return |
7675 |
7671 |
7676 package = os.path.dirname(self.fileName) |
7672 package = os.path.dirname(self.fileName) |
7677 res = EricMessageBox.yesNo( |
7673 res = EricMessageBox.yesNo( |
7678 self, |
7674 self, |
7679 self.tr("Imports Diagram"), |
7675 self.tr("Imports Diagram"), |
7680 self.tr("""Include imports from external modules?""")) |
7676 self.tr("""Include imports from external modules?"""), |
|
7677 ) |
7681 self.importsDiagram = UMLDialog( |
7678 self.importsDiagram = UMLDialog( |
7682 UMLDialogType.IMPORTS_DIAGRAM, self.project, package, |
7679 UMLDialogType.IMPORTS_DIAGRAM, |
7683 self, showExternalImports=res) |
7680 self.project, |
|
7681 package, |
|
7682 self, |
|
7683 showExternalImports=res, |
|
7684 ) |
7684 self.importsDiagram.show() |
7685 self.importsDiagram.show() |
7685 |
7686 |
7686 def __showApplicationDiagram(self): |
7687 def __showApplicationDiagram(self): |
7687 """ |
7688 """ |
7688 Private method to handle the Imports Diagram context menu action. |
7689 Private method to handle the Imports Diagram context menu action. |
7689 """ |
7690 """ |
7690 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
7691 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
7692 |
7691 res = EricMessageBox.yesNo( |
7693 res = EricMessageBox.yesNo( |
7692 self, |
7694 self, |
7693 self.tr("Application Diagram"), |
7695 self.tr("Application Diagram"), |
7694 self.tr("""Include module names?"""), |
7696 self.tr("""Include module names?"""), |
7695 yesDefault=True) |
7697 yesDefault=True, |
|
7698 ) |
7696 self.applicationDiagram = UMLDialog( |
7699 self.applicationDiagram = UMLDialog( |
7697 UMLDialogType.APPLICATION_DIAGRAM, self.project, |
7700 UMLDialogType.APPLICATION_DIAGRAM, self.project, self, noModules=not res |
7698 self, noModules=not res) |
7701 ) |
7699 self.applicationDiagram.show() |
7702 self.applicationDiagram.show() |
7700 |
7703 |
7701 def __loadDiagram(self): |
7704 def __loadDiagram(self): |
7702 """ |
7705 """ |
7703 Private slot to load a diagram from file. |
7706 Private slot to load a diagram from file. |
7704 """ |
7707 """ |
7705 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
7708 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
7709 |
7706 self.loadedDiagram = UMLDialog( |
7710 self.loadedDiagram = UMLDialog( |
7707 UMLDialogType.NO_DIAGRAM, self.project, parent=self) |
7711 UMLDialogType.NO_DIAGRAM, self.project, parent=self |
|
7712 ) |
7708 if self.loadedDiagram.load(): |
7713 if self.loadedDiagram.load(): |
7709 self.loadedDiagram.show(fromFile=True) |
7714 self.loadedDiagram.show(fromFile=True) |
7710 else: |
7715 else: |
7711 self.loadedDiagram = None |
7716 self.loadedDiagram = None |
7712 |
7717 |
7713 ####################################################################### |
7718 ####################################################################### |
7714 ## Typing aids related methods below |
7719 ## Typing aids related methods below |
7715 ####################################################################### |
7720 ####################################################################### |
7716 |
7721 |
7717 def __toggleTypingAids(self): |
7722 def __toggleTypingAids(self): |
7718 """ |
7723 """ |
7719 Private slot to toggle the typing aids. |
7724 Private slot to toggle the typing aids. |
7720 """ |
7725 """ |
7721 if self.menuActs["TypingAidsEnabled"].isChecked(): |
7726 if self.menuActs["TypingAidsEnabled"].isChecked(): |
7722 self.completer.setEnabled(True) |
7727 self.completer.setEnabled(True) |
7723 else: |
7728 else: |
7724 self.completer.setEnabled(False) |
7729 self.completer.setEnabled(False) |
7725 |
7730 |
7726 ####################################################################### |
7731 ####################################################################### |
7727 ## Auto-completing templates |
7732 ## Auto-completing templates |
7728 ####################################################################### |
7733 ####################################################################### |
7729 |
7734 |
7730 def editorCommand(self, cmd): |
7735 def editorCommand(self, cmd): |
7731 """ |
7736 """ |
7732 Public method to perform a simple editor command. |
7737 Public method to perform a simple editor command. |
7733 |
7738 |
7734 @param cmd the scintilla command to be performed |
7739 @param cmd the scintilla command to be performed |
7735 """ |
7740 """ |
7736 if cmd == QsciScintilla.SCI_TAB: |
7741 if cmd == QsciScintilla.SCI_TAB: |
7737 try: |
7742 try: |
7738 templateViewer = ericApp().getObject("TemplateViewer") |
7743 templateViewer = ericApp().getObject("TemplateViewer") |
7739 except KeyError: |
7744 except KeyError: |
7740 # template viewer is not active |
7745 # template viewer is not active |
7741 templateViewer = None |
7746 templateViewer = None |
7742 |
7747 |
7743 if templateViewer is not None: |
7748 if templateViewer is not None: |
7744 line, index = self.getCursorPosition() |
7749 line, index = self.getCursorPosition() |
7745 tmplName = self.getWordLeft(line, index) |
7750 tmplName = self.getWordLeft(line, index) |
7746 if tmplName: |
7751 if tmplName: |
7747 if templateViewer.hasTemplate(tmplName, |
7752 if templateViewer.hasTemplate(tmplName, self.getLanguage()): |
7748 self.getLanguage()): |
|
7749 self.__applyTemplate(tmplName, self.getLanguage()) |
7753 self.__applyTemplate(tmplName, self.getLanguage()) |
7750 return |
7754 return |
7751 else: |
7755 else: |
7752 templateNames = templateViewer.getTemplateNames( |
7756 templateNames = templateViewer.getTemplateNames( |
7753 tmplName, self.getLanguage()) |
7757 tmplName, self.getLanguage() |
|
7758 ) |
7754 if len(templateNames) == 1: |
7759 if len(templateNames) == 1: |
7755 self.__applyTemplate(templateNames[0], |
7760 self.__applyTemplate(templateNames[0], self.getLanguage()) |
7756 self.getLanguage()) |
|
7757 return |
7761 return |
7758 elif len(templateNames) > 1: |
7762 elif len(templateNames) > 1: |
7759 self.showUserList( |
7763 self.showUserList( |
7760 TemplateCompletionListID, |
7764 TemplateCompletionListID, |
7761 ["{0}?{1:d}".format(t, self.TemplateImageID) |
7765 [ |
7762 for t in templateNames]) |
7766 "{0}?{1:d}".format(t, self.TemplateImageID) |
|
7767 for t in templateNames |
|
7768 ], |
|
7769 ) |
7763 return |
7770 return |
7764 |
7771 |
7765 elif cmd == QsciScintilla.SCI_DELETEBACK: |
7772 elif cmd == QsciScintilla.SCI_DELETEBACK: |
7766 line, index = self.getCursorPosition() |
7773 line, index = self.getCursorPosition() |
7767 text = self.text(line)[index - 1:index + 1] |
7774 text = self.text(line)[index - 1 : index + 1] |
7768 matchingPairs = ['()', '[]', '{}', '<>', "''", '""'] |
7775 matchingPairs = ["()", "[]", "{}", "<>", "''", '""'] |
7769 # __IGNORE_WARNING_M613__ |
7776 # __IGNORE_WARNING_M613__ |
7770 if text in matchingPairs: |
7777 if text in matchingPairs: |
7771 self.delete() |
7778 self.delete() |
7772 |
7779 |
7773 super().editorCommand(cmd) |
7780 super().editorCommand(cmd) |
7774 |
7781 |
7775 def __applyTemplate(self, templateName, language): |
7782 def __applyTemplate(self, templateName, language): |
7776 """ |
7783 """ |
7777 Private method to apply a template by name. |
7784 Private method to apply a template by name. |
7778 |
7785 |
7779 @param templateName name of the template to apply (string) |
7786 @param templateName name of the template to apply (string) |
7780 @param language name of the language (group) to get the template |
7787 @param language name of the language (group) to get the template |
7781 from (string) |
7788 from (string) |
7782 """ |
7789 """ |
7783 try: |
7790 try: |
7784 templateViewer = ericApp().getObject("TemplateViewer") |
7791 templateViewer = ericApp().getObject("TemplateViewer") |
7785 except KeyError: |
7792 except KeyError: |
7786 # template viewer is not active |
7793 # template viewer is not active |
7787 return |
7794 return |
7788 |
7795 |
7789 if templateViewer.hasTemplate(templateName, self.getLanguage()): |
7796 if templateViewer.hasTemplate(templateName, self.getLanguage()): |
7790 self.extendSelectionWordLeft() |
7797 self.extendSelectionWordLeft() |
7791 templateViewer.applyNamedTemplate(templateName, |
7798 templateViewer.applyNamedTemplate(templateName, self.getLanguage()) |
7792 self.getLanguage()) |
7799 |
7793 |
|
7794 ####################################################################### |
7800 ####################################################################### |
7795 ## Project related methods |
7801 ## Project related methods |
7796 ####################################################################### |
7802 ####################################################################### |
7797 |
7803 |
7798 def __projectPropertiesChanged(self): |
7804 def __projectPropertiesChanged(self): |
7799 """ |
7805 """ |
7800 Private slot to handle changes of the project properties. |
7806 Private slot to handle changes of the project properties. |
7801 """ |
7807 """ |
7802 if self.spell: |
7808 if self.spell: |
7803 pwl, pel = self.project.getProjectDictionaries() |
7809 pwl, pel = self.project.getProjectDictionaries() |
7804 self.__setSpellingLanguage(self.project.getProjectSpellLanguage(), |
7810 self.__setSpellingLanguage( |
7805 pwl=pwl, pel=pel) |
7811 self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel |
7806 |
7812 ) |
|
7813 |
7807 editorConfigEol = self.__getEditorConfig("EOLMode", nodefault=True) |
7814 editorConfigEol = self.__getEditorConfig("EOLMode", nodefault=True) |
7808 if editorConfigEol is not None: |
7815 if editorConfigEol is not None: |
7809 self.setEolMode(editorConfigEol) |
7816 self.setEolMode(editorConfigEol) |
7810 else: |
7817 else: |
7811 self.setEolModeByEolString(self.project.getEolString()) |
7818 self.setEolModeByEolString(self.project.getEolString()) |
7812 self.convertEols(self.eolMode()) |
7819 self.convertEols(self.eolMode()) |
7813 |
7820 |
7814 def addedToProject(self): |
7821 def addedToProject(self): |
7815 """ |
7822 """ |
7816 Public method to signal, that this editor has been added to a project. |
7823 Public method to signal, that this editor has been added to a project. |
7817 """ |
7824 """ |
7818 if self.spell: |
7825 if self.spell: |
7819 pwl, pel = self.project.getProjectDictionaries() |
7826 pwl, pel = self.project.getProjectDictionaries() |
7820 self.__setSpellingLanguage(self.project.getProjectSpellLanguage(), |
7827 self.__setSpellingLanguage( |
7821 pwl=pwl, pel=pel) |
7828 self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel |
7822 |
7829 ) |
7823 self.project.projectPropertiesChanged.connect( |
7830 |
7824 self.__projectPropertiesChanged) |
7831 self.project.projectPropertiesChanged.connect(self.__projectPropertiesChanged) |
7825 |
7832 |
7826 def projectOpened(self): |
7833 def projectOpened(self): |
7827 """ |
7834 """ |
7828 Public slot to handle the opening of a project. |
7835 Public slot to handle the opening of a project. |
7829 """ |
7836 """ |
7830 if ( |
7837 if self.fileName and self.project.isProjectSource(self.fileName): |
7831 self.fileName and |
|
7832 self.project.isProjectSource(self.fileName) |
|
7833 ): |
|
7834 self.project.projectPropertiesChanged.connect( |
7838 self.project.projectPropertiesChanged.connect( |
7835 self.__projectPropertiesChanged) |
7839 self.__projectPropertiesChanged |
|
7840 ) |
7836 self.setSpellingForProject() |
7841 self.setSpellingForProject() |
7837 |
7842 |
7838 def projectClosed(self): |
7843 def projectClosed(self): |
7839 """ |
7844 """ |
7840 Public slot to handle the closing of a project. |
7845 Public slot to handle the closing of a project. |
7841 """ |
7846 """ |
7842 with contextlib.suppress(TypeError): |
7847 with contextlib.suppress(TypeError): |
7843 self.project.projectPropertiesChanged.disconnect( |
7848 self.project.projectPropertiesChanged.disconnect( |
7844 self.__projectPropertiesChanged) |
7849 self.__projectPropertiesChanged |
7845 |
7850 ) |
|
7851 |
7846 ####################################################################### |
7852 ####################################################################### |
7847 ## Spell checking related methods |
7853 ## Spell checking related methods |
7848 ####################################################################### |
7854 ####################################################################### |
7849 |
7855 |
7850 def getSpellingLanguage(self): |
7856 def getSpellingLanguage(self): |
7851 """ |
7857 """ |
7852 Public method to get the current spelling language. |
7858 Public method to get the current spelling language. |
7853 |
7859 |
7854 @return current spelling language |
7860 @return current spelling language |
7855 @rtype str |
7861 @rtype str |
7856 """ |
7862 """ |
7857 if self.spell: |
7863 if self.spell: |
7858 return self.spell.getLanguage() |
7864 return self.spell.getLanguage() |
7859 |
7865 |
7860 return "" |
7866 return "" |
7861 |
7867 |
7862 def __setSpellingLanguage(self, language, pwl="", pel=""): |
7868 def __setSpellingLanguage(self, language, pwl="", pel=""): |
7863 """ |
7869 """ |
7864 Private slot to set the spell checking language. |
7870 Private slot to set the spell checking language. |
7865 |
7871 |
7866 @param language spell checking language to be set (string) |
7872 @param language spell checking language to be set (string) |
7867 @param pwl name of the personal/project word list (string) |
7873 @param pwl name of the personal/project word list (string) |
7868 @param pel name of the personal/project exclude list (string) |
7874 @param pel name of the personal/project exclude list (string) |
7869 """ |
7875 """ |
7870 if self.spell and self.spell.getLanguage() != language: |
7876 if self.spell and self.spell.getLanguage() != language: |
7871 self.spell.setLanguage(language, pwl=pwl, pel=pel) |
7877 self.spell.setLanguage(language, pwl=pwl, pel=pel) |
7872 self.spell.checkDocumentIncrementally() |
7878 self.spell.checkDocumentIncrementally() |
7873 |
7879 |
7874 def __setSpelling(self): |
7880 def __setSpelling(self): |
7875 """ |
7881 """ |
7876 Private method to initialize the spell checking functionality. |
7882 Private method to initialize the spell checking functionality. |
7877 """ |
7883 """ |
7878 if Preferences.getEditor("SpellCheckingEnabled"): |
7884 if Preferences.getEditor("SpellCheckingEnabled"): |
7879 self.__spellCheckStringsOnly = Preferences.getEditor( |
7885 self.__spellCheckStringsOnly = Preferences.getEditor( |
7880 "SpellCheckStringsOnly") |
7886 "SpellCheckStringsOnly" |
|
7887 ) |
7881 if self.spell is None: |
7888 if self.spell is None: |
7882 self.spell = SpellChecker(self, self.spellingIndicator, |
7889 self.spell = SpellChecker( |
7883 checkRegion=self.isSpellCheckRegion) |
7890 self, self.spellingIndicator, checkRegion=self.isSpellCheckRegion |
|
7891 ) |
7884 self.setSpellingForProject() |
7892 self.setSpellingForProject() |
7885 self.spell.setMinimumWordSize( |
7893 self.spell.setMinimumWordSize( |
7886 Preferences.getEditor("SpellCheckingMinWordSize")) |
7894 Preferences.getEditor("SpellCheckingMinWordSize") |
7887 |
7895 ) |
|
7896 |
7888 self.setAutoSpellChecking() |
7897 self.setAutoSpellChecking() |
7889 else: |
7898 else: |
7890 self.spell = None |
7899 self.spell = None |
7891 self.clearAllIndicators(self.spellingIndicator) |
7900 self.clearAllIndicators(self.spellingIndicator) |
7892 |
7901 |
7894 """ |
7903 """ |
7895 Public method to set the spell checking options for files belonging |
7904 Public method to set the spell checking options for files belonging |
7896 to the current project. |
7905 to the current project. |
7897 """ |
7906 """ |
7898 if ( |
7907 if ( |
7899 self.fileName and |
7908 self.fileName |
7900 self.project.isOpen() and |
7909 and self.project.isOpen() |
7901 self.project.isProjectSource(self.fileName) |
7910 and self.project.isProjectSource(self.fileName) |
7902 ): |
7911 ): |
7903 pwl, pel = self.project.getProjectDictionaries() |
7912 pwl, pel = self.project.getProjectDictionaries() |
7904 self.__setSpellingLanguage(self.project.getProjectSpellLanguage(), |
7913 self.__setSpellingLanguage( |
7905 pwl=pwl, pel=pel) |
7914 self.project.getProjectSpellLanguage(), pwl=pwl, pel=pel |
7906 |
7915 ) |
|
7916 |
7907 def setAutoSpellChecking(self): |
7917 def setAutoSpellChecking(self): |
7908 """ |
7918 """ |
7909 Public method to set the automatic spell checking. |
7919 Public method to set the automatic spell checking. |
7910 """ |
7920 """ |
7911 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
7921 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
7912 with contextlib.suppress(TypeError): |
7922 with contextlib.suppress(TypeError): |
7913 self.SCN_CHARADDED.connect( |
7923 self.SCN_CHARADDED.connect( |
7914 self.__spellCharAdded, Qt.ConnectionType.UniqueConnection) |
7924 self.__spellCharAdded, Qt.ConnectionType.UniqueConnection |
|
7925 ) |
7915 self.spell.checkDocumentIncrementally() |
7926 self.spell.checkDocumentIncrementally() |
7916 else: |
7927 else: |
7917 with contextlib.suppress(TypeError): |
7928 with contextlib.suppress(TypeError): |
7918 self.SCN_CHARADDED.disconnect(self.__spellCharAdded) |
7929 self.SCN_CHARADDED.disconnect(self.__spellCharAdded) |
7919 self.clearAllIndicators(self.spellingIndicator) |
7930 self.clearAllIndicators(self.spellingIndicator) |
7920 |
7931 |
7921 def isSpellCheckRegion(self, pos): |
7932 def isSpellCheckRegion(self, pos): |
7922 """ |
7933 """ |
7923 Public method to check, if the given position is within a region, that |
7934 Public method to check, if the given position is within a region, that |
7924 should be spell checked. |
7935 should be spell checked. |
7925 |
7936 |
7926 For files with a configured full text file extension all regions will |
7937 For files with a configured full text file extension all regions will |
7927 be regarded as to be checked. Depending on configuration, all unknown |
7938 be regarded as to be checked. Depending on configuration, all unknown |
7928 files (i.e. those without a file extension) will be checked fully as |
7939 files (i.e. those without a file extension) will be checked fully as |
7929 well. |
7940 well. |
7930 |
7941 |
7931 @param pos position to be checked |
7942 @param pos position to be checked |
7932 @type int |
7943 @type int |
7933 @return flag indicating pos is in a spell check region |
7944 @return flag indicating pos is in a spell check region |
7934 @rtype bool |
7945 @rtype bool |
7935 """ |
7946 """ |
7936 if self.__spellCheckStringsOnly: |
7947 if self.__spellCheckStringsOnly: |
7937 if ( |
7948 if ( |
7938 (self.__fileNameExtension in |
7949 self.__fileNameExtension |
7939 Preferences.getEditor("FullSpellCheckExtensions")) or |
7950 in Preferences.getEditor("FullSpellCheckExtensions") |
7940 (not self.__fileNameExtension and |
7951 ) or ( |
7941 Preferences.getEditor("FullSpellCheckUnknown")) |
7952 not self.__fileNameExtension |
|
7953 and Preferences.getEditor("FullSpellCheckUnknown") |
7942 ): |
7954 ): |
7943 return True |
7955 return True |
7944 else: |
7956 else: |
7945 style = self.styleAt(pos) |
7957 style = self.styleAt(pos) |
7946 if self.lexer_ is not None: |
7958 if self.lexer_ is not None: |
7947 return ( |
7959 return self.lexer_.isCommentStyle( |
7948 self.lexer_.isCommentStyle(style) or |
7960 style |
7949 self.lexer_.isStringStyle(style) |
7961 ) or self.lexer_.isStringStyle(style) |
7950 ) |
7962 |
7951 |
|
7952 return True |
7963 return True |
7953 |
7964 |
7954 @pyqtSlot(int) |
7965 @pyqtSlot(int) |
7955 def __spellCharAdded(self, charNumber): |
7966 def __spellCharAdded(self, charNumber): |
7956 """ |
7967 """ |
7957 Private slot called to handle the user entering a character. |
7968 Private slot called to handle the user entering a character. |
7958 |
7969 |
7959 @param charNumber value of the character entered (integer) |
7970 @param charNumber value of the character entered (integer) |
7960 """ |
7971 """ |
7961 if self.spell: |
7972 if self.spell: |
7962 if not chr(charNumber).isalnum(): |
7973 if not chr(charNumber).isalnum(): |
7963 self.spell.checkWord( |
7974 self.spell.checkWord(self.positionBefore(self.currentPosition()), True) |
7964 self.positionBefore(self.currentPosition()), True) |
7975 elif self.hasIndicator(self.spellingIndicator, self.currentPosition()): |
7965 elif self.hasIndicator( |
|
7966 self.spellingIndicator, self.currentPosition()): |
|
7967 self.spell.checkWord(self.currentPosition()) |
7976 self.spell.checkWord(self.currentPosition()) |
7968 |
7977 |
7969 def checkSpelling(self): |
7978 def checkSpelling(self): |
7970 """ |
7979 """ |
7971 Public slot to perform an interactive spell check of the document. |
7980 Public slot to perform an interactive spell check of the document. |
7972 """ |
7981 """ |
7973 if self.spell: |
7982 if self.spell: |
7974 cline, cindex = self.getCursorPosition() |
7983 cline, cindex = self.getCursorPosition() |
7975 from .SpellCheckingDialog import SpellCheckingDialog |
7984 from .SpellCheckingDialog import SpellCheckingDialog |
|
7985 |
7976 dlg = SpellCheckingDialog(self.spell, 0, self.length(), self) |
7986 dlg = SpellCheckingDialog(self.spell, 0, self.length(), self) |
7977 dlg.exec() |
7987 dlg.exec() |
7978 self.setCursorPosition(cline, cindex) |
7988 self.setCursorPosition(cline, cindex) |
7979 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
7989 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
7980 self.spell.checkDocumentIncrementally() |
7990 self.spell.checkDocumentIncrementally() |
7981 |
7991 |
7982 def __checkSpellingSelection(self): |
7992 def __checkSpellingSelection(self): |
7983 """ |
7993 """ |
7984 Private slot to spell check the current selection. |
7994 Private slot to spell check the current selection. |
7985 """ |
7995 """ |
7986 from .SpellCheckingDialog import SpellCheckingDialog |
7996 from .SpellCheckingDialog import SpellCheckingDialog |
|
7997 |
7987 sline, sindex, eline, eindex = self.getSelection() |
7998 sline, sindex, eline, eindex = self.getSelection() |
7988 startPos = self.positionFromLineIndex(sline, sindex) |
7999 startPos = self.positionFromLineIndex(sline, sindex) |
7989 endPos = self.positionFromLineIndex(eline, eindex) |
8000 endPos = self.positionFromLineIndex(eline, eindex) |
7990 dlg = SpellCheckingDialog(self.spell, startPos, endPos, self) |
8001 dlg = SpellCheckingDialog(self.spell, startPos, endPos, self) |
7991 dlg.exec() |
8002 dlg.exec() |
7992 |
8003 |
7993 def __checkSpellingWord(self): |
8004 def __checkSpellingWord(self): |
7994 """ |
8005 """ |
7995 Private slot to check the word below the spelling context menu. |
8006 Private slot to check the word below the spelling context menu. |
7996 """ |
8007 """ |
7997 from .SpellCheckingDialog import SpellCheckingDialog |
8008 from .SpellCheckingDialog import SpellCheckingDialog |
|
8009 |
7998 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8010 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
7999 wordStart, wordEnd = self.getWordBoundaries(line, index) |
8011 wordStart, wordEnd = self.getWordBoundaries(line, index) |
8000 wordStartPos = self.positionFromLineIndex(line, wordStart) |
8012 wordStartPos = self.positionFromLineIndex(line, wordStart) |
8001 wordEndPos = self.positionFromLineIndex(line, wordEnd) |
8013 wordEndPos = self.positionFromLineIndex(line, wordEnd) |
8002 dlg = SpellCheckingDialog(self.spell, wordStartPos, wordEndPos, self) |
8014 dlg = SpellCheckingDialog(self.spell, wordStartPos, wordEndPos, self) |
8003 dlg.exec() |
8015 dlg.exec() |
8004 |
8016 |
8005 def __showContextMenuSpelling(self): |
8017 def __showContextMenuSpelling(self): |
8006 """ |
8018 """ |
8007 Private slot to set up the spelling menu before it is shown. |
8019 Private slot to set up the spelling menu before it is shown. |
8008 """ |
8020 """ |
8009 self.spellingMenu.clear() |
8021 self.spellingMenu.clear() |
8010 self.spellingSuggActs = [] |
8022 self.spellingSuggActs = [] |
8011 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8023 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8012 word = self.getWord(line, index) |
8024 word = self.getWord(line, index) |
8013 suggestions = self.spell.getSuggestions(word) |
8025 suggestions = self.spell.getSuggestions(word) |
8014 for suggestion in suggestions[:5]: |
8026 for suggestion in suggestions[:5]: |
8015 self.spellingSuggActs.append( |
8027 self.spellingSuggActs.append(self.spellingMenu.addAction(suggestion)) |
8016 self.spellingMenu.addAction(suggestion)) |
|
8017 if suggestions: |
8028 if suggestions: |
8018 self.spellingMenu.addSeparator() |
8029 self.spellingMenu.addSeparator() |
8019 self.spellingMenu.addAction( |
8030 self.spellingMenu.addAction( |
8020 UI.PixmapCache.getIcon("spellchecking"), |
8031 UI.PixmapCache.getIcon("spellchecking"), |
8021 self.tr("Check spelling..."), self.__checkSpellingWord) |
8032 self.tr("Check spelling..."), |
|
8033 self.__checkSpellingWord, |
|
8034 ) |
8022 self.spellingMenu.addAction( |
8035 self.spellingMenu.addAction( |
8023 self.tr("Add to dictionary"), self.__addToSpellingDictionary) |
8036 self.tr("Add to dictionary"), self.__addToSpellingDictionary |
8024 self.spellingMenu.addAction( |
8037 ) |
8025 self.tr("Ignore All"), self.__ignoreSpellingAlways) |
8038 self.spellingMenu.addAction(self.tr("Ignore All"), self.__ignoreSpellingAlways) |
8026 |
8039 |
8027 self.showMenu.emit("Spelling", self.spellingMenu, self) |
8040 self.showMenu.emit("Spelling", self.spellingMenu, self) |
8028 |
8041 |
8029 def __contextMenuSpellingTriggered(self, action): |
8042 def __contextMenuSpellingTriggered(self, action): |
8030 """ |
8043 """ |
8031 Private slot to handle the selection of a suggestion of the spelling |
8044 Private slot to handle the selection of a suggestion of the spelling |
8032 context menu. |
8045 context menu. |
8033 |
8046 |
8034 @param action reference to the action that was selected (QAction) |
8047 @param action reference to the action that was selected (QAction) |
8035 """ |
8048 """ |
8036 if action in self.spellingSuggActs: |
8049 if action in self.spellingSuggActs: |
8037 replacement = action.text() |
8050 replacement = action.text() |
8038 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8051 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8040 self.setSelection(line, wordStart, line, wordEnd) |
8053 self.setSelection(line, wordStart, line, wordEnd) |
8041 self.beginUndoAction() |
8054 self.beginUndoAction() |
8042 self.removeSelectedText() |
8055 self.removeSelectedText() |
8043 self.insert(replacement) |
8056 self.insert(replacement) |
8044 self.endUndoAction() |
8057 self.endUndoAction() |
8045 |
8058 |
8046 def __addToSpellingDictionary(self): |
8059 def __addToSpellingDictionary(self): |
8047 """ |
8060 """ |
8048 Private slot to add the word below the spelling context menu to the |
8061 Private slot to add the word below the spelling context menu to the |
8049 dictionary. |
8062 dictionary. |
8050 """ |
8063 """ |
8051 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8064 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8052 word = self.getWord(line, index) |
8065 word = self.getWord(line, index) |
8053 self.spell.add(word) |
8066 self.spell.add(word) |
8054 |
8067 |
8055 wordStart, wordEnd = self.getWordBoundaries(line, index) |
8068 wordStart, wordEnd = self.getWordBoundaries(line, index) |
8056 self.clearIndicator(self.spellingIndicator, line, wordStart, |
8069 self.clearIndicator(self.spellingIndicator, line, wordStart, line, wordEnd) |
8057 line, wordEnd) |
|
8058 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8070 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8059 self.spell.checkDocumentIncrementally() |
8071 self.spell.checkDocumentIncrementally() |
8060 |
8072 |
8061 def __removeFromSpellingDictionary(self): |
8073 def __removeFromSpellingDictionary(self): |
8062 """ |
8074 """ |
8063 Private slot to remove the word below the context menu to the |
8075 Private slot to remove the word below the context menu to the |
8064 dictionary. |
8076 dictionary. |
8065 """ |
8077 """ |
8066 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8078 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8067 word = self.getWord(line, index) |
8079 word = self.getWord(line, index) |
8068 self.spell.remove(word) |
8080 self.spell.remove(word) |
8069 |
8081 |
8070 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8082 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8071 self.spell.checkDocumentIncrementally() |
8083 self.spell.checkDocumentIncrementally() |
8072 |
8084 |
8073 def __ignoreSpellingAlways(self): |
8085 def __ignoreSpellingAlways(self): |
8074 """ |
8086 """ |
8075 Private to always ignore the word below the spelling context menu. |
8087 Private to always ignore the word below the spelling context menu. |
8076 """ |
8088 """ |
8077 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8089 line, index = self.lineIndexFromPosition(self.spellingMenuPos) |
8078 word = self.getWord(line, index) |
8090 word = self.getWord(line, index) |
8079 self.spell.ignoreAlways(word) |
8091 self.spell.ignoreAlways(word) |
8080 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8092 if Preferences.getEditor("AutoSpellCheckingEnabled"): |
8081 self.spell.checkDocumentIncrementally() |
8093 self.spell.checkDocumentIncrementally() |
8082 |
8094 |
8083 ####################################################################### |
8095 ####################################################################### |
8084 ## Cooperation related methods |
8096 ## Cooperation related methods |
8085 ####################################################################### |
8097 ####################################################################### |
8086 |
8098 |
8087 def getSharingStatus(self): |
8099 def getSharingStatus(self): |
8088 """ |
8100 """ |
8089 Public method to get some share status info. |
8101 Public method to get some share status info. |
8090 |
8102 |
8091 @return tuple indicating, if the editor is sharable, the sharing |
8103 @return tuple indicating, if the editor is sharable, the sharing |
8092 status, if it is inside a locally initiated shared edit session |
8104 status, if it is inside a locally initiated shared edit session |
8093 and if it is inside a remotely initiated shared edit session |
8105 and if it is inside a remotely initiated shared edit session |
8094 (boolean, boolean, boolean, boolean) |
8106 (boolean, boolean, boolean, boolean) |
8095 """ |
8107 """ |
8096 return ( |
8108 return ( |
8097 (bool(self.fileName) and |
8109 ( |
8098 self.project.isOpen() and |
8110 bool(self.fileName) |
8099 self.project.isProjectFile(self.fileName)), |
8111 and self.project.isOpen() |
|
8112 and self.project.isProjectFile(self.fileName) |
|
8113 ), |
8100 self.__isShared, |
8114 self.__isShared, |
8101 self.__inSharedEdit, |
8115 self.__inSharedEdit, |
8102 self.__inRemoteSharedEdit |
8116 self.__inRemoteSharedEdit, |
8103 ) |
8117 ) |
8104 |
8118 |
8105 def shareConnected(self, connected): |
8119 def shareConnected(self, connected): |
8106 """ |
8120 """ |
8107 Public slot to handle a change of the connected state. |
8121 Public slot to handle a change of the connected state. |
8108 |
8122 |
8109 @param connected flag indicating the connected state (boolean) |
8123 @param connected flag indicating the connected state (boolean) |
8110 """ |
8124 """ |
8111 if not connected: |
8125 if not connected: |
8112 self.__inRemoteSharedEdit = False |
8126 self.__inRemoteSharedEdit = False |
8113 self.setReadOnly(False) |
8127 self.setReadOnly(False) |
8114 self.__updateReadOnly() |
8128 self.__updateReadOnly() |
8115 self.cancelSharedEdit(send=False) |
8129 self.cancelSharedEdit(send=False) |
8116 self.__isSyncing = False |
8130 self.__isSyncing = False |
8117 self.__receivedWhileSyncing = [] |
8131 self.__receivedWhileSyncing = [] |
8118 |
8132 |
8119 def shareEditor(self, share): |
8133 def shareEditor(self, share): |
8120 """ |
8134 """ |
8121 Public slot to set the shared status of the editor. |
8135 Public slot to set the shared status of the editor. |
8122 |
8136 |
8123 @param share flag indicating the share status (boolean) |
8137 @param share flag indicating the share status (boolean) |
8124 """ |
8138 """ |
8125 self.__isShared = share |
8139 self.__isShared = share |
8126 if not share: |
8140 if not share: |
8127 self.shareConnected(False) |
8141 self.shareConnected(False) |
8128 |
8142 |
8129 def startSharedEdit(self): |
8143 def startSharedEdit(self): |
8130 """ |
8144 """ |
8131 Public slot to start a shared edit session for the editor. |
8145 Public slot to start a shared edit session for the editor. |
8132 """ |
8146 """ |
8133 self.__inSharedEdit = True |
8147 self.__inSharedEdit = True |
8134 self.__savedText = self.text() |
8148 self.__savedText = self.text() |
8135 hashStr = str( |
8149 hashStr = str( |
8136 QCryptographicHash.hash( |
8150 QCryptographicHash.hash( |
8137 Utilities.encode(self.__savedText, self.encoding)[0], |
8151 Utilities.encode(self.__savedText, self.encoding)[0], |
8138 QCryptographicHash.Algorithm.Sha1).toHex(), |
8152 QCryptographicHash.Algorithm.Sha1, |
8139 encoding="utf-8") |
8153 ).toHex(), |
|
8154 encoding="utf-8", |
|
8155 ) |
8140 self.__send(Editor.StartEditToken, hashStr) |
8156 self.__send(Editor.StartEditToken, hashStr) |
8141 |
8157 |
8142 def sendSharedEdit(self): |
8158 def sendSharedEdit(self): |
8143 """ |
8159 """ |
8144 Public slot to end a shared edit session for the editor and |
8160 Public slot to end a shared edit session for the editor and |
8145 send the changes. |
8161 send the changes. |
8146 """ |
8162 """ |
8147 commands = self.__calculateChanges(self.__savedText, self.text()) |
8163 commands = self.__calculateChanges(self.__savedText, self.text()) |
8148 self.__send(Editor.EndEditToken, commands) |
8164 self.__send(Editor.EndEditToken, commands) |
8149 self.__inSharedEdit = False |
8165 self.__inSharedEdit = False |
8150 self.__savedText = "" |
8166 self.__savedText = "" |
8151 |
8167 |
8152 def cancelSharedEdit(self, send=True): |
8168 def cancelSharedEdit(self, send=True): |
8153 """ |
8169 """ |
8154 Public slot to cancel a shared edit session for the editor. |
8170 Public slot to cancel a shared edit session for the editor. |
8155 |
8171 |
8156 @param send flag indicating to send the CancelEdit command (boolean) |
8172 @param send flag indicating to send the CancelEdit command (boolean) |
8157 """ |
8173 """ |
8158 self.__inSharedEdit = False |
8174 self.__inSharedEdit = False |
8159 self.__savedText = "" |
8175 self.__savedText = "" |
8160 if send: |
8176 if send: |
8161 self.__send(Editor.CancelEditToken) |
8177 self.__send(Editor.CancelEditToken) |
8162 |
8178 |
8163 def __send(self, token, args=None): |
8179 def __send(self, token, args=None): |
8164 """ |
8180 """ |
8165 Private method to send an editor command to remote editors. |
8181 Private method to send an editor command to remote editors. |
8166 |
8182 |
8167 @param token command token (string) |
8183 @param token command token (string) |
8168 @param args arguments for the command (string) |
8184 @param args arguments for the command (string) |
8169 """ |
8185 """ |
8170 if self.vm.isConnected(): |
8186 if self.vm.isConnected(): |
8171 msg = "" |
8187 msg = "" |
8172 if token in (Editor.StartEditToken, |
8188 if token in ( |
8173 Editor.EndEditToken, |
8189 Editor.StartEditToken, |
8174 Editor.RequestSyncToken, |
8190 Editor.EndEditToken, |
8175 Editor.SyncToken): |
8191 Editor.RequestSyncToken, |
8176 msg = "{0}{1}{2}".format( |
8192 Editor.SyncToken, |
8177 token, |
8193 ): |
8178 Editor.Separator, |
8194 msg = "{0}{1}{2}".format(token, Editor.Separator, args) |
8179 args |
|
8180 ) |
|
8181 elif token == Editor.CancelEditToken: |
8195 elif token == Editor.CancelEditToken: |
8182 msg = "{0}{1}c".format( |
8196 msg = "{0}{1}c".format(token, Editor.Separator) |
8183 token, |
8197 |
8184 Editor.Separator |
|
8185 ) |
|
8186 |
|
8187 self.vm.send(self.fileName, msg) |
8198 self.vm.send(self.fileName, msg) |
8188 |
8199 |
8189 def receive(self, command): |
8200 def receive(self, command): |
8190 """ |
8201 """ |
8191 Public slot to handle received editor commands. |
8202 Public slot to handle received editor commands. |
8192 |
8203 |
8193 @param command command string (string) |
8204 @param command command string (string) |
8194 """ |
8205 """ |
8195 if self.__isShared: |
8206 if self.__isShared: |
8196 if ( |
8207 if self.__isSyncing and not command.startswith( |
8197 self.__isSyncing and |
8208 Editor.SyncToken + Editor.Separator |
8198 not command.startswith(Editor.SyncToken + Editor.Separator) |
|
8199 ): |
8209 ): |
8200 self.__receivedWhileSyncing.append(command) |
8210 self.__receivedWhileSyncing.append(command) |
8201 else: |
8211 else: |
8202 self.__dispatchCommand(command) |
8212 self.__dispatchCommand(command) |
8203 |
8213 |
8204 def __dispatchCommand(self, command): |
8214 def __dispatchCommand(self, command): |
8205 """ |
8215 """ |
8206 Private method to dispatch received commands. |
8216 Private method to dispatch received commands. |
8207 |
8217 |
8208 @param command command to be processed (string) |
8218 @param command command to be processed (string) |
8209 """ |
8219 """ |
8210 token, argsString = command.split(Editor.Separator, 1) |
8220 token, argsString = command.split(Editor.Separator, 1) |
8211 if token == Editor.StartEditToken: |
8221 if token == Editor.StartEditToken: |
8212 self.__processStartEditCommand(argsString) |
8222 self.__processStartEditCommand(argsString) |