RefactoringRope/MoveDialog.py

Wed, 26 May 2021 19:07:42 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 26 May 2021 19:07:42 +0200
branch
eric7
changeset 365
f740b50380df
parent 354
a967ff16629a
child 374
958f34e97952
permissions
-rw-r--r--

Ported the plug-in to PyQt6 for eric7.

# -*- coding: utf-8 -*-

# Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the Move Method or Module dialog.
"""

import os

from PyQt6.QtCore import pyqtSlot
from PyQt6.QtWidgets import QDialogButtonBox, QAbstractButton

from EricWidgets import EricFileDialog, EricMessageBox
from EricWidgets.EricApplication import ericApp
from EricWidgets.EricCompleters import EricFileCompleter

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 RefactoringServer
        @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 = EricFileCompleter(self.destinationEdit)
        
        self.__filename = filename
        self.__offset = offset
        
        self.__project = ericApp().getObject("Project")
        
        self.__okButton = self.buttonBox.button(
            QDialogButtonBox.StandardButton.Ok)
        self.__okButton.setEnabled(False)
        self.__previewButton = self.buttonBox.addButton(
            self.tr("Preview"), QDialogButtonBox.ButtonRole.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)
        destination = (
            EricFileDialog.getOpenFileName(
                self,
                self.windowTitle(),
                dest,
                self.tr("Python Files (*.py *.py3);;All Files (*)"))
            if self.__moveType == "move_global_method" else
            # move_module
            EricFileDialog.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.""")
                EricMessageBox.critical(
                    self,
                    self.windowTitle(),
                    errorMessage)
                return
            
            if self.__moveType == "move_global_method":
                if not os.path.exists(destination):
                    EricMessageBox.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")):
                    EricMessageBox.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
        @rtype bool
        """
        destination = os.path.join(
            self.__project.getProjectPath(),
            self.destinationEdit.text())
        if self.__moveType == "move_global_method":
            if not os.path.exists(destination):
                EricMessageBox.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")):
                EricMessageBox.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