RefactoringRope/RefactoringServer.py

branch
server_client_variant
changeset 189
2711fdd91925
parent 188
05fb0977ce1b
child 191
2af42804bca2
equal deleted inserted replaced
188:05fb0977ce1b 189:2711fdd91925
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2017 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the refactoring interface to rope.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_WARNING__
13 except NameError:
14 pass
15
16 import os
17 import sys
18
19 sys.path.insert(0, os.path.dirname(__file__))
20
21 from PyQt5.QtWidgets import QMenu, QApplication, QAction
22 from PyQt5.Qsci import QsciScintilla
23
24 from E5Gui.E5Application import e5App
25 from E5Gui import E5MessageBox
26 from E5Gui.E5Action import E5Action
27
28 from .JsonServer import JsonServer
29 from .RopeProgressDialog import RopeProgressDialog
30
31 import Utilities
32 import Preferences
33
34
35 class RefactoringServer(JsonServer):
36 """
37 Class implementing the refactoring interface to rope.
38 """
39 def __init__(self, plugin, parent=None):
40 """
41 Constructor
42
43 @param plugin reference to the plugin object
44 @param parent parent (QObject)
45 """
46 super(RefactoringServer, self).__init__(parent)
47
48 self.__plugin = plugin
49 self.__ui = parent
50 self.__e5project = e5App().getObject("Project")
51 self.__projectpath = ''
52 self.__projectLanguage = ""
53 self.__projectopen = False
54 self.__ropeConfig = {}
55
56 self.__mainMenu = None
57 self.__progressDialog = None
58 self.__helpDialog = None
59 self.__historyDialog = None
60 self.__refactoringDialogs = {}
61
62 from FileSystemCommands import E5FileSystemCommands
63 self.__fsCommands = E5FileSystemCommands(self.__e5project)
64
65 self.__methodMapping = {
66 "Config": self.__setConfig,
67 "Progress": self.__processProgress,
68 "QueryReferencesResult": self.__queryReferencesResult,
69 "QueryDefinitionResult": self.__queryDefinitionResult,
70 "QueryImplementationsResult": self.__queryImplementationsResult,
71 "SoaFinished": self.__soaFinished,
72
73 "FileSystemCommand": self.__fsCommands.processFileSystemCommand,
74
75 "ClientException": self.__processClientException,
76
77 "HistoryResult": self.__processHistoryResult,
78
79 "Changes": self.__processChanges,
80 }
81
82 def getMainWindow(self):
83 """
84 Public method to get a reference to the IDE main window.
85
86 @return reference to the IDE main window
87 @rtype UserInterface
88 """
89 return self.__ui
90
91 def initActions(self):
92 """
93 Public method to define the refactoring actions.
94 """
95 self.actions = []
96
97 #####################################################
98 ## Rename refactoring actions
99 #####################################################
100
101 self.refactoringRenameAct = E5Action(
102 self.tr('Rename'),
103 self.tr('&Rename'),
104 0, 0,
105 self, 'refactoring_rename')
106 self.refactoringRenameAct.setStatusTip(self.tr(
107 'Rename the highlighted object'))
108 self.refactoringRenameAct.setWhatsThis(self.tr(
109 """<b>Rename</b>"""
110 """<p>Rename the highlighted Python object.</p>"""
111 ))
112 self.refactoringRenameAct.triggered.connect(
113 self.__rename)
114 self.actions.append(self.refactoringRenameAct)
115
116 self.refactoringRenameLocalAct = E5Action(
117 self.tr('Local Rename'),
118 self.tr('&Local Rename'),
119 0, 0,
120 self, 'refactoring_rename_local')
121 self.refactoringRenameLocalAct.setStatusTip(self.tr(
122 'Rename the highlighted object in the current module only'))
123 self.refactoringRenameLocalAct.setWhatsThis(self.tr(
124 """<b>Local Rename</b>"""
125 """<p>Rename the highlighted Python object in the current"""
126 """ module only.</p>"""
127 ))
128 self.refactoringRenameLocalAct.triggered.connect(
129 self.__renameLocal)
130 self.actions.append(self.refactoringRenameLocalAct)
131
132 self.refactoringRenameModuleAct = E5Action(
133 self.tr('Rename Current Module'),
134 self.tr('Rename Current Module'),
135 0, 0,
136 self, 'refactoring_rename_module')
137 self.refactoringRenameModuleAct.setStatusTip(self.tr(
138 'Rename the current module'))
139 self.refactoringRenameModuleAct.setWhatsThis(self.tr(
140 """<b>Rename Current Module</b>"""
141 """<p>Rename the current module.</p>"""
142 ))
143 self.refactoringRenameModuleAct.triggered.connect(
144 self.__renameModule)
145 self.actions.append(self.refactoringRenameModuleAct)
146
147 self.refactoringChangeOccurrencesAct = E5Action(
148 self.tr('Change Occurrences'),
149 self.tr('Change &Occurrences'),
150 0, 0,
151 self, 'refactoring_change_occurrences')
152 self.refactoringChangeOccurrencesAct.setStatusTip(self.tr(
153 'Change all occurrences in the local scope'))
154 self.refactoringChangeOccurrencesAct.setWhatsThis(self.tr(
155 """<b>Change Occurrences</b>"""
156 """<p>Change all occurrences in the local scope.</p>"""
157 ))
158 self.refactoringChangeOccurrencesAct.triggered.connect(
159 self.__changeOccurrences)
160 self.actions.append(self.refactoringChangeOccurrencesAct)
161
162 #####################################################
163 ## Extract refactoring actions
164 #####################################################
165
166 self.refactoringExtractMethodAct = E5Action(
167 self.tr('Extract method'),
168 self.tr('Extract &Method'),
169 0, 0,
170 self, 'refactoring_extract_method')
171 self.refactoringExtractMethodAct.setStatusTip(self.tr(
172 'Extract the highlighted area as a method'))
173 self.refactoringExtractMethodAct.setWhatsThis(self.tr(
174 """<b>Extract method</b>"""
175 """<p>Extract the highlighted area as a method or function.</p>"""
176 ))
177 self.refactoringExtractMethodAct.triggered.connect(
178 self.__extractMethod)
179 self.actions.append(self.refactoringExtractMethodAct)
180
181 self.refactoringExtractLocalVariableAct = E5Action(
182 self.tr('Extract local variable'),
183 self.tr('&Extract Local Variable'),
184 0, 0,
185 self, 'refactoring_extract_variable')
186 self.refactoringExtractLocalVariableAct.setStatusTip(self.tr(
187 'Extract the highlighted area as a local variable'))
188 self.refactoringExtractLocalVariableAct.setWhatsThis(self.tr(
189 """<b>Extract local variable</b>"""
190 """<p>Extract the highlighted area as a local variable.</p>"""
191 ))
192 self.refactoringExtractLocalVariableAct.triggered.connect(
193 self.__extractLocalVariable)
194 self.actions.append(self.refactoringExtractLocalVariableAct)
195
196 #####################################################
197 ## Inline refactoring actions
198 #####################################################
199
200 self.refactoringInlineAct = E5Action(
201 self.tr('Inline'),
202 self.tr('&Inline'),
203 0, 0,
204 self, 'refactoring_inline')
205 self.refactoringInlineAct.setStatusTip(self.tr(
206 'Inlines the selected local variable or method'))
207 self.refactoringInlineAct.setWhatsThis(self.tr(
208 """<b>Inline</b>"""
209 """<p>Inlines the selected local variable or method.</p>"""
210 ))
211 self.refactoringInlineAct.triggered.connect(
212 self.__inline)
213 self.actions.append(self.refactoringInlineAct)
214
215 #####################################################
216 ## Move refactoring actions
217 #####################################################
218
219 self.refactoringMoveMethodAct = E5Action(
220 self.tr('Move method'),
221 self.tr('Mo&ve Method'),
222 0, 0,
223 self, 'refactoring_move_method')
224 self.refactoringMoveMethodAct.setStatusTip(self.tr(
225 'Move the highlighted method to another class'))
226 self.refactoringMoveMethodAct.setWhatsThis(self.tr(
227 """<b>Move method</b>"""
228 """<p>Move the highlighted method to another class.</p>"""
229 ))
230 self.refactoringMoveMethodAct.triggered.connect(
231 lambda: self.__move("move_method"))
232 self.actions.append(self.refactoringMoveMethodAct)
233
234 self.refactoringMoveModuleAct = E5Action(
235 self.tr('Move current module'),
236 self.tr('Move Current Module'),
237 0, 0,
238 self, 'refactoring_move_module')
239 self.refactoringMoveModuleAct.setStatusTip(self.tr(
240 'Move the current module to another package'))
241 self.refactoringMoveModuleAct.setWhatsThis(self.tr(
242 """<b>Move current module</b>"""
243 """<p>Move the current module to another package.</p>"""
244 ))
245 self.refactoringMoveModuleAct.triggered.connect(
246 lambda: self.__move("move_module"))
247 self.actions.append(self.refactoringMoveModuleAct)
248
249 #####################################################
250 ## Use function refactoring action
251 #####################################################
252
253 self.refactoringUseFunctionAct = E5Action(
254 self.tr('Use Function'),
255 self.tr('Use Function'),
256 0, 0,
257 self, 'refactoring_use_function')
258 self.refactoringUseFunctionAct.setStatusTip(self.tr(
259 'Use a function wherever possible.'))
260 self.refactoringUseFunctionAct.setWhatsThis(self.tr(
261 """<b>Use function</b>"""
262 """<p>Tries to use a function wherever possible.</p>"""
263 ))
264 self.refactoringUseFunctionAct.triggered.connect(
265 self.__useFunction)
266 self.actions.append(self.refactoringUseFunctionAct)
267
268 #####################################################
269 ## Introduce refactorings actions
270 #####################################################
271
272 self.refactoringIntroduceFactoryAct = E5Action(
273 self.tr('Introduce Factory Method'),
274 self.tr('Introduce &Factory Method'),
275 0, 0,
276 self, 'refactoring_introduce_factory_method')
277 self.refactoringIntroduceFactoryAct.setStatusTip(self.tr(
278 'Introduce a factory method or function'))
279 self.refactoringIntroduceFactoryAct.setWhatsThis(self.tr(
280 """<b>Introduce Factory Method</b>"""
281 """<p>Introduce a factory method or function.</p>"""
282 ))
283 self.refactoringIntroduceFactoryAct.triggered.connect(
284 self.__introduceFactoryMethod)
285 self.actions.append(self.refactoringIntroduceFactoryAct)
286
287 self.refactoringIntroduceParameterAct = E5Action(
288 self.tr('Introduce Parameter'),
289 self.tr('Introduce &Parameter'),
290 0, 0,
291 self, 'refactoring_introduce_parameter_method')
292 self.refactoringIntroduceParameterAct.setStatusTip(self.tr(
293 'Introduce a parameter in a function'))
294 self.refactoringIntroduceParameterAct.setWhatsThis(self.tr(
295 """<b>Introduce Parameter</b>"""
296 """<p>Introduce a parameter in a function.</p>"""
297 ))
298 self.refactoringIntroduceParameterAct.triggered.connect(
299 self.__introduceParameter)
300 self.actions.append(self.refactoringIntroduceParameterAct)
301
302 #####################################################
303 ## Import refactorings actions
304 #####################################################
305
306 self.refactoringImportsOrganizeAct = E5Action(
307 self.tr('Organize Imports'),
308 self.tr('&Organize Imports'),
309 0, 0,
310 self, 'refactoring_organize_imports')
311 self.refactoringImportsOrganizeAct.setStatusTip(self.tr(
312 'Sort imports according to PEP-8'))
313 self.refactoringImportsOrganizeAct.setWhatsThis(self.tr(
314 """<b>Organize Imports</b>"""
315 """<p>Sort imports according to PEP-8.</p>"""
316 ))
317 self.refactoringImportsOrganizeAct.triggered.connect(
318 self.__importsOrganize)
319 self.actions.append(self.refactoringImportsOrganizeAct)
320
321 self.refactoringImportsStarExpandAct = E5Action(
322 self.tr('Expand Star Imports'),
323 self.tr('E&xpand Star Imports'),
324 0, 0,
325 self, 'refactoring_expand_star_imports')
326 self.refactoringImportsStarExpandAct.setStatusTip(self.tr(
327 'Expand imports like "from xxx import *"'))
328 self.refactoringImportsStarExpandAct.setWhatsThis(self.tr(
329 """<b>Expand Star Imports</b>"""
330 """<p>Expand imports like "from xxx import *".</p>"""
331 """<p>Select the import to act on or none to do all."""
332 """ Unused imports are deleted.</p>"""
333 ))
334 self.refactoringImportsStarExpandAct.triggered.connect(
335 self.__importsExpandStar)
336 self.actions.append(self.refactoringImportsStarExpandAct)
337
338 self.refactoringImportsRelativeToAbsoluteAct = E5Action(
339 self.tr('Relative to Absolute'),
340 self.tr('Relative to &Absolute'),
341 0, 0,
342 self, 'refactoring_relative_to_absolute_imports')
343 self.refactoringImportsRelativeToAbsoluteAct.setStatusTip(self.tr(
344 'Transform relative imports to absolute ones'))
345 self.refactoringImportsRelativeToAbsoluteAct.setWhatsThis(self.tr(
346 """<b>Relative to Absolute</b>"""
347 """<p>Transform relative imports to absolute ones.</p>"""
348 """<p>Select the import to act on or none to do all."""
349 """ Unused imports are deleted.</p>"""
350 ))
351 self.refactoringImportsRelativeToAbsoluteAct.triggered.connect(
352 self.__importsRelativeToAbsolute)
353 self.actions.append(self.refactoringImportsRelativeToAbsoluteAct)
354
355 self.refactoringImportsFromsToImportsAct = E5Action(
356 self.tr('Froms to Imports'),
357 self.tr('Froms to &Imports'),
358 0, 0,
359 self, 'refactoring_froms_to_imports')
360 self.refactoringImportsFromsToImportsAct.setStatusTip(self.tr(
361 'Transform From imports to plain imports'))
362 self.refactoringImportsFromsToImportsAct.setWhatsThis(self.tr(
363 """<b>Froms to Imports</b>"""
364 """<p>Transform From imports to plain imports.</p>"""
365 """<p>Select the import to act on or none to do all."""
366 """ Unused imports are deleted.</p>"""
367 ))
368 self.refactoringImportsFromsToImportsAct.triggered.connect(
369 self.__importsFromToImport)
370 self.actions.append(self.refactoringImportsFromsToImportsAct)
371
372 self.refactoringImportsHandleLongAct = E5Action(
373 self.tr('Handle Long Imports'),
374 self.tr('Handle &Long Imports'),
375 0, 0,
376 self, 'refactoring_organize_imports')
377 self.refactoringImportsHandleLongAct.setStatusTip(self.tr(
378 'Transform long import statements to look better'))
379 self.refactoringImportsHandleLongAct.setWhatsThis(self.tr(
380 """<b>Handle Long Imports</b>"""
381 """<p>Transform long import statements to look better.</p>"""
382 """<p>Select the import to act on or none to do all."""
383 """ Unused imports are deleted.</p>"""
384 ))
385 self.refactoringImportsHandleLongAct.triggered.connect(
386 self.__importsHandleLong)
387 self.actions.append(self.refactoringImportsHandleLongAct)
388
389 #####################################################
390 ## Various refactorings actions
391 #####################################################
392
393 self.refactoringRestructureAct = E5Action(
394 self.tr('Restructure'),
395 self.tr('Res&tructure'),
396 0, 0,
397 self, 'refactoring_restructure')
398 self.refactoringRestructureAct.setStatusTip(self.tr(
399 'Restructure code'))
400 self.refactoringRestructureAct.setWhatsThis(self.tr(
401 """<b>Restructure</b>"""
402 """<p>Restructure code. See "Rope Help" for examples.</p>"""
403 ))
404 self.refactoringRestructureAct.triggered.connect(
405 self.__restructure)
406 self.actions.append(self.refactoringRestructureAct)
407
408 self.refactoringChangeSignatureAct = E5Action(
409 self.tr('Change Method Signature'),
410 self.tr('&Change Method Signature'),
411 0, 0,
412 self, 'refactoring_change_method_signature')
413 self.refactoringChangeSignatureAct.setStatusTip(self.tr(
414 'Change the signature of the selected method or function'))
415 self.refactoringChangeSignatureAct.setWhatsThis(self.tr(
416 """<b>Change Method Signature</b>"""
417 """<p>Change the signature of the selected method"""
418 """ or function.</p>"""
419 ))
420 self.refactoringChangeSignatureAct.triggered.connect(
421 self.__changeSignature)
422 self.actions.append(self.refactoringChangeSignatureAct)
423
424 self.refactoringInlineArgumentDefaultAct = E5Action(
425 self.tr('Inline Argument Default'),
426 self.tr('Inline &Argument Default'),
427 0, 0,
428 self, 'refactoring_inline_argument_default')
429 self.refactoringInlineArgumentDefaultAct.setStatusTip(self.tr(
430 'Inline a parameters default value'))
431 self.refactoringInlineArgumentDefaultAct.setWhatsThis(self.tr(
432 """<b>Inline Argument Default</b>"""
433 """<p>Inline a parameters default value.</p>"""
434 ))
435 self.refactoringInlineArgumentDefaultAct.triggered.connect(
436 self.__inlineArgumentDefault)
437 self.actions.append(self.refactoringInlineArgumentDefaultAct)
438
439 self.refactoringTransformModuleAct = E5Action(
440 self.tr('Transform Module to Package'),
441 self.tr('Transform Module to Package'),
442 0, 0,
443 self, 'refactoring_transform_module_to_package')
444 self.refactoringTransformModuleAct.setStatusTip(self.tr(
445 'Transform the current module to a package'))
446 self.refactoringTransformModuleAct.setWhatsThis(self.tr(
447 """<b>Transform Module to Package</b>"""
448 """<p>Transform the current module to a package.</p>"""
449 ))
450 self.refactoringTransformModuleAct.triggered.connect(
451 self.__transformModuleToPackage)
452 self.actions.append(self.refactoringTransformModuleAct)
453
454 self.refactoringEncapsulateAttributeAct = E5Action(
455 self.tr('Encapsulate Attribute'),
456 self.tr('Encap&sulate Attribute'),
457 0, 0,
458 self, 'refactoring_encapsulate_attribute')
459 self.refactoringEncapsulateAttributeAct.setStatusTip(self.tr(
460 'Generate a getter/setter for an attribute'))
461 self.refactoringEncapsulateAttributeAct.setWhatsThis(self.tr(
462 """<b>Encapsulate Attribute</b>"""
463 """<p>Generate a getter/setter for an attribute and changes"""
464 """ its occurrences to use them.</p>"""
465 ))
466 self.refactoringEncapsulateAttributeAct.triggered.connect(
467 self.__encapsulateAttribute)
468 self.actions.append(self.refactoringEncapsulateAttributeAct)
469
470 self.refactoringLocalVariableToAttributeAct = E5Action(
471 self.tr('Local Variable to Attribute'),
472 self.tr('Local Varia&ble to Attribute'),
473 0, 0,
474 self, 'refactoring_local_variable_to_attribute')
475 self.refactoringLocalVariableToAttributeAct.setStatusTip(self.tr(
476 'Change a local variable to an attribute'))
477 self.refactoringLocalVariableToAttributeAct.setWhatsThis(self.tr(
478 """<b>Local Variable to Attribute</b>"""
479 """<p>Change a local variable to an attribute.</p>"""
480 ))
481 self.refactoringLocalVariableToAttributeAct.triggered.connect(
482 self.__convertLocalToAttribute)
483 self.actions.append(self.refactoringLocalVariableToAttributeAct)
484
485 self.refactoringMethodToMethodObjectAct = E5Action(
486 self.tr('Method To Method Object'),
487 self.tr('Method To Method Ob&ject'),
488 0, 0,
489 self, 'refactoring_method_to_methodobject')
490 self.refactoringMethodToMethodObjectAct.setStatusTip(self.tr(
491 'Transform a function or a method to a method object'))
492 self.refactoringMethodToMethodObjectAct.setWhatsThis(self.tr(
493 """<b>Method To Method Object</b>"""
494 """<p>Transform a function or a method to a method object.</p>"""
495 ))
496 self.refactoringMethodToMethodObjectAct.triggered.connect(
497 self.__methodToMethodObject)
498 self.actions.append(self.refactoringMethodToMethodObjectAct)
499
500 #####################################################
501 ## History actions
502 #####################################################
503
504 self.refactoringProjectHistoryAct = E5Action(
505 self.tr('Show Project History'),
506 self.tr('Show Project History...'),
507 0, 0,
508 self, 'refactoring_show_project_history')
509 self.refactoringProjectHistoryAct.setStatusTip(self.tr(
510 'Show the refactoring history of the project'))
511 self.refactoringProjectHistoryAct.setWhatsThis(self.tr(
512 """<b>Show Project History</b>"""
513 """<p>This opens a dialog to show the refactoring history of"""
514 """ the project.</p>"""
515 ))
516 self.refactoringProjectHistoryAct.triggered.connect(
517 self.__showProjectHistory)
518 self.actions.append(self.refactoringProjectHistoryAct)
519
520 self.refactoringFileHistoryAct = E5Action(
521 self.tr('Show Current File History'),
522 self.tr('Show Current File History...'),
523 0, 0,
524 self, 'refactoring_show_file_history')
525 self.refactoringFileHistoryAct.setStatusTip(self.tr(
526 'Show the refactoring history of the current file'))
527 self.refactoringFileHistoryAct.setWhatsThis(self.tr(
528 """<b>Show Current File History</b>"""
529 """<p>This opens a dialog to show the refactoring history of"""
530 """ the current file.</p>"""
531 ))
532 self.refactoringFileHistoryAct.triggered.connect(
533 self.__showFileHistory)
534 self.actions.append(self.refactoringFileHistoryAct)
535
536 self.refactoringClearHistoryAct = E5Action(
537 self.tr('Clear History'),
538 self.tr('Clear History'),
539 0, 0,
540 self, 'refactoring_clear_history')
541 self.refactoringClearHistoryAct.setStatusTip(self.tr(
542 'Clear the refactoring history'))
543 self.refactoringClearHistoryAct.setWhatsThis(self.tr(
544 """<b>Clear History</b>"""
545 """<p>Clears the refactoring history.</p>"""
546 ))
547 self.refactoringClearHistoryAct.triggered.connect(
548 self.__clearHistory)
549 self.actions.append(self.refactoringClearHistoryAct)
550
551 #####################################################
552 ## Query actions
553 #####################################################
554
555 self.queryReferencesAct = E5Action(
556 self.tr('Find occurrences'),
557 self.tr('Find &Occurrences'),
558 0, 0,
559 self, 'refactoring_find_occurrences')
560 self.queryReferencesAct.setStatusTip(self.tr(
561 'Find occurrences of the highlighted object'))
562 self.queryReferencesAct.setWhatsThis(self.tr(
563 """<b>Find occurrences</b>"""
564 """<p>Find occurrences of the highlighted class, method,"""
565 """ function or variable.</p>"""
566 ))
567 self.queryReferencesAct.triggered.connect(
568 self.__queryReferences)
569 self.actions.append(self.queryReferencesAct)
570
571 self.queryDefinitionAct = E5Action(
572 self.tr('Find definition'),
573 self.tr('Find &Definition'),
574 0, 0,
575 self, 'refactoring_find_definition')
576 self.queryDefinitionAct.setStatusTip(self.tr(
577 'Find definition of the highlighted item'))
578 self.queryDefinitionAct.setWhatsThis(self.tr(
579 """<b>Find definition</b>"""
580 """<p>Find the definition of the highlighted class, method,"""
581 """ function or variable.</p>"""
582 ))
583 self.queryDefinitionAct.triggered.connect(
584 self.__queryDefinition)
585 self.actions.append(self.queryDefinitionAct)
586
587 self.queryImplementationsAct = E5Action(
588 self.tr('Find implementations'),
589 self.tr('Find &Implementations'),
590 0, 0,
591 self, 'refactoring_find_implementations')
592 self.queryImplementationsAct.setStatusTip(self.tr(
593 'Find places where the selected method is overridden'))
594 self.queryImplementationsAct.setWhatsThis(self.tr(
595 """<b>Find implementations</b>"""
596 """<p>Find places where the selected method is overridden.</p>"""
597 ))
598 self.queryImplementationsAct.triggered.connect(
599 self.__queryImplementations)
600 self.actions.append(self.queryImplementationsAct)
601
602 #####################################################
603 ## Various actions
604 #####################################################
605
606 self.refactoringEditConfigAct = E5Action(
607 self.tr('Configure Rope'),
608 self.tr('&Configure Rope'),
609 0, 0,
610 self, 'refactoring_edit_config')
611 self.refactoringEditConfigAct.setStatusTip(self.tr(
612 'Open the rope configuration file'))
613 self.refactoringEditConfigAct.setWhatsThis(self.tr(
614 """<b>Configure Rope</b>"""
615 """<p>Opens the rope configuration file in an editor.</p>"""
616 ))
617 self.refactoringEditConfigAct.triggered.connect(
618 self.__editConfig)
619 self.refactoringEditConfigAct.setMenuRole(QAction.NoRole)
620 self.actions.append(self.refactoringEditConfigAct)
621
622 self.refactoringHelpAct = E5Action(
623 self.tr('Rope Help'),
624 self.tr('Rope &Help'),
625 0, 0,
626 self, 'refactoring_help')
627 self.refactoringHelpAct.setStatusTip(self.tr(
628 'Show help about the rope refactorings'))
629 self.refactoringHelpAct.setWhatsThis(self.tr(
630 """<b>Rope help</b>"""
631 """<p>Show some help text about the rope refactorings.</p>"""
632 ))
633 self.refactoringHelpAct.triggered.connect(
634 self.__showRopeHelp)
635 self.actions.append(self.refactoringHelpAct)
636
637 self.refactoringAllSoaAct = E5Action(
638 self.tr('Analyse all modules'),
639 self.tr('&Analyse all modules'),
640 0, 0,
641 self, 'refactoring_analyze_all')
642 self.refactoringAllSoaAct.setStatusTip(self.tr(
643 'Perform static object analysis on all modules'))
644 self.refactoringAllSoaAct.setWhatsThis(self.tr(
645 """<b>Analyse all modules</b>"""
646 """<p>Perform static object analysis (SOA) on all modules. """
647 """This might be time consuming. Analysis of all modules """
648 """should only be neccessary, if the project was created """
649 """with the rope plugin disabled or if files were added.</p>"""
650 ))
651 self.refactoringAllSoaAct.triggered.connect(
652 self.__performSOA)
653 self.actions.append(self.refactoringAllSoaAct)
654
655 self.updateConfigAct = E5Action(
656 self.tr('Update Configuration'),
657 self.tr('&Update Configuration'),
658 0, 0,
659 self, 'refactoring_update_configuration')
660 self.updateConfigAct.setStatusTip(self.tr(
661 'Generates a new configuration file overwriting the current one.'))
662 self.updateConfigAct.setWhatsThis(self.tr(
663 """<b>Update Configuration</b>"""
664 """<p>Generates a new configuration file overwriting"""
665 """ the current one.</p>"""
666 ))
667 self.updateConfigAct.triggered.connect(
668 self.__updateConfig)
669 self.actions.append(self.updateConfigAct)
670
671 for act in self.actions:
672 act.setEnabled(False)
673
674 def initMenu(self):
675 """
676 Public slot to initialize the refactoring menu.
677
678 @return the menu generated (QMenu)
679 """
680 menu = QMenu(self.tr('&Refactoring'), self.__ui)
681 menu.setTearOffEnabled(True)
682
683 act = menu.addAction('rope', self.__ropeInfo)
684 font = act.font()
685 font.setBold(True)
686 act.setFont(font)
687 menu.addSeparator()
688
689 smenu = menu.addMenu(self.tr("&Query"))
690 smenu.addAction(self.queryReferencesAct)
691 smenu.addAction(self.queryDefinitionAct)
692 smenu.addAction(self.queryImplementationsAct)
693
694 smenu = menu.addMenu(self.tr("&Refactoring"))
695 smenu.addAction(self.refactoringRenameAct)
696 smenu.addAction(self.refactoringRenameLocalAct)
697 smenu.addAction(self.refactoringChangeOccurrencesAct)
698 smenu.addSeparator()
699 smenu.addAction(self.refactoringExtractMethodAct)
700 smenu.addAction(self.refactoringMoveMethodAct)
701 smenu.addSeparator()
702 smenu.addAction(self.refactoringInlineAct)
703 smenu.addSeparator()
704 smenu.addAction(self.refactoringExtractLocalVariableAct)
705 smenu.addSeparator()
706 smenu.addAction(self.refactoringUseFunctionAct)
707 smenu.addSeparator()
708 smenu.addAction(self.refactoringChangeSignatureAct)
709 smenu.addAction(self.refactoringInlineArgumentDefaultAct)
710 smenu.addSeparator()
711 smenu.addAction(self.refactoringRestructureAct)
712 smenu.addSeparator()
713 smenu.addAction(self.refactoringIntroduceFactoryAct)
714 smenu.addAction(self.refactoringIntroduceParameterAct)
715 smenu.addAction(self.refactoringMethodToMethodObjectAct)
716 smenu.addSeparator()
717 smenu.addAction(self.refactoringEncapsulateAttributeAct)
718 smenu.addAction(self.refactoringLocalVariableToAttributeAct)
719 smenu.addSeparator()
720 smenu.addAction(self.refactoringRenameModuleAct)
721 smenu.addAction(self.refactoringMoveModuleAct)
722 smenu.addAction(self.refactoringTransformModuleAct)
723 smenu.addSeparator()
724
725 imenu = smenu.addMenu(self.tr("Im&ports"))
726 imenu.addAction(self.refactoringImportsOrganizeAct)
727 imenu.addAction(self.refactoringImportsStarExpandAct)
728 imenu.addAction(self.refactoringImportsRelativeToAbsoluteAct)
729 imenu.addAction(self.refactoringImportsFromsToImportsAct)
730 imenu.addAction(self.refactoringImportsHandleLongAct)
731
732 smenu.addSeparator()
733
734 hmenu = smenu.addMenu(self.tr("History"))
735 hmenu.aboutToShow.connect(self.__showRefactoringHistoryMenu)
736 hmenu.addAction(self.refactoringProjectHistoryAct)
737 hmenu.addAction(self.refactoringFileHistoryAct)
738 hmenu.addSeparator()
739 hmenu.addAction(self.refactoringClearHistoryAct)
740
741 smenu = menu.addMenu(self.tr("&Utilities"))
742 smenu.addAction(self.refactoringAllSoaAct)
743 smenu.addSeparator()
744 smenu.addAction(self.updateConfigAct)
745
746 menu.addSeparator()
747 menu.addAction(self.refactoringEditConfigAct)
748 menu.addAction(self.refactoringHelpAct)
749
750 self.__mainMenu = menu
751
752 return menu
753
754 ##################################################################
755 ## slots below implement general functionality
756 ##################################################################
757
758 def __ropeInfo(self):
759 """
760 Private slot to show some info about rope.
761 """
762 if self.__ropeConfig:
763 E5MessageBox.about(
764 self.__ui,
765 self.tr("About rope"),
766 self.tr("{0}\nVersion {1}\n\n{2}".format(
767 self.__ropeConfig["RopeInfo"],
768 self.__ropeConfig["RopeVersion"],
769 self.__ropeConfig["RopeCopyright"])))
770
771 def __showRefactoringHistoryMenu(self):
772 """
773 Private slot called before the refactoring history menu is shown.
774 """
775 aw = e5App().getObject("ViewManager").activeWindow()
776 enable = aw is not None and bool(aw.getFileName())
777
778 self.refactoringFileHistoryAct.setEnabled(enable)
779
780 def handleRopeError(self, result):
781 """
782 Public method to handle a rope error.
783
784 @param result dictionary containing the error information
785 @type dict
786 @return flag indicating, that the error is to be ignored
787 @rtype bool
788 """
789 if "Error" not in result:
790 return True
791
792 if "Title" in result:
793 title = result["Title"]
794 else:
795 title = self.tr("Rope Error")
796
797 if result["Error"] == 'ModuleSyntaxError':
798 res = E5MessageBox.warning(
799 self.__ui, title,
800 self.tr("Rope error: {0}").format(
801 result["ErrorString"]),
802 E5MessageBox.Ok | E5MessageBox.Open)
803 if res == E5MessageBox.Open:
804 e5App().getObject("ViewManager").openSourceFile(
805 os.path.join(self.__e5project.getProjectPath(),
806 result["ErrorFile"]),
807 result["ErrorLine"])
808 elif result["Error"] == "InterruptedTaskError":
809 return True
810 else:
811 E5MessageBox.warning(
812 self.__ui, title,
813 self.tr("Rope error: {0}").format(
814 result["ErrorString"])
815 )
816
817 return False
818
819 def __getOffset(self, editor, line, index):
820 r"""
821 Private method to get the offset into the text treating CRLF as ONE
822 character.
823
824 Note: rope seems to convert all EOL styles to just \n.
825
826 @param editor reference to the editor (Editor)
827 @param line line for the offset (integer)
828 @param index index into line for the offset (integer)
829 @return rope compliant offset into the file (integer)
830 """
831 source = editor.text()
832 offset = len("".join(source.splitlines(True)[:line])) + index
833 if editor.eolMode() == QsciScintilla.EolWindows:
834 offset -= line
835 return offset
836
837 ##################################################################
838 ## slots below implement the various refactorings
839 ##################################################################
840
841 def __processChanges(self, result):
842 """
843 Private method to process the changes data sent by the refactoring
844 client.
845
846 @param result dictionary containing the changes data
847 @type dict
848 """
849 if self.handleRopeError(result):
850 changeGroup = result["ChangeGroup"]
851 try:
852 self.__refactoringDialogs[changeGroup]\
853 .processChangeData(result)
854 except KeyError:
855 # ignore data for non-existing dialogs
856 pass
857
858 def __refactoringDialogClosed(self, changeGroup):
859 """
860 Private slot handling the closing of a refactoring dialog.
861
862 @param changeGroup name of the refactoring change group the dialog
863 belonged to
864 @type str
865 """
866 try:
867 del self.__refactoringDialogs[changeGroup]
868 except KeyError:
869 # it's gone already; ignore it
870 pass
871
872 #####################################################
873 ## Rename refactorings
874 #####################################################
875
876 def __rename(self):
877 """
878 Private slot to handle the Rename action.
879 """
880 self.__doRename(self.tr('Rename'))
881
882 def __renameLocal(self):
883 """
884 Private slot to handle the Local Rename action.
885 """
886 self.__doRename(self.tr('Local Rename'), isLocal=True)
887
888 def __renameModule(self):
889 """
890 Private slot to handle the Rename Current Module action.
891 """
892 self.__doRename(self.tr('Rename Current Module'),
893 renameModule=True)
894
895 def __doRename(self, title, isLocal=False, renameModule=False):
896 """
897 Private method to perform the various renaming refactorings.
898
899 @param title title of the refactoring (string)
900 @param isLocal flag indicating to restrict refactoring to
901 the local file (boolean)
902 @param renameModule flag indicating a module rename refactoring
903 (boolean)
904 """
905 aw = e5App().getObject("ViewManager").activeWindow()
906
907 if aw is None:
908 return
909
910 if not renameModule and not aw.hasSelectedText():
911 # no selection available
912 E5MessageBox.warning(
913 self.__ui, title,
914 self.tr("Highlight the declaration you want to rename"
915 " and try again."))
916 return
917
918 if isLocal:
919 if not self.confirmBufferIsSaved(aw):
920 return
921 else:
922 if not self.confirmAllBuffersSaved():
923 return
924
925 filename = aw.getFileName()
926 if renameModule:
927 offset = None
928 selectedText, _ = os.path.splitext(os.path.basename(filename))
929 else:
930 line, index, line1, index1 = aw.getSelection()
931 if line != line1:
932 # selection span more than one line
933 E5MessageBox.warning(
934 self.__ui, title,
935 self.tr("The selection must not extend beyond"
936 " one line."))
937 return
938 index = int(index + (index1 - index) / 2)
939 # keep it inside the object
940 offset = self.__getOffset(aw, line, index)
941 selectedText = aw.selectedText()
942
943 from RenameDialog import RenameDialog
944 dlg = RenameDialog(self, title, filename, offset, isLocal,
945 selectedText=selectedText, parent=self.__ui)
946 changeGroup = dlg.getChangeGroupName()
947 self.__refactoringDialogs[changeGroup] = dlg
948 dlg.finished.connect(
949 lambda: self.__refactoringDialogClosed(changeGroup))
950 dlg.show()
951
952 def __changeOccurrences(self):
953 """
954 Private slot to perform the Change Occurrences refactoring.
955 """
956 aw = e5App().getObject("ViewManager").activeWindow()
957
958 if aw is None:
959 return
960
961 title = self.tr("Change Occurrences")
962 if not aw.hasSelectedText():
963 # no selection available
964 E5MessageBox.warning(
965 self.__ui, title,
966 self.tr("Highlight an occurrence to be changed"
967 " and try again."))
968 return
969
970 if not self.confirmBufferIsSaved(aw):
971 return
972
973 filename = aw.getFileName()
974 line, index, line1, index1 = aw.getSelection()
975 offset = self.__getOffset(aw, line, index)
976
977 from ChangeOccurrencesDialog import ChangeOccurrencesDialog
978 dlg = ChangeOccurrencesDialog(self, title, filename, offset,
979 parent=self.__ui)
980 changeGroup = dlg.getChangeGroupName()
981 self.__refactoringDialogs[changeGroup] = dlg
982 dlg.finished.connect(
983 lambda: self.__refactoringDialogClosed(changeGroup))
984 dlg.show()
985
986 #####################################################
987 ## Extract refactorings
988 #####################################################
989
990 def __extractMethod(self):
991 """
992 Private slot to handle the Extract Method action.
993 """
994 self.__doExtract(self.tr("Extract Method"), "method")
995
996 def __extractLocalVariable(self):
997 """
998 Private slot to handle the Extract Local Variable action.
999 """
1000 self.__doExtract(self.tr("Extract Local Variable"), "variable")
1001
1002 def __doExtract(self, title, kind):
1003 """
1004 Private method to perform the extract refactoring.
1005
1006 @param title title of the refactoring
1007 @type str
1008 @param kind kind of extraction to be done
1009 @type str ("method" or "variable")
1010 """
1011 assert kind in ["variable", "method"]
1012
1013 aw = e5App().getObject("ViewManager").activeWindow()
1014
1015 if aw is None:
1016 return
1017
1018 if not aw.hasSelectedText():
1019 # no selection available
1020 E5MessageBox.warning(
1021 self.__ui, title,
1022 self.tr("Highlight the region of code you want to extract"
1023 " and try again."))
1024 return
1025
1026 if not self.confirmBufferIsSaved(aw):
1027 return
1028
1029 filename = aw.getFileName()
1030 startline, startcolumn, endline, endcolumn = aw.getSelection()
1031 startOffset = self.__getOffset(aw, startline, startcolumn)
1032 endOffset = self.__getOffset(aw, endline, endcolumn)
1033
1034 from ExtractDialog import ExtractDialog
1035 dlg = ExtractDialog(self, title, filename, startOffset, endOffset,
1036 kind, parent=self.__ui)
1037 changeGroup = dlg.getChangeGroupName()
1038 self.__refactoringDialogs[changeGroup] = dlg
1039 dlg.finished.connect(
1040 lambda: self.__refactoringDialogClosed(changeGroup))
1041 dlg.show()
1042
1043 #####################################################
1044 ## Inline refactorings
1045 #####################################################
1046
1047 def __inline(self):
1048 """
1049 Private slot to handle the Inline Local Variable action.
1050 """
1051 aw = e5App().getObject("ViewManager").activeWindow()
1052
1053 if aw is None:
1054 return
1055
1056 title = self.tr("Inline")
1057 if not aw.hasSelectedText():
1058 # no selection available
1059 E5MessageBox.warning(
1060 self.__ui, title,
1061 self.tr("Highlight the local variable, method or parameter"
1062 " you want to inline and try again."))
1063 return
1064
1065 if not self.confirmAllBuffersSaved():
1066 return
1067
1068 filename = aw.getFileName()
1069 line, index, line1, index1 = aw.getSelection()
1070 offset = self.__getOffset(aw, line, index)
1071
1072 from InlineDialog import InlineDialog
1073 dlg = InlineDialog(self, title, filename, offset, parent=self.__ui)
1074 changeGroup = dlg.getChangeGroupName()
1075 self.__refactoringDialogs[changeGroup] = dlg
1076 dlg.finished.connect(
1077 lambda: self.__refactoringDialogClosed(changeGroup))
1078 dlg.show()
1079
1080 #####################################################
1081 ## Move refactorings
1082 #####################################################
1083
1084 def __move(self, moveKind):
1085 """
1086 Private slot to handle the Move Method action.
1087
1088 @param moveKind kind of move to be performed
1089 @type str (one of 'move_method' or 'move_module')
1090 """
1091 aw = e5App().getObject("ViewManager").activeWindow()
1092
1093 if aw is None:
1094 return
1095
1096 if moveKind == "move_method":
1097 title = self.tr("Move Method")
1098 if not aw.hasSelectedText():
1099 # no selection available
1100 E5MessageBox.warning(
1101 self.__ui, title,
1102 self.tr("Highlight the method to move"
1103 " and try again."))
1104 return
1105 else:
1106 title = self.tr("Move Current Module")
1107
1108 if not self.confirmAllBuffersSaved():
1109 return
1110
1111 filename = aw.getFileName()
1112 if moveKind == "move_method":
1113 line, index, line1, index1 = aw.getSelection()
1114 offset = self.__getOffset(aw, line, index)
1115 else:
1116 offset = None
1117
1118 from MoveDialog import MoveDialog
1119 dlg = MoveDialog(self, title, filename, offset, parent=self.__ui)
1120 changeGroup = dlg.getChangeGroupName()
1121 self.__refactoringDialogs[changeGroup] = dlg
1122 dlg.finished.connect(
1123 lambda: self.__refactoringDialogClosed(changeGroup))
1124 dlg.show()
1125
1126 #####################################################
1127 ## Use function refactoring
1128 #####################################################
1129
1130 def __useFunction(self):
1131 """
1132 Private slot to use a function wherever possible.
1133 """
1134 aw = e5App().getObject("ViewManager").activeWindow()
1135
1136 if aw is None:
1137 return
1138
1139 title = self.tr("Use Function")
1140 if not aw.hasSelectedText():
1141 # no selection available
1142 E5MessageBox.warning(
1143 self.__ui, title,
1144 self.tr("Highlight a global function and try again."))
1145 return
1146
1147 if not self.confirmAllBuffersSaved():
1148 return
1149
1150 filename = aw.getFileName()
1151 line, index, line1, index1 = aw.getSelection()
1152 offset = self.__getOffset(aw, line, index)
1153
1154 from UseFunctionDialog import UseFunctionDialog
1155 dlg = UseFunctionDialog(self, title, filename, offset,
1156 parent=self.__ui)
1157 changeGroup = dlg.getChangeGroupName()
1158 self.__refactoringDialogs[changeGroup] = dlg
1159 dlg.finished.connect(
1160 lambda: self.__refactoringDialogClosed(changeGroup))
1161 dlg.show()
1162
1163 #####################################################
1164 ## Introduce refactorings
1165 #####################################################
1166
1167 def __introduceFactoryMethod(self):
1168 """
1169 Private slot to introduce a factory method or global function.
1170 """
1171 aw = e5App().getObject("ViewManager").activeWindow()
1172
1173 if aw is None:
1174 return
1175
1176 title = self.tr("Introduce Factory Method")
1177 if not aw.hasSelectedText():
1178 # no selection available
1179 E5MessageBox.warning(
1180 self.__ui, title,
1181 self.tr("Highlight the class to introduce a factory"
1182 " method for and try again."))
1183 return
1184
1185 if not self.confirmAllBuffersSaved():
1186 return
1187
1188 filename = aw.getFileName()
1189 line, index, line1, index1 = aw.getSelection()
1190 offset = self.__getOffset(aw, line, index)
1191
1192 from IntroduceFactoryDialog import IntroduceFactoryDialog
1193 dlg = IntroduceFactoryDialog(self, title, filename, offset,
1194 parent=self.__ui)
1195 changeGroup = dlg.getChangeGroupName()
1196 self.__refactoringDialogs[changeGroup] = dlg
1197 dlg.finished.connect(
1198 lambda: self.__refactoringDialogClosed(changeGroup))
1199 dlg.show()
1200
1201 def __introduceParameter(self):
1202 """
1203 Private slot to introduce a parameter in a function.
1204 """
1205 aw = e5App().getObject("ViewManager").activeWindow()
1206
1207 if aw is None:
1208 return
1209
1210 title = self.tr("Introduce Parameter")
1211 if not aw.hasSelectedText():
1212 # no selection available
1213 E5MessageBox.warning(
1214 self.__ui, title,
1215 self.tr("Highlight the code for the new parameter"
1216 " and try again."))
1217 return
1218
1219 if not self.confirmAllBuffersSaved():
1220 return
1221
1222 filename = aw.getFileName()
1223 line, index, line1, index1 = aw.getSelection()
1224 offset = self.__getOffset(aw, line, index)
1225
1226 from IntroduceParameterDialog import IntroduceParameterDialog
1227 dlg = IntroduceParameterDialog(self, title, filename, offset,
1228 parent=self.__ui)
1229 changeGroup = dlg.getChangeGroupName()
1230 self.__refactoringDialogs[changeGroup] = dlg
1231 dlg.finished.connect(
1232 lambda: self.__refactoringDialogClosed(changeGroup))
1233 dlg.show()
1234
1235 #####################################################
1236 ## Import refactorings
1237 #####################################################
1238
1239 def __importsOrganize(self):
1240 """
1241 Private slot to organize imports.
1242 """
1243 self.__doImports(
1244 self.tr("Organize Imports"),
1245 "organize_imports")
1246
1247 def __importsExpandStar(self):
1248 """
1249 Private slot to expand star imports.
1250 """
1251 self.__doImports(
1252 self.tr("Expand Star Imports"),
1253 "expand_star_imports")
1254
1255 def __importsRelativeToAbsolute(self):
1256 """
1257 Private slot to transform relative to absolute imports.
1258 """
1259 self.__doImports(
1260 self.tr("Relative to Absolute"),
1261 "relatives_to_absolutes")
1262
1263 def __importsFromToImport(self):
1264 """
1265 Private slot to transform from imports to plain imports.
1266 """
1267 self.__doImports(
1268 self.tr("Froms to Imports"),
1269 "froms_to_imports")
1270
1271 def __importsHandleLong(self):
1272 """
1273 Private slot to handle long imports.
1274 """
1275 self.__doImports(
1276 self.tr("Handle Long Imports"),
1277 "handle_long_imports")
1278
1279 def __doImports(self, title, methodName):
1280 """
1281 Private method to perform the various imports refactorings.
1282
1283 @param title title to be used for the import refactoring
1284 @type str
1285 @param methodName name of the method performing the import refactoring
1286 @type str
1287 """
1288 aw = e5App().getObject("ViewManager").activeWindow()
1289
1290 if aw is None:
1291 return
1292
1293 if not self.confirmBufferIsSaved(aw):
1294 return
1295
1296 filename = aw.getFileName()
1297 if aw.hasSelectedText():
1298 line, index, line1, index1 = aw.getSelection()
1299 offset = self.__getOffset(aw, line, index)
1300 else:
1301 offset = None
1302
1303 from ConfirmationDialog import ConfirmationDialog
1304 dlg = ConfirmationDialog(
1305 self, title, "Imports", "CalculateImportsChanges", {
1306 "MethodName": methodName,
1307 "FileName": filename,
1308 "Offset": offset,
1309 },
1310 parent=self.__ui)
1311 changeGroup = dlg.getChangeGroupName()
1312 self.__refactoringDialogs[changeGroup] = dlg
1313 dlg.finished.connect(
1314 lambda: self.__refactoringDialogClosed(changeGroup))
1315 dlg.show()
1316
1317 #####################################################
1318 ## Various refactorings
1319 #####################################################
1320
1321 def __restructure(self):
1322 """
1323 Private slot to restructure code.
1324 """
1325 from RestructureDialog import RestructureDialog
1326 title = self.tr("Restructure")
1327 dlg = RestructureDialog(self, title, parent=self.__ui)
1328 changeGroup = dlg.getChangeGroupName()
1329 self.__refactoringDialogs[changeGroup] = dlg
1330 dlg.finished.connect(
1331 lambda: self.__refactoringDialogClosed(changeGroup))
1332 dlg.show()
1333
1334 def __changeSignature(self):
1335 """
1336 Private slot to change the signature of a method or function.
1337 """
1338 aw = e5App().getObject("ViewManager").activeWindow()
1339
1340 if aw is None:
1341 return
1342
1343 title = self.tr("Change Method Signature")
1344 if not aw.hasSelectedText():
1345 # no selection available
1346 E5MessageBox.warning(
1347 self.__ui, title,
1348 self.tr("Highlight the method or function to change"
1349 " and try again."))
1350 return
1351
1352 if not self.confirmAllBuffersSaved():
1353 return
1354
1355 filename = aw.getFileName()
1356 line, index, line1, index1 = aw.getSelection()
1357 offset = self.__getOffset(aw, line, index)
1358
1359 from ChangeSignatureDialog import ChangeSignatureDialog
1360 dlg = ChangeSignatureDialog(self, title, filename, offset,
1361 parent=self.__ui)
1362 changeGroup = dlg.getChangeGroupName()
1363 self.__refactoringDialogs[changeGroup] = dlg
1364 dlg.finished.connect(
1365 lambda: self.__refactoringDialogClosed(changeGroup))
1366 dlg.show()
1367
1368 def __inlineArgumentDefault(self):
1369 """
1370 Private slot to inline the default value of a parameter of a
1371 method or function.
1372 """
1373 aw = e5App().getObject("ViewManager").activeWindow()
1374
1375 if aw is None:
1376 return
1377
1378 title = self.tr("Inline Argument Default")
1379 if not aw.hasSelectedText():
1380 # no selection available
1381 E5MessageBox.warning(
1382 self.__ui, title,
1383 self.tr("Highlight the method or function to inline"
1384 " a parameter's default and try again."))
1385 return
1386
1387 if not self.confirmAllBuffersSaved():
1388 return
1389
1390 filename = aw.getFileName()
1391 line, index, line1, index1 = aw.getSelection()
1392 offset = self.__getOffset(aw, line, index)
1393
1394 from InlineArgumentDefaultDialog import InlineArgumentDefaultDialog
1395 dlg = InlineArgumentDefaultDialog(self, title, filename, offset,
1396 parent=self.__ui)
1397 changeGroup = dlg.getChangeGroupName()
1398 self.__refactoringDialogs[changeGroup] = dlg
1399 dlg.finished.connect(
1400 lambda: self.__refactoringDialogClosed(changeGroup))
1401 dlg.show()
1402
1403 def __transformModuleToPackage(self):
1404 """
1405 Private slot to transform a module to a package.
1406 """
1407 aw = e5App().getObject("ViewManager").activeWindow()
1408
1409 if aw is None:
1410 return
1411
1412 title = self.tr("Transform Module to Package")
1413
1414 if not self.confirmAllBuffersSaved():
1415 return
1416
1417 filename = aw.getFileName()
1418
1419 from ConfirmationDialog import ConfirmationDialog
1420 dlg = ConfirmationDialog(
1421 self, title, "ModuleToPackage", "CalculateModuleToPackageChanges",
1422 {
1423 "FileName": filename,
1424 },
1425 parent=self.__ui)
1426 changeGroup = dlg.getChangeGroupName()
1427 self.__refactoringDialogs[changeGroup] = dlg
1428 dlg.finished.connect(
1429 lambda: self.__refactoringDialogClosed(changeGroup))
1430 dlg.show()
1431
1432 def __encapsulateAttribute(self):
1433 """
1434 Private slot to encapsulate an attribute.
1435 """
1436 aw = e5App().getObject("ViewManager").activeWindow()
1437
1438 if aw is None:
1439 return
1440
1441 title = self.tr("Encapsulate Attribute")
1442 if not aw.hasSelectedText():
1443 # no selection available
1444 E5MessageBox.warning(
1445 self.__ui, title,
1446 self.tr("Highlight the attribute to encapsulate"
1447 " and try again."))
1448 return
1449
1450 if not self.confirmAllBuffersSaved():
1451 return
1452
1453 filename = aw.getFileName()
1454 line, index, line1, index1 = aw.getSelection()
1455 offset = self.__getOffset(aw, line, index)
1456
1457 from GetterSetterDialog import GetterSetterDialog
1458 dlg = GetterSetterDialog(self, title, filename, offset,
1459 parent=self.__ui)
1460 changeGroup = dlg.getChangeGroupName()
1461 self.__refactoringDialogs[changeGroup] = dlg
1462 dlg.finished.connect(
1463 lambda: self.__refactoringDialogClosed(changeGroup))
1464 dlg.show()
1465
1466 def __convertLocalToAttribute(self):
1467 """
1468 Private slot to convert a local variable to an attribute.
1469 """
1470 aw = e5App().getObject("ViewManager").activeWindow()
1471
1472 if aw is None:
1473 return
1474
1475 title = self.tr("Local Variable to Attribute")
1476 if not aw.hasSelectedText():
1477 # no selection available
1478 E5MessageBox.warning(
1479 self.__ui, title,
1480 self.tr("Highlight the local variable to make an attribute"
1481 " and try again."))
1482 return
1483
1484 if not self.confirmAllBuffersSaved():
1485 return
1486
1487 filename = aw.getFileName()
1488 line, index, line1, index1 = aw.getSelection()
1489 offset = self.__getOffset(aw, line, index)
1490
1491 from ConfirmationDialog import ConfirmationDialog
1492 dlg = ConfirmationDialog(
1493 self, title, "LocalToAttribute",
1494 "CalculateLocalToAttributeChanges", {
1495 "FileName": filename,
1496 "Offset": offset,
1497 },
1498 parent=self.__ui)
1499 changeGroup = dlg.getChangeGroupName()
1500 self.__refactoringDialogs[changeGroup] = dlg
1501 dlg.finished.connect(
1502 lambda: self.__refactoringDialogClosed(changeGroup))
1503 dlg.show()
1504
1505 def __methodToMethodObject(self):
1506 """
1507 Private slot to change the signature of a method or function.
1508 """
1509 aw = e5App().getObject("ViewManager").activeWindow()
1510
1511 if aw is None:
1512 return
1513
1514 title = self.tr("Replace Method With Method Object")
1515 if not aw.hasSelectedText():
1516 # no selection available
1517 E5MessageBox.warning(
1518 self.__ui, title,
1519 self.tr("Highlight the method or function to convert"
1520 " and try again."))
1521 return
1522
1523 if not self.confirmAllBuffersSaved():
1524 return
1525
1526 filename = aw.getFileName()
1527 line, index, line1, index1 = aw.getSelection()
1528 offset = self.__getOffset(aw, line, index)
1529
1530 from MethodToMethodObjectDialog import MethodToMethodObjectDialog
1531 dlg = MethodToMethodObjectDialog(self, title, filename, offset,
1532 parent=self.__ui)
1533 changeGroup = dlg.getChangeGroupName()
1534 self.__refactoringDialogs[changeGroup] = dlg
1535 dlg.finished.connect(
1536 lambda: self.__refactoringDialogClosed(changeGroup))
1537 dlg.show()
1538
1539 #####################################################
1540 ## Refactoring History
1541 #####################################################
1542
1543 def __showProjectHistory(self):
1544 """
1545 Private method to show the project refactoring history.
1546 """
1547 if self.__historyDialog is not None:
1548 self.__historyDialog.close()
1549
1550 from HistoryDialog import HistoryDialog
1551 self.__historyDialog = HistoryDialog(self, parent=self.__ui)
1552 self.__historyDialog.finished.connect(self.__historyDialogClosed)
1553 self.__historyDialog.show()
1554
1555 def __showFileHistory(self):
1556 """
1557 Private method to show the refactoring history of the current file.
1558 """
1559 aw = e5App().getObject("ViewManager").activeWindow()
1560
1561 if aw is None:
1562 return
1563
1564 if self.__historyDialog is not None:
1565 self.__historyDialog.close()
1566
1567 from HistoryDialog import HistoryDialog
1568 filename = aw.getFileName()
1569 if filename:
1570 self.__historyDialog = HistoryDialog(
1571 self, filename=filename, parent=self.__ui)
1572 self.__historyDialog.show()
1573
1574 def __clearHistory(self):
1575 """
1576 Private slot to clear the redo and undo lists.
1577 """
1578 res = E5MessageBox.yesNo(
1579 None,
1580 self.tr("Clear History"),
1581 self.tr("Do you really want to clear the refactoring history?"))
1582 if res:
1583 self.sendJson("History", {
1584 "Subcommand": "Clear",
1585 })
1586
1587 if self.__historyDialog is not None:
1588 self.__historyDialog.historyCleared()
1589
1590 def __processHistoryResult(self, result):
1591 """
1592 Private method to process the history data sent by the refactoring
1593 client.
1594
1595 @param result dictionary containing the history data
1596 @type dict
1597 """
1598 if self.handleRopeError(result) and self.__historyDialog is not None:
1599 self.__historyDialog.processHistoryCommand(result)
1600
1601 def __historyDialogClosed(self):
1602 """
1603 Private slot handling the closing of the history dialog.
1604 """
1605 self.__historyDialog = None
1606
1607 #####################################################
1608 ## Find actions including mouse click handler
1609 #####################################################
1610
1611 def __queryReferences(self):
1612 """
1613 Private slot to handle the Find References action.
1614 """
1615 aw = e5App().getObject("ViewManager").activeWindow()
1616
1617 if aw is None:
1618 return
1619
1620 title = self.tr("Find Occurrences")
1621
1622 if not self.confirmAllBuffersSaved():
1623 return
1624
1625 filename = aw.getFileName()
1626 line, index = aw.getCursorPosition()
1627 offset = self.__getOffset(aw, line, index)
1628
1629 self.sendJson("QueryReferences", {
1630 "Title": title,
1631 "FileName": filename,
1632 "Offset": offset,
1633 })
1634
1635 def __queryReferencesResult(self, result):
1636 """
1637 Private method to handle the "Query References" result sent by
1638 the client.
1639
1640 @param result dictionary containing the result data
1641 @type dict
1642 """
1643 if self.handleRopeError(result):
1644 title = result["Title"]
1645 if result["EntriesCount"] > 0:
1646 from MatchesDialog import MatchesDialog
1647 self.dlg = MatchesDialog(self.__ui, True)
1648 self.dlg.show()
1649 for occurrence in result["Entries"]:
1650 self.dlg.addEntry(
1651 # file name, lineno, unsure
1652 occurrence[0], occurrence[1], occurrence[2])
1653 else:
1654 E5MessageBox.warning(
1655 self.__ui, title,
1656 self.tr("No occurrences found."))
1657
1658 def __queryDefinition(self):
1659 """
1660 Private slot to handle the Find Definition action.
1661 """
1662 aw = e5App().getObject("ViewManager").activeWindow()
1663
1664 if aw is None:
1665 return
1666
1667 title = self.tr("Find Definition")
1668
1669 if not self.confirmAllBuffersSaved():
1670 return
1671
1672 filename = aw.getFileName()
1673 line, index = aw.getCursorPosition()
1674 offset = self.__getOffset(aw, line, index)
1675
1676 self.sendJson("QueryDefinition", {
1677 "Title": title,
1678 "FileName": filename,
1679 "Offset": offset,
1680 "Source": aw.text(),
1681 "Subcommand": "Query",
1682 })
1683
1684 def gotoDefinition(self, editor):
1685 """
1686 Public slot to find the definition for the word at the cursor position
1687 and go to it.
1688
1689 Note: This is executed upon a mouse click sequence.
1690
1691 @param editor reference to the calling editor (Editor)
1692 """
1693 filename = editor.getFileName()
1694 line, index = editor.getCursorPosition()
1695 offset = self.__getOffset(editor, line, index)
1696
1697 self.sendJson("QueryDefinition", {
1698 "Title": "",
1699 "FileName": filename,
1700 "Offset": offset,
1701 "Source": editor.text(),
1702 "Subcommand": "Goto",
1703 })
1704
1705 def __queryDefinitionResult(self, result):
1706 """
1707 Private method to handle the "Query Definition" result sent by
1708 the client.
1709
1710 @param result dictionary containing the result data
1711 @type dict
1712 """
1713 if result["Subcommand"] == "Query":
1714 if self.handleRopeError(result):
1715 title = result["Title"]
1716 if "Location" in result:
1717 location = result["Location"]
1718
1719 from MatchesDialog import MatchesDialog
1720 self.dlg = MatchesDialog(self.__ui, False)
1721 self.dlg.show()
1722 self.dlg.addEntry(location[0], location[1])
1723 # file name, lineno
1724 else:
1725 E5MessageBox.warning(
1726 self.__ui, title,
1727 self.tr("No matching definition found."))
1728 elif result["Subcommand"] == "Goto":
1729 if "Error" not in result:
1730 # ignore errors silently
1731 if "Location" in result:
1732 location = result["Location"]
1733 try:
1734 e5App().getObject("ViewManager").openSourceFile(
1735 location[0], location[1], addNext=True)
1736 except TypeError:
1737 # backward compatibility; <= 17.03
1738 e5App().getObject("ViewManager").openSourceFile(
1739 location[0], location[1], next=True)
1740 else:
1741 e5App().getObject("UserInterface").statusBar().showMessage(
1742 self.tr('No definition found'), 5000)
1743
1744 def __queryImplementations(self):
1745 """
1746 Private slot to handle the Find Implementations action.
1747 """
1748 aw = e5App().getObject("ViewManager").activeWindow()
1749
1750 if aw is None:
1751 return
1752
1753 title = self.tr("Find Implementations")
1754
1755 if not self.confirmAllBuffersSaved():
1756 return
1757
1758 filename = aw.getFileName()
1759 line, index = aw.getCursorPosition()
1760 offset = self.__getOffset(aw, line, index)
1761
1762 self.sendJson("QueryImplementations", {
1763 "Title": title,
1764 "FileName": filename,
1765 "Offset": offset,
1766 })
1767
1768 def __queryImplementationsResult(self, result):
1769 """
1770 Private method to handle the "Query Implementations" result sent by
1771 the client.
1772
1773 @param result dictionary containing the result data
1774 @type dict
1775 """
1776 if self.handleRopeError(result):
1777 title = result["Title"]
1778 if result["EntriesCount"] > 0:
1779 from MatchesDialog import MatchesDialog
1780 self.dlg = MatchesDialog(self.__ui, True)
1781 self.dlg.show()
1782 for occurrence in result["Entries"]:
1783 self.dlg.addEntry(
1784 # file name, lineno, unsure
1785 occurrence[0], occurrence[1], occurrence[2])
1786 else:
1787 E5MessageBox.warning(
1788 self.__ui, title, self.tr("No implementations found."))
1789
1790 #####################################################
1791 ## Various actions
1792 #####################################################
1793
1794 def __editConfig(self):
1795 """
1796 Private slot to open the rope configuration file in an editor.
1797 """
1798 ropedir = self.__ropeConfig["RopeFolderName"]
1799 configfile = ""
1800 if ropedir and os.path.exists(ropedir):
1801 configfile = os.path.join(ropedir, "config.py")
1802 if os.path.exists(configfile):
1803 from QScintilla.MiniEditor import MiniEditor
1804 self.__editor = MiniEditor(configfile)
1805 self.__editor.show()
1806 self.__editor.editorSaved.connect(self.__configChanged)
1807 else:
1808 E5MessageBox.critical(
1809 self.__ui,
1810 self.tr("Configure Rope"),
1811 self.tr("""The Rope configuration file '{0}' does"""
1812 """ not exist.""").format(configfile))
1813 else:
1814 E5MessageBox.critical(
1815 self.__ui,
1816 self.tr("Configure Rope"),
1817 self.tr("""The Rope admin directory does not exist."""))
1818
1819 def __updateConfig(self):
1820 """
1821 Private slot to update the configuration file.
1822 """
1823 res = E5MessageBox.yesNo(
1824 self.__ui,
1825 self.tr("Update Configuration"),
1826 self.tr("""Shall rope's current configuration be replaced """
1827 """by a new default configuration?"""))
1828 if res:
1829 src = self.__defaultConfig()
1830 cname = self.__ropeConfigFile()
1831 if src != "" and cname is not None:
1832 try:
1833 f = open(cname, "w")
1834 f.write(src)
1835 f.close()
1836 self.__configChanged()
1837 self.__editConfig()
1838 except IOError as err:
1839 E5MessageBox.critical(
1840 None,
1841 self.tr("Update Configuration"),
1842 self.tr("""<p>The configuration could not be"""
1843 """ updated.</p><p>Reason: {0}</p>""")
1844 .format(str(err)))
1845
1846 def __showRopeHelp(self):
1847 """
1848 Private slot to show help about the refactorings offered by Rope.
1849 """
1850 if self.__helpDialog is None:
1851 from HelpDialog import HelpDialog
1852 self.__helpDialog = \
1853 HelpDialog(self.tr("Help about rope refactorings"),
1854 self.__ropeConfig["RopeHelpFile"])
1855 self.__helpDialog.show()
1856
1857 def __performSOA(self):
1858 """
1859 Private slot to perform SOA on all modules.
1860 """
1861 title = self.tr("Analyse all modules")
1862 res = E5MessageBox.yesNo(
1863 self.__ui,
1864 title,
1865 self.tr("""This action might take some time. """
1866 """Do you really want to perform SOA?"""))
1867 if res:
1868
1869 self.sendJson("PerformSoa", {
1870 "Title": title,
1871 })
1872
1873 def __soaFinished(self, result):
1874 """
1875 Private method to handle the "Soa Finished" result sent by
1876 the client.
1877
1878 @param result dictionary containing the result data
1879 @type dict
1880 """
1881 if self.handleRopeError(result):
1882 title = result["Title"]
1883
1884 E5MessageBox.information(
1885 self.__ui,
1886 title,
1887 self.tr("""Static object analysis (SOA) done. """
1888 """SOA database updated."""))
1889
1890 ##################################################################
1891 ## methods below are private utility methods
1892 ##################################################################
1893
1894 def __processProgress(self, params):
1895 """
1896 Private method to handle Progress commands.
1897
1898 @param params dictionary containing the progress data
1899 @type dict
1900 """
1901 subcommand = params["Subcommand"]
1902 if subcommand == "Init":
1903 if self.__progressDialog is not None:
1904 self.__progressDialog.reset()
1905
1906 progressDialog = RopeProgressDialog(
1907 self, params["Title"], params["Interruptable"])
1908 progressDialog.show()
1909 progressDialog.raise_()
1910 self.__progressDialog = progressDialog
1911 QApplication.processEvents()
1912
1913 elif subcommand == "Progress":
1914 if self.__progressDialog is not None:
1915 self.__progressDialog.updateProgress(params)
1916 self.__progressDialog.raise_()
1917
1918 elif subcommand == "Reset":
1919 if self.__progressDialog is not None:
1920 self.__progressDialog.reset()
1921
1922 def __setConfig(self, params):
1923 """
1924 Private method to set the rope client configuration data.
1925
1926 @param params dictionary containing the configuration data
1927 @type dict
1928 """
1929 self.__ropeConfig = params
1930 # keys: RopeFolderName, DefaultConfig, RopeHelpFile,
1931 # RopeInfo, RopeVersion, RopeCopyright
1932
1933 def __ropeConfigFile(self):
1934 """
1935 Private method to get the name of the rope configuration file.
1936
1937 @return name of the rope configuration file (string)
1938 """
1939 configfile = None
1940 if self.__ropeConfig:
1941 ropedir = self.__ropeConfig["RopeFolderName"]
1942 if ropedir:
1943 configfile = os.path.join(ropedir, "config.py")
1944 if not os.path.exists(configfile):
1945 configfile = None
1946 return configfile
1947
1948 def __configChanged(self):
1949 """
1950 Private slot called, when the rope config file has changed.
1951 """
1952 self.sendJson("ConfigChanged", {})
1953
1954 def __defaultConfig(self):
1955 """
1956 Private slot to return the contents of rope's default configuration.
1957
1958 @return string containing the source of rope's default
1959 configuration (string)
1960 """
1961 if self.__ropeConfig and "DefaultConfig" in self.__ropeConfig:
1962 return self.__ropeConfig["DefaultConfig"]
1963 else:
1964 return ""
1965
1966 ##################################################################
1967 ## methods below are public utility methods
1968 ##################################################################
1969
1970 def getActions(self):
1971 """
1972 Public method to get a list of all actions.
1973
1974 @return list of all actions (list of E5Action)
1975 """
1976 return self.actions[:]
1977
1978 def projectOpened(self):
1979 """
1980 Public slot to handle the projectOpened signal.
1981 """
1982 if self.__projectopen:
1983 self.projectClosed()
1984
1985 self.__projectopen = True
1986 self.__projectpath = self.__e5project.getProjectPath()
1987 self.__projectLanguage = self.__e5project.getProjectLanguage()
1988
1989 ok = False
1990
1991 if self.__projectLanguage.startswith("Python"):
1992 # get interpreter from project first
1993 interpreter = self.__e5project.getDebugProperty("INTERPRETER")
1994 if not interpreter or not Utilities.isinpath(interpreter):
1995 # get it from debugger settings second
1996 if self.__projectLanguage == "Python2":
1997 interpreter = Preferences.getDebugger("PythonInterpreter")
1998 elif self.__projectLanguage == "Python3":
1999 interpreter = Preferences.getDebugger("Python3Interpreter")
2000 else:
2001 interpreter = ""
2002 if interpreter:
2003 ok = self.__startRefactoringClient(interpreter)
2004 if not ok:
2005 self.__ui.appendToStderr(self.tr(
2006 "Project language '{0}' is not supported because"
2007 " the configured interpreter could not be started."
2008 " Refactoring is disabled."
2009 ).format(self.__projectLanguage))
2010 else:
2011 for act in self.actions:
2012 act.setEnabled(True)
2013 else:
2014 self.__ui.appendToStderr(self.tr(
2015 "Project language '{0}' is not supported because no"
2016 " suitable interpreter is configured. Refactoring is"
2017 " disabled."
2018 ).format(self.__projectLanguage))
2019 else:
2020 self.__ui.appendToStderr(self.tr(
2021 "Refactoring for project language '{0}' is not supported."
2022 ).format(self.__projectLanguage))
2023
2024 self.__mainMenu.menuAction().setEnabled(ok)
2025
2026 def projectClosed(self):
2027 """
2028 Public slot to handle the projectClosed signal.
2029 """
2030 for act in self.actions:
2031 act.setEnabled(False)
2032 self.__mainMenu.menuAction().setEnabled(False)
2033
2034 if self.__helpDialog is not None:
2035 self.__helpDialog.close()
2036 self.__helpDialog = None
2037 if self.__historyDialog is not None:
2038 self.__historyDialog.close()
2039 self.__historyDialog = None
2040 for dlg in self.__refactoringDialogs.values():
2041 dlg.close()
2042 self.__refactoringDialogs = {}
2043
2044 self.sendJson("CloseProject", {}, flush=True)
2045
2046 self.__projectopen = False
2047 self.__projectpath = ''
2048 self.__projectLanguage = ""
2049 self.__ropeConfig = {}
2050
2051 self.stopClient()
2052
2053 def confirmBufferIsSaved(self, editor):
2054 """
2055 Public method to check, if an editor has unsaved changes.
2056
2057 @param editor reference to the editor to be checked
2058 @return flag indicating, that the editor doesn't contain
2059 unsaved edits (boolean)
2060 """
2061 res = editor.checkDirty()
2062 self.sendJson("Validate", {})
2063 return res
2064
2065 def confirmAllBuffersSaved(self):
2066 """
2067 Public method to check, if any editor has unsaved changes.
2068
2069 @return flag indicating, that no editor contains unsaved edits
2070 (boolean)
2071 """
2072 res = e5App().getObject("ViewManager").checkAllDirty()
2073 self.sendJson("Validate", {})
2074 return res
2075
2076 def refreshEditors(self, changedFiles):
2077 """
2078 Public method to refresh modified editors.
2079
2080 @param changedFiles list of changed files
2081 @type list of str
2082 """
2083 vm = e5App().getObject("ViewManager")
2084 openFiles = [Utilities.normcasepath(f) for f in vm.getOpenFilenames()]
2085
2086 for fileName in changedFiles:
2087 normfile = Utilities.normcasepath(fileName)
2088 if normfile in openFiles:
2089 editor = vm.getEditor(normfile)[1]
2090 editor.refresh()
2091
2092 aw = vm.activeWindow()
2093 if aw is not None:
2094 filename = aw.getFileName()
2095 if filename is not None:
2096 vm.openSourceFile(filename, aw.getCursorPosition()[0] + 1)
2097
2098 def reportChanged(self, filename, oldSource):
2099 """
2100 Public slot to report some changed sources.
2101
2102 @param filename file name of the changed source (string)
2103 @param oldSource source code before the change (string)
2104 """
2105 if self.__e5project.isOpen() and \
2106 self.__e5project.isProjectFile(filename):
2107 self.sendJson("ReportChanged", {
2108 "FileName": filename,
2109 "OldSource": oldSource,
2110 })
2111
2112 #######################################################################
2113 ## Methods below handle the network connection
2114 #######################################################################
2115
2116 def handleCall(self, method, params):
2117 """
2118 Public method to handle a method call from the client.
2119
2120 Note: This is an empty implementation that must be overridden in
2121 derived classes.
2122
2123 @param method requested method name
2124 @type str
2125 @param params dictionary with method specific parameters
2126 @type dict
2127 """
2128 self.__methodMapping[method](params)
2129
2130 def __processClientException(self, params):
2131 """
2132 Private method to handle exceptions of the refactoring client.
2133
2134 @param params dictionary containing the exception data
2135 @type dict
2136 """
2137 if params["ExceptionType"] == "ProtocolError":
2138 E5MessageBox.critical(
2139 None,
2140 self.tr("Refactoring Protocol Error"),
2141 self.tr("""<p>The data received from the refactoring"""
2142 """ server could not be decoded. Please report"""
2143 """ this issue with the received data to the"""
2144 """ eric bugs email address.</p>"""
2145 """<p>Error: {0}</p>"""
2146 """<p>Data:<br/>{0}</p>""").format(
2147 params["ExceptionValue"],
2148 Utilities.html_encode(params["ProtocolData"])),
2149 E5MessageBox.StandardButtons(
2150 E5MessageBox.Ok))
2151 else:
2152 E5MessageBox.critical(
2153 None,
2154 self.tr("Refactoring Client Error"),
2155 self.tr("<p>An exception happened in the refactoring"
2156 " client. Please report it to the eric bugs"
2157 " email address.</p>"
2158 "<p>Exception: {0}</p>"
2159 "<p>Value: {1}</p>"
2160 "Traceback: {2}</p>").format(
2161 Utilities.html_encode(params["ExceptionType"]),
2162 params["ExceptionValue"],
2163 params["Traceback"].replace("\r\n", "<br/>")
2164 .replace("\n", "<br/>").replace("\r", "<br/>"),
2165 ),
2166 E5MessageBox.StandardButtons(
2167 E5MessageBox.Ok))
2168
2169 def __startRefactoringClient(self, interpreter):
2170 """
2171 Private method to start the refactoring client.
2172
2173 @param interpreter interpreter to be used for the refactoring client
2174 @type str
2175 @return flag indicating a successful client start
2176 @rtype bool
2177 """
2178 client = os.path.join(os.path.dirname(__file__),
2179 "RefactoringClient.py")
2180 ok = self.startClient(interpreter, client, [self.__projectpath])
2181 return ok

eric ide

mercurial