RefactoringRope/MoveDialog.py

branch
server_client_variant
changeset 178
70b4fb448811
parent 147
3f8a995f6e49
child 189
2711fdd91925
diff -r 963fc1b0ba6e -r 70b4fb448811 RefactoringRope/MoveDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RefactoringRope/MoveDialog.py	Fri Sep 22 19:47:36 2017 +0200
@@ -0,0 +1,305 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2010 - 2017 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the Move Method or Module dialog.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import pyqtSlot
+from PyQt5.QtWidgets import QDialogButtonBox, QAbstractButton
+
+from E5Gui import E5FileDialog, E5MessageBox
+from E5Gui.E5Application import e5App
+from E5Gui.E5Completers import E5FileCompleter
+
+from Ui_MoveDialog import Ui_MoveDialog
+from RefactoringDialogBase import RefactoringDialogBase
+
+import Utilities
+
+
+class MoveDialog(RefactoringDialogBase, Ui_MoveDialog):
+    """
+    Class implementing the Move Method or Module dialog.
+    """
+    def __init__(self, refactoring, title, filename, offset, parent=None):
+        """
+        Constructor
+        
+        @param refactoring reference to the main refactoring object
+        @type Refactoring
+        @param title title of the dialog
+        @type str
+        @param filename file name to be worked on
+        @type str
+        @param offset offset within file
+        @type int or None
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        RefactoringDialogBase.__init__(self, refactoring, title, parent)
+        self.setupUi(self)
+        
+        self._changeGroupName = "Move"
+        
+        self.__destinationCompleter = E5FileCompleter(self.destinationEdit)
+        
+        self.__filename = filename
+        self.__offset = offset
+        
+        self.__project = e5App().getObject("Project")
+        
+        self.__okButton = self.buttonBox.button(QDialogButtonBox.Ok)
+        self.__okButton.setEnabled(False)
+        self.__previewButton = self.buttonBox.addButton(
+            self.tr("Preview"), QDialogButtonBox.ActionRole)
+        self.__previewButton.setDefault(True)
+        
+        self.moveStackWidget.setCurrentIndex(0)
+        
+        self.__moveType = ""
+        
+        if offset is None:
+            # it is a 'move module' refactoring, no need to determine
+            # the move type via the client
+            self.__processMoveType({"Kind": "move_module"})
+        else:
+            self._refactoring.sendJson("RequestMoveType", {
+                "ChangeGroup": self._changeGroupName,
+                "Title": self._title,
+                "FileName": self.__filename,
+                "Offset": self.__offset,
+            })
+    
+    def __processMoveType(self, data):
+        """
+        Private method to process the move type data sent by the refactoring
+        client in order to polish the dialog.
+        
+        @param data dictionary containing the move type data
+        @type dict
+        """
+        self.__moveType = data["Kind"]
+        
+        if self.__moveType == "move_method":
+            self.setWindowTitle(self.tr("Move Method"))
+            self.moveStackWidget.setCurrentIndex(1)
+            self.methodEdit.setText(data["Method"])
+            self.methodEdit.selectAll()
+        elif self.__moveType == "move_global_method":
+            self.setWindowTitle(self.tr("Move Global Method"))
+            self.moveStackWidget.setCurrentIndex(2)
+            self.destinationLabel.setText(self.tr("Destination Module:"))
+            self.destinationEdit.setToolTip(self.tr(
+                "Enter the destination module for the method"))
+            self.selectButton.setToolTip(self.tr(
+                "Select the destination module via a file selection dialog"))
+        elif self.__moveType == "move_module":
+            self.setWindowTitle(self.tr("Move Module"))
+            self.moveStackWidget.setCurrentIndex(2)
+            self.destinationLabel.setText(self.tr("Destination Package:"))
+            self.destinationEdit.setToolTip(self.tr(
+                "Enter the destination package for the module"))
+            self.selectButton.setToolTip(self.tr(
+                "Select the destination package via a directory selection"
+                " dialog"))
+        else:
+            self.setWindowTitle(self.tr("Move"))
+            self.moveStackWidget.setCurrentIndex(0)
+        
+        self.__updateUI()
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+    
+    @pyqtSlot(str)
+    def on_attributeEdit_textChanged(self, text):
+        """
+        Private slot to react to changes of the attribute.
+        
+        @param text text entered into the edit
+        @type str
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_methodEdit_textChanged(self, text):
+        """
+        Private slot to react to changes of the method.
+        
+        @param text text entered into the edit
+        @type str
+        """
+        self.__updateUI()
+    
+    @pyqtSlot(str)
+    def on_destinationEdit_textChanged(self, text):
+        """
+        Private slot to react to changes of the destination module.
+        
+        @param text text entered into the edit
+        @type str
+        """
+        self.__updateUI()
+    
+    def __updateUI(self):
+        """
+        Private method to perform various UI updates.
+        """
+        if self.__moveType == "move_method":
+            enable = self.attributeEdit.text() != "" and \
+                self.methodEdit.text() != ""
+        elif self.__moveType in ["move_global_method", "move_module"]:
+            enable = self.destinationEdit.text() != ""
+        else:
+            enable = False
+        
+        self.__okButton.setEnabled(enable)
+        self.__previewButton.setEnabled(enable)
+    
+    @pyqtSlot()
+    def on_selectButton_clicked(self):
+        """
+        Private slot called to select the destination module via a file
+        selection dialog.
+        """
+        dest = self.destinationEdit.text()
+        if not dest:
+            dest = self.__project.getProjectPath()
+        elif not os.path.isabs(dest):
+            dest = os.path.join(self.__project.getProjectPath(), dest)
+        if self.__moveType == "move_global_method":
+            destination = E5FileDialog.getOpenFileName(
+                self,
+                self.windowTitle(),
+                dest,
+                self.tr("Python Files (*.py *.py2 *.py3);;All Files (*)"))
+        else:
+            # move_module
+            destination = E5FileDialog.getExistingDirectory(
+                self,
+                self.windowTitle(),
+                dest)
+        
+        if destination:
+            destination = Utilities.toNativeSeparators(destination)
+            if not self.__project.startswithProjectPath(destination):
+                if self.__moveType == "move_global_method":
+                    errorMessage = self.tr("""The selected module must be """
+                                           """inside the project.""")
+                else:
+                    # move_module
+                    errorMessage = self.tr("""The selected directory must"""
+                                           """ be inside the project.""")
+                E5MessageBox.critical(
+                    self,
+                    self.windowTitle(),
+                    errorMessage)
+                return
+            
+            if self.__moveType == "move_global_method":
+                if not os.path.exists(destination):
+                    E5MessageBox.critical(
+                        self,
+                        self.windowTitle(),
+                        self.tr("""The selected module <b>{0}</b> does"""
+                                """ not exist.""").format(destination))
+                    return
+            else:
+                # move_module
+                if not os.path.exists(
+                        os.path.join(destination, "__init__.py")):
+                    E5MessageBox.critical(
+                        self,
+                        self.windowTitle(),
+                        self.tr("""The selected directory <b>{0}</b> is"""
+                                """ not a package.""").format(destination))
+                    return
+            
+            destination = self.__project.getRelativePath(destination)
+            self.destinationEdit.setText(destination)
+    
+    def __checkDestination(self):
+        """
+        Private method to check the destination entered.
+        
+        @return flag indicating a valid entry (boolean)
+        """
+        destination = os.path.join(
+            self.__project.getProjectPath(),
+            self.destinationEdit.text())
+        if self.__moveType == "move_global_method":
+            if not os.path.exists(destination):
+                E5MessageBox.critical(
+                    self,
+                    self.windowTitle(),
+                    self.tr("""The selected module <b>{0}</b> does"""
+                            """ not exist.""").format(destination))
+                return False
+        else:
+            # move_module
+            if not os.path.exists(os.path.join(destination, "__init__.py")):
+                E5MessageBox.critical(
+                    self,
+                    self.windowTitle(),
+                    self.tr("""The selected directory <b>{0}</b> is"""
+                            """ not a package.""").format(destination))
+                return False
+        
+        return True
+    
+    @pyqtSlot(QAbstractButton)
+    def on_buttonBox_clicked(self, button):
+        """
+        Private slot to act on the button pressed.
+        
+        @param button reference to the button pressed
+        @type QAbstractButton
+        """
+        if self.__moveType == "move_method" or (
+            self.__moveType in ["move_global_method", "move_module"] and 
+                self.__checkDestination()):
+            if button == self.__previewButton:
+                self.requestPreview()
+            elif button == self.__okButton:
+                self.applyChanges()
+    
+    def _calculateChanges(self):
+        """
+        Protected method to initiate the calculation of the changes.
+        """
+        newName = self.methodEdit.text()
+        if not newName:
+            newName = None
+        
+        self._refactoring.sendJson("CalculateMoveChanges", {
+            "ChangeGroup": self._changeGroupName,
+            "Title": self.windowTitle(),
+            "FileName": self.__filename,
+            "Offset": self.__offset,
+            "Kind": self.__moveType,
+            "NewName": newName,
+            "Attribute": self.attributeEdit.text(),
+            "DestinationModule": self.destinationEdit.text(),
+        })
+    
+    def processChangeData(self, data):
+        """
+        Public method to process the change data sent by the refactoring
+        client.
+        
+        @param data dictionary containing the change data
+        @type dict
+        """
+        subcommand = data["Subcommand"]
+        if subcommand == "MoveType":
+            self.__processMoveType(data)
+        else:
+            # pass on to base class
+            RefactoringDialogBase.processChangeData(self, data)

eric ide

mercurial