class QadCommandClass(QObject): # derivato da QObject per gestire il metodo sender()
   def showMsg(self, msg, displayPromptAfterMsg = False):
      if self.plugIn is not None:
         self.plugIn.showMsg(msg, displayPromptAfterMsg)
         
   def showErr(self, err):
      if self.plugIn is not None:
         self.plugIn.showErr(err)

   def showInputMsg(self, inputMsg, inputType, default = None, keyWords = "", \
                    inputMode = QadInputModeEnum.NONE):
      if self.plugIn is not None:
         self.plugIn.showInputMsg(inputMsg, inputType, default, keyWords, inputMode)

      # inizializzo il menu contestuale
      self.initContextualMenu(inputType, keyWords)


   def initContextualMenu(self, inputType, keyWords):
      if self.plugIn is None:
         return
      
      if keyWords == "":
         if self.contextualMenu:
            del self.contextualMenu
            self.contextualMenu = None
         return

      self.contextualMenu = QadContextualMenuClass(self.plugIn, inputType, keyWords)


   def enterActionByContextualMenu(self):
      self.plugIn.showEvaluateMsg(None)

   
   def cancelActionByContextualMenu(self):
      self.plugIn.abortCommand()


   def showEvaluateMsgByContextualMenu(self):
      sender = self.sender()
      self.plugIn.showEvaluateMsg(sender.text())


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = QadGetPoint(self.plugIn, drawMode) # per selezione di un punto
         return self.PointMapTool
      else:
         return None


   def getCurrentContextualMenu(self):
      return self.contextualMenu


   def hidePointMapToolMarkers(self):
      if self.PointMapTool is not None:
         self.PointMapTool.hidePointMapToolMarkers()

   def setMapTool(self, mapTool):
      if self.plugIn is not None:
         # setto il maptool per l'input via finestra grafica
         self.plugIn.canvas.setMapTool(mapTool)
         self.plugIn.mainAction.setChecked(True)     

   def waitForPoint(self, msg = QadMsg.translate("QAD", "Specify point: "), \
                    default = None, inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.POINT2D, default, "", inputMode)

   def waitForString(self, msg, default = None, inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.STRING, default, "", inputMode)

   def waitForInt(self, msg, default = None, inputMode = QadInputModeEnum.NOT_NULL):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.INT, default, "", inputMode)

   def waitForLong(self, msg, default = None, inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.LONG, default, "", inputMode)

   def waitForFloat(self, msg, default = None, inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.FLOAT, default, "", inputMode)

   def waitForBool(self, msg, default = None, inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.BOOL, default, "", inputMode)

   def waitForSelSet(self, msg = QadMsg.translate("QAD", "Select objects: ")):
      self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_RECTANGLE)
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, QadInputTypeEnum.POINT2D)

   def waitFor(self, msg, inputType, default = None, keyWords = "", \
               inputMode = QadInputModeEnum.NONE):
      self.setMapTool(self.getPointMapTool())
      # setto l'input via finestra di testo
      self.showInputMsg(msg, inputType, default, keyWords, inputMode)

   def getCurrMsgFromTxtWindow(self):
      if self.plugIn is not None:
         return self.plugIn.getCurrMsgFromTxtWindow()
      else:
         return None
         
   def showEvaluateMsg(self, msg = None):
      if self.plugIn is not None:
         self.plugIn.showEvaluateMsg(msg)

   def runCommandAbortingTheCurrent(self):
      self.plugIn.runCommandAbortingTheCurrent(self.getName())
      
   def getToolTipText(self):
      text = self.getName()
      if self.getNote() > 0:
         text = text + "\n\n" + self.getNote()
      return text
      
   #============================================================================
   # funzioni da sovrascrivere con le classi ereditate da questa
   #============================================================================
   def getName(self):
      """ impostare il nome del comando in maiuscolo """
      return ""

   def getEnglishName(self):
      """ impostare il nome del comando in inglese maiuscolo """
      return ""

   def connectQAction(self, action):
      pass     
      #QObject.connect(action, SIGNAL("triggered()"), self.plugIn.runPLINECommand)

   def getIcon(self):
      # impostare l'icona  del comando (es. QIcon(":/plugins/qad/icons/pline.png"))
      # ricordarsi di inserire l'icona in resources.qrc e di ricompilare le risorse
      return None

   def getNote(self):
      """ impostare le note esplicative del comando """
      return ""
   
   def __init__(self, plugIn):
      QObject.__init__(self)      
      self.plugIn       = plugIn
      self.PointMapTool = None
      self.step         = 0      
      self.isValidPreviousInput = True # per gestire il comando anche in macro
      self.contextualMenu = None
      
      # inizializzare tutti i maptool necessari al comando
      # esempio di struttura di un comando che richiede
      # 1) un punto
      # self.mapTool = QadGetPoint(self.plugIn) # per selezione di un punto


   def __del__(self):
      """ distruttore """
      self.hidePointMapToolMarkers()
      
      if self.PointMapTool:
         self.PointMapTool.removeItems()
         del self.PointMapTool
         self.PointMapTool = None
         
      if self.contextualMenu:
         #QObject.disconnect(enterAction, SIGNAL("triggered()"), self.enterActionByContextualMenu)

         del self.contextualMenu
         self.contextualMenu = None
      
      
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return None
   
   def run(self, msgMapTool = False, msg = None):
      """
      Esegue il comando. 
      - msgMapTool; se True significa che arriva un valore da MapTool del comando
                    se false significa che il valore é nel parametro msg
      - msg;        valore in input al comando (usato quando msgMapTool = False)
      
      ritorna True se il comando é terminato altrimenti False
      """
      # esempio di struttura di un comando che richiede
      # 1) un punto
      if self.step == 0: # inizio del comando
         self.waitForPoint() # si appresta ad attendere un punto
         self.step = self.step + 1
         return False
      elif self.step == 1: # dopo aver atteso un punto si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               self.setMapTool(self.getPointMapTool()) # riattivo il maptool
               return False

            pt = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            pt = msg
            
         return True

   def mapToLayerCoordinates(self, layer, point_geom):
      # transform point o geometry coordinates from output CRS to layer's CRS 
      if self.plugIn is None:
         return None
      if type(point_geom) == QgsPoint:
         return self.plugIn.canvas.mapSettings().mapToLayerCoordinates(layer, point_geom)
      elif type(point_geom) == QgsGeometry:
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         coordTransform = QgsCoordinateTransform(self.plugIn.canvas.mapSettings().destinationCrs(), layer.crs())
         g = QgsGeometry(point_geom)
         g.transform(coordTransform)
         return g
      elif (type(point_geom) == list or type(point_geom) == tuple): # lista di punti o di geometrie
         coordTransform = QgsCoordinateTransform(self.plugIn.canvas.mapSettings().destinationCrs(), layer.crs())
         res = []
         for pt in point_geom:
            if type(pt) == QgsPoint:
               res.append(coordTransform.transform(pt))
            elif type(point_geom) == QgsGeometry:
               g = QgsGeometry(point_geom)
               g.transform(coordTransform)
               res.append(g)
         return res
      else:
         return None

   def layerToMapCoordinates(self, layer, point_geom):
      # transform point o geometry coordinates from layer's CRS to output CRS 
      if self.plugIn is None:
         return None
      if type(point_geom) == QgsPoint:
         return self.plugIn.canvas.mapSettings().layerToMapCoordinates(layer, point_geom)
      elif type(point_geom) == QgsGeometry:
         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         coordTransform = QgsCoordinateTransform(layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs())
         g = QgsGeometry(point_geom)
         g.transform(coordTransform)
         return g
      elif (type(point_geom) == list or type(point_geom) == tuple): # lista di punti o di geometrie
         coordTransform = QgsCoordinateTransform(self.plugIn.canvas.mapSettings().destinationCrs(), layer.crs())
         res = []
         for pt in point_geom:
            if type(pt) == QgsPoint:
               res.append(coordTransform.transform(pt))
            elif type(point_geom) == QgsGeometry:
               g = QgsGeometry(point_geom)
               g.transform(coordTransform)
               res.append(g)
         return res
      else:
         return None class QadSSGetClass(QadCommandClass):
# Classe che gestisce la selezione di oggetti geometrici

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadSSGetClass(self.plugIn)
      
   def __init__(self, plugIn):
      self.init(plugIn)

   def __del__(self):
      QadCommandClass.__del__(self)
      #self.entitySet.deselectOnLayer()

   def init(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.AddOnSelection = True # se = False significa remove
      self.entitySet = QadEntitySet()
      self.points = []
      self.currSelectionMode = ""
      # opzioni per limitare gli oggetti da selezionare
      self.onlyEditableLayers = False
      self.checkPointLayer = True
      self.checkLineLayer = True
      self.checkPolygonLayer = True
      self.checkDimLayers = True # include tutte le features che compongono le quotature selezionate
      
      self.help = False
      # se SingleSelection = True viene selezionato il primo oggetto o gruppo di oggetti indicato,
      # senza che vengano richieste altre selezioni.      
      self.SingleSelection = False
      self.pickAdd = QadVariables.get(QadMsg.translate("Environment variables", "PICKADD"))
      
      # se exitAfterSelection = True il comando viene terminato dopo una qualunque selezione 
      # indipendentemente che sia stato selezionato o meno un oggetto o gruppo di oggetti.
      # usato da QadVirtualSelCommandClass
      self.exitAfterSelection = False
      
      # selezione degli oggetti aggiunti più recentemente al gruppo di selezione (x opzione annulla)
      self.lastEntitySet = QadEntitySet()
      self.PLINECommand = None
      self.CIRCLECommand = None
      self.MPOLYGONCommand = None
      self.MBUFFERCommand = None
      self.SSGetClass = None

   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.step == 4: # quando si é in fase di disegno linea
         return self.PLINECommand.getPointMapTool(drawMode)
      elif self.step == 5: # quando si é in fase di disegno cerchio
         return self.CIRCLECommand.getPointMapTool(drawMode)
      elif self.step == 6: # quando si é in fase di selezione entità
         return self.SSGetClass.getPointMapTool(drawMode)
      elif self.step == 7: # quando si é in fase di disegno polygono
         return self.MPOLYGONCommand.getPointMapTool(drawMode)
      elif self.step == 8: # quando si é in fase di disegno buffer 
         return self.MBUFFERCommand.getPointMapTool(drawMode)      
      else:
         ptMapTool = QadCommandClass.getPointMapTool(self, drawMode)
         ptMapTool.setSnapType(QadSnapTypeEnum.DISABLE)
         ptMapTool.setOrthoMode(0)
         return ptMapTool


   def getCurrentContextualMenu(self):
      if self.step == 4: # quando si é in fase di disegno linea
         return self.PLINECommand.getCurrentContextualMenu()
      elif self.step == 5: # quando si é in fase di disegno cerchio
         return self.CIRCLECommand.getCurrentContextualMenu()
      elif self.step == 6: # quando si é in fase di selezione entità
         return self.SSGetClass.getCurrentContextualMenu()
      elif self.step == 7: # quando si é in fase di disegno polygono
         return self.MPOLYGONCommand.getCurrentContextualMenu()
      elif self.step == 8: # quando si é in fase di disegno buffer 
         return self.MBUFFERCommand.getCurrentContextualMenu()     
      else:
         return self.contextualMenu

   
   #============================================================================
   # getLayersToCheck
   #============================================================================
   def getLayersToCheck(self):
      layerList = []
      for layer in qad_utils.getVisibleVectorLayers(self.plugIn.canvas): # Tutti i layer vettoriali visibili
         # considero solo i layer vettoriali che sono filtrati per tipo
         if ((layer.geometryType() == QGis.Point and self.checkPointLayer == True) or \
             (layer.geometryType() == QGis.Line and self.checkLineLayer == True) or \
             (layer.geometryType() == QGis.Polygon and self.checkPolygonLayer == True)) and \
             (self.onlyEditableLayers == False or layer.isEditable()):
            # se devo includere i layers delle quotature
            if self.checkDimLayers == True or \
               len(QadDimStyles.getDimListByLayer(layer)) == 0:
               layerList.append(layer)
         
      return layerList


   #============================================================================
   # showMsgOnAddRemove
   #============================================================================
   def showMsgOnAddRemove(self, found):
      msg = QadMsg.translate("Command_SSGET", " found {0}, total {1}")
      self.showMsg(msg.format(found, self.entitySet.count()), False) # non ripete il prompt 2016


   #============================================================================
   # elaborateEntity
   #============================================================================
   def elaborateEntity(self, entity, shiftKey):
      if self.AddOnSelection == True: # aggiungi al gruppo di selezione
         if shiftKey: # se la selezione é avvenuta con shift premuto
            if self.pickAdd == 0: # The objects most recently selected become the selection set
               if self.entitySet.containsEntity(entity): # se l'entità era già stata selezionata
                  self.AddRemoveEntity(entity, False) # rimuovo l'entità
               else:
                  self.AddRemoveEntity(entity, True) # aggiungo l'entità
            else:
               self.AddRemoveEntity(entity, False) # rimuovo l'entità
         else: # senza tasto shift
            if self.pickAdd == 0: # The objects most recently selected become the selection set
               self.SetEntity(entity)
            else:
               self.AddRemoveEntity(entity, True) # aggiungo l'entità
      else: # se si deve rimuovere dal gruppo di selezione
         self.AddRemoveEntity(entity, False) # rimuovo l'entità


   #============================================================================
   # SetEntity
   #============================================================================
   def SetEntity(self, entity):
      # controllo sul layer
      if self.onlyEditableLayers == True and entity.layer.isEditable() == False:
         self.showMsgOnAddRemove(0)
         return
      # controllo sul tipo
      if (self.checkPointLayer == False and entity.layer.geometryType() == QGis.Point) or \
         (self.checkLineLayer == False and entity.layer.geometryType() == QGis.Line) or \
         (self.checkPolygonLayer == False and entity.layer.geometryType() == QGis.Polygon):
         self.showMsgOnAddRemove(0)
         return
      
      # controllo su layer delle quotature
      # verifico se l'entità appartiene ad uno stile di quotatura
      dimEntity = QadDimStyles.getDimEntity(entity)
      if self.checkDimLayers == False and dimEntity is not None:
         self.showMsgOnAddRemove(0)
         return

      self.entitySet.deselectOnLayer()
      self.entitySet.clear()
      self.entitySet.addEntity(entity)

      if self.checkDimLayers == True and dimEntity is not None:
         # Aggiungo i componenenti della quotatura a set <entitySet>
         self.entitySet.unite(dimEntity.getEntitySet())

      self.showMsgOnAddRemove(self.entitySet.count())
      self.entitySet.selectOnLayer(False) # incremental = False aaaaaaaaaaaaaaaaaaaaaaaaaa qui parte l'evento activate di qad_maptool (se il layer non è in modifica)
      self.lastEntitySet.clear()
      self.lastEntitySet.addEntity(entity)


   #============================================================================
   # AddRemoveEntity
   #============================================================================
   def AddRemoveEntity(self, entity, Add):
      # controllo sul layer
      if self.onlyEditableLayers == True and entity.layer.isEditable() == False:
         self.showMsgOnAddRemove(0)
         return
      # controllo sul tipo
      if (self.checkPointLayer == False and entity.layer.geometryType() == QGis.Point) or \
         (self.checkLineLayer == False and entity.layer.geometryType() == QGis.Line) or \
         (self.checkPolygonLayer == False and entity.layer.geometryType() == QGis.Polygon):
         self.showMsgOnAddRemove(0)
         return
      # controllo su layer delle quotature
      if self.checkDimLayers == False and len(QadDimStyles.getDimListByLayer(entity.layer)) > 0:
         self.showMsgOnAddRemove(0)
         return
      
      self.entitySet.deselectOnLayer()
      if Add == True: # aggiungi al gruppo di selezione
         self.entitySet.addEntity(entity)
      else: # rimuovi dal gruppo di selezione
         self.entitySet.removeEntity(entity)

      if self.checkDimLayers == True:
         dimEntitySet = QadEntitySet()
         dimEntitySet.addEntity(entity)
         # La funzione verifica se le entità che fanno parte di un entitySet sono anche parte di quotatura e,
         # in caso affermativo, aggiunge/rimuove tutti i componenti delle quotature all'entitySet.
         QadDimStyles.addAllDimComponentsToEntitySet(dimEntitySet, self.onlyEditableLayers)
         if Add == True: # aggiungi al gruppo di selezione
            self.entitySet.unite(dimEntitySet)
         else: # rimuovi dal gruppo di selezione
            self.entitySet.subtract(dimEntitySet)
         self.showMsgOnAddRemove(dimEntitySet.count())
      else:
         self.showMsgOnAddRemove(1)
         
      self.entitySet.selectOnLayer(False) # incremental = False
      self.lastEntitySet.clear()
      self.lastEntitySet.addEntity(entity)


   #============================================================================
   # elaborateSelSet
   #============================================================================
   def elaborateSelSet(self, selSet, shiftKey):
      if self.checkDimLayers == True:
         dimEntitySet = QadEntitySet(selSet)
         # La funzione verifica se le entità che fanno parte di un entitySet sono anche parte di quotatura e,
         # in caso affermativo, aggiunge tutti i componenti delle quotature all'entitySet.
         QadDimStyles.addAllDimComponentsToEntitySet(dimEntitySet, self.onlyEditableLayers)
         selSet.unite(dimEntitySet)

      if self.AddOnSelection == True: # aggiungi al gruppo di selezione
         if shiftKey: # se la selezione é avvenuta con shift premuto
            if self.pickAdd == 0: # The objects most recently selected become the selection set
               # verifico se ci sono degli oggetti non ancora selezionati
               intersectSS = QadEntitySet(selSet)
               intersectSS.subtract(self.entitySet)
               if intersectSS.isEmpty(): # tutti gli oggetti erano già selezionati
                  self.AddRemoveSelSet(selSet, False) # rimuovo il gruppo di selezione
               else:
                  self.AddRemoveSelSet(selSet, True) # aggiungo il gruppo di selezione
            else:
               self.AddRemoveSelSet(selSet, False) # rimuovo il gruppo di selezione
         else: # senza tasto shift
            if self.pickAdd == 0: # The objects most recently selected become the selection set
               self.SetSelSet(selSet)
            else:
               self.AddRemoveSelSet(selSet, True) # aggiungo il gruppo di selezione
      else: # se si deve rimuovere dal gruppo di selezione
         self.AddRemoveEntity(selSet, False) # rimuovo  il gruppo di selezione

    
   #============================================================================
   # SetSelSet
   #============================================================================
   def SetSelSet(self, selSet):
      for layerEntitySet in self.entitySet.layerEntitySetList:
         # se il layer non é presente in selSet
         if selSet.findLayerEntitySet(layerEntitySet) is None:            
            layerEntitySet.deselectOnLayer()
         else:
            layerEntitySet.deselectOnLayer()

      self.entitySet.set(selSet)

      self.showMsgOnAddRemove(self.entitySet.count())
      self.entitySet.selectOnLayer(False) # incremental = False
      self.lastEntitySet.set(selSet)


   #============================================================================
   # AddCurrentQgsSelectedFeatures
   #============================================================================
   def AddCurrentQgsSelectedFeatures(self):
      # verifico se ci sono entità correntemente selezionate
      self.entitySet.initByCurrentQgsSelectedFeatures(self.getLayersToCheck())
      found = self.entitySet.count()
      if found > 0:
         msg = QadMsg.translate("Command_SSGET", "\nfound {0}")
         self.showMsg(msg.format(found), False) # non ripete il prompt
         return True
      else:
         return False


   #============================================================================
   # AddRemoveSelSet
   #============================================================================
   def AddRemoveSelSet(self, selSet, Add):
      self.entitySet.deselectOnLayer()
      if Add == True: # aggiungi al gruppo di selezione
         self.entitySet.unite(selSet)
      else: # rimuovi dal gruppo di selezione
         self.entitySet.subtract(selSet)

      self.showMsgOnAddRemove(selSet.count())

      self.entitySet.selectOnLayer(False) # incremental = False
      self.lastEntitySet.set(selSet)

   #============================================================================
   # AddRemoveSelSetByFence
   #============================================================================
   def AddRemoveSelSetByFence(self, points):
      if len(points) > 1:
         selSet = qad_utils.getSelSet("F", self.getPointMapTool(), points, \
                                      self.getLayersToCheck())
         self.elaborateSelSet(selSet, False)

   #============================================================================
   # AddRemoveSelSetByPolygon
   #============================================================================
   def AddRemoveSelSetByPolygon(self, mode, points):
      if len(points) > 2:
         selSet = qad_utils.getSelSet(mode, self.getPointMapTool(), points, \
                                      self.getLayersToCheck())
         self.elaborateSelSet(selSet, False)

   #============================================================================
   # AddRemoveSelSetByGeometry
   #============================================================================
   def AddRemoveSelSetByGeometry(self, mode, geom):
      if type(geom) == QgsGeometry: # singola geometria
         selSet = qad_utils.getSelSet(mode, self.getPointMapTool(), geom, \
                                      self.getLayersToCheck())
      else: # lista di geometrie
         selSet = QadEntitySet()
         for g in geom:
            partial = qad_utils.getSelSet(mode, self.getPointMapTool(), g, \
                                          self.getLayersToCheck())
            selSet.unite(partial)
      self.elaborateSelSet(selSet, False)

      
   #============================================================================
   # WaitForFirstPoint
   #============================================================================
   def WaitForFirstPoint(self):
      self.step = 1

      # "Finestra" "Ultimo" "Interseca"
      # "Riquadro" "Tutto" "iNTercetta"
      # "FPoligono" "IPoligono"
      # "FCerchio" "ICerchio"
      # "FOggetti" "IOggetti"
      # "FBuffer" "IBuffer"
      # "AGgiungi" "Elimina"
      # "Precedente" "Annulla"
      # "AUto" "SIngolo" "Help"
      keyWords = QadMsg.translate("Command_SSGET", "Window") + "/" + \
                 QadMsg.translate("Command_SSGET", "Last") + "/" + \
                 QadMsg.translate("Command_SSGET", "Crossing") + "/" + \
                 QadMsg.translate("Command_SSGET", "Box") + "/" + \
                 QadMsg.translate("Command_SSGET", "All") + "/" + \
                 QadMsg.translate("Command_SSGET", "Fence") + "/" + \
                 QadMsg.translate("Command_SSGET", "WPolygon") + "/" + \
                 QadMsg.translate("Command_SSGET", "CPolygon") + "/" + \
                 QadMsg.translate("Command_SSGET", "WCircle") + "/" + \
                 QadMsg.translate("Command_SSGET", "CCircle") + "/" + \
                 QadMsg.translate("Command_SSGET", "WObjects") + "/" + \
                 QadMsg.translate("Command_SSGET", "CObjects") + "/" + \
                 QadMsg.translate("Command_SSGET", "WBuffer") + "/" + \
                 QadMsg.translate("Command_SSGET", "CBuffer") + "/" + \
                 QadMsg.translate("Command_SSGET", "Add") + "/" + \
                 QadMsg.translate("Command_SSGET", "Remove") + "/" + \
                 QadMsg.translate("Command_SSGET", "Previous") + "/" + \
                 QadMsg.translate("Command_SSGET", "Undo") + "/" + \
                 QadMsg.translate("Command_SSGET", "AUto") + "/" + \
                 QadMsg.translate("Command_SSGET", "SIngle") + "/" + \
                 QadMsg.translate("Command_SSGET", "Help")
      englishKeyWords = "Window" + "/" + "Last" + "/" + "Crossing" + "/" + "Box" + "/" \
                         + "All" + "/" + "Fence" + "/" + "WPolygon" + "/" + "CPolygon" + "/" \
                         + "WCircle" + "/" + "CCircle" + "/" + "WObjects" + "/" + "CObjects" + "/" \
                         + "WBuffer" + "/" + "CBuffer" + "/" + "Add" + "/" + "Remove" + "/" \
                         + "Previous" + "/" + "Undo" + "/" + "AUto" + "/" + "SIngle" + "/" + "Help"
                 
      if self.AddOnSelection == True:
         prompt = QadMsg.translate("Command_SSGET", "Select Objects")
      else:
         prompt = QadMsg.translate("Command_SSGET", "Remove objects")
                           
      if self.help == True:         
         prompt = prompt + QadMsg.translate("Command_SSGET", " or [{0}]").format(keyWords)
         
      prompt = prompt + QadMsg.translate("Command_SSGET", ": ")
            
      # imposto il map tool
      self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.ENTITY_SELECTION)
      self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
      # imposto i layer da controllare sul maptool
      self.getPointMapTool().layersToCheck = self.getLayersToCheck()
      self.points = []
           
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      return

   def run(self, msgMapTool = False, msg = None):
      # ritorna:
      # True per selezione non terminata
      # False per selezione terminata
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # errore
            
      #=========================================================================
      # RICHIESTA PRIMO PUNTO PER SELEZIONE OGGETTI
      if self.step == 0:
         # if you can also select objects before you start a command
         if QadVariables.get(QadMsg.translate("Environment variables", "PICKFIRST")) == 1:
            if self.AddCurrentQgsSelectedFeatures() == True:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True;
         self.WaitForFirstPoint()
         return False # continua
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER SELEZIONE OGGETTI
      elif self.step == 1: # dopo aver atteso un punto o enter o una parola chiave si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.entitySet.count() > 0:
                     self.plugIn.setLastEntitySet(self.entitySet)
                  return True # fine
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False # continua
            
            shiftKey = self.getPointMapTool().shiftKey

            # se é stata selezionata un'entità
            if self.getPointMapTool().entity.isInitialized():
               value = self.getPointMapTool().entity
            else:
               value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            shiftKey = False
            value = msg

         if value is None:
            if self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
            return True # fine

         if type(value) == unicode:
            self.currSelectionMode = value
            
            if value == QadMsg.translate("Command_SSGET", "Window") or value == "Window" or \
               value == QadMsg.translate("Command_SSGET", "Crossing") or value == "Crossing":
               # "Finestra" = Seleziona tutti gli oggetti che si trovano completamente all'interno di un rettangolo definito da due punti
               # "Interseca" = Seleziona gli oggetti che intersecano o si trovano all'interno di un'area definita da due punti
               # imposto il map tool
               self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.POINT_SELECTION)
               self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_SSGET", "First corner: "))
               self.step = 2
            if value == QadMsg.translate("Command_SSGET", "Last") or value == "Last": 
               # Seleziona l'ultima entità inserita
               if self.plugIn.getLastEntity() is None:
                  self.showMsgOnAddRemove(0)
               else:
                  self.AddRemoveEntity(self.plugIn.getLastEntity(), self.AddOnSelection)
                  if self.SingleSelection == True and self.entitySet.count() > 0:
                     self.plugIn.setLastEntitySet(self.entitySet)
                     return True # fine
               
               if self.exitAfterSelection == True:
                  return True # fine
               
               self.WaitForFirstPoint()                          
            elif value == QadMsg.translate("Command_SSGET", "Box") or value == "Box":
               # Seleziona tutti gli oggetti che intersecano o si trovano all'interno di un rettangolo specificato da due punti.
               # Se i punti del rettangolo sono specificati da destra a sinistra, Riquadro equivale ad Interseca,
               # altrimenti é equivalente a Finestra
               # imposto il map tool
               self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.POINT_SELECTION)
               self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.NONE)
               # si appresta ad attendere un punto
               self.waitForPoint(QadMsg.translate("Command_SSGET", "First corner: "))
               self.step = 2           
            elif value == QadMsg.translate("Command_SSGET", "All") or value == "All":
               # Seleziona tutti gli oggetti 
               selSet = qad_utils.getSelSet("X", self.getPointMapTool(), None, \
                                            self.getLayersToCheck())
               self.elaborateSelSet(selSet, False)
               if self.SingleSelection == True and self.entitySet.count() > 0:
                  self.plugIn.setLastEntitySet(self.entitySet)
                  return True # fine 

               if self.exitAfterSelection == True:
                  return True # fine

               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "Fence") or value == "Fence":
               # Seleziona tutti gli oggetti che intersecano una polilinea
               self.PLINECommand = QadPLINECommandClass(self.plugIn)
               # se questo flag = True il comando serve all'interno di un altro comando per disegnare una linea
               # che non verrà salvata su un layer
               self.PLINECommand.virtualCmd = True   
               self.PLINECommand.run(msgMapTool, msg)
               self.step = 4
            elif value == QadMsg.translate("Command_SSGET", "WPolygon") or value == "WPolygon" or \
                 value == QadMsg.translate("Command_SSGET", "CPolygon") or value == "CPolygon":
               # "FPoligono" = Seleziona oggetti che si trovano completamente all'interno di un poligono definito da punti
               # "IPoligono" = Seleziona gli oggetti che intersecano o si trovano all'interno di un poligono definito specificando dei punti
               self.MPOLYGONCommand = QadMPOLYGONCommandClass(self.plugIn)
               # se questo flag = True il comando serve all'interno di un altro comando per disegnare una linea
               # che non verrà salvata su un layer
               self.MPOLYGONCommand.virtualCmd = True
               
               if value == QadMsg.translate("Command_SSGET", "WPolygon") or value == "WPolygon":
                  self.MPOLYGONCommand.setRubberBandColor(None, getColorForWindowSelectionArea())
               else:
                  self.MPOLYGONCommand.setRubberBandColor(None, getColorForCrossingSelectionArea())
               
               self.MPOLYGONCommand.run(msgMapTool, msg)
               self.step = 7
            elif value == QadMsg.translate("Command_SSGET", "WCircle") or value == "WCircle" or \
                 value == QadMsg.translate("Command_SSGET", "CCircle") or value == "CCircle":
               # "FCerchio" = Seleziona oggetti che si trovano completamente all'interno di un cerchio
               # "ICerchio" = Seleziona oggetti che intersecano o si trovano all'interno di un cerchio
               self.CIRCLECommand = QadCIRCLECommandClass(self.plugIn)
               # se questo flag = True il comando serve all'interno di un altro comando per disegnare un cerchio
               # che non verrà salvata su un layer
               self.CIRCLECommand.virtualCmd = True
               
               if value == QadMsg.translate("Command_SSGET", "WCircle") or value == "WCircle":
                  self.CIRCLECommand.setRubberBandColor(None, getColorForWindowSelectionArea())
               else:
                  self.CIRCLECommand.setRubberBandColor(None, getColorForCrossingSelectionArea())
                  
               self.CIRCLECommand.run(msgMapTool, msg)
               self.step = 5
            elif value == QadMsg.translate("Command_SSGET", "WObjects") or value == "WObjects" or \
                 value == QadMsg.translate("Command_SSGET", "CObjects") or value == "CObjects":
               # "FOggetti" = Seleziona oggetti che si trovano completamente all'interno di oggetti da selezionare
               # "IOggetti" = Seleziona oggetti che intersecano o si trovano all'interno di oggetti da selezionare
               self.SSGetClass = QadSSGetClass(self.plugIn)
               self.SSGetClass.run(msgMapTool, msg)
               self.step = 6
            elif value == QadMsg.translate("Command_SSGET", "WBuffer") or value == "WBuffer" or \
                 value == QadMsg.translate("Command_SSGET", "CBuffer") or value == "CBuffer":
               # ho dovuto spostare questo import perché qad_mbuffer_cmd fa l'import di qad_ssget_cmd
               from qad_mbuffer_cmd import QadMBUFFERCommandClass
               
               # "FBuffer" = Seleziona oggetti che si trovano completamente all'interno di buffer intorno ad oggetti da selezionare
               # "IBuffer" = Seleziona oggetti che intersecano o si trovano all'interno di buffer intorno ad oggetti da selezionare
               self.MBUFFERCommand = QadMBUFFERCommandClass(self.plugIn)
               # se questo flag = True il comando serve all'interno di un altro comando per disegnare un cerchio
               # che non verrà salvata su un layer
               self.MBUFFERCommand.virtualCmd = True   
               
               if value == QadMsg.translate("Command_SSGET", "WBuffer") or value == "WBuffer":
                  self.MBUFFERCommand.setRubberBandColor(None, getColorForWindowSelectionArea())
               else:
                  self.MBUFFERCommand.setRubberBandColor(None, getColorForCrossingSelectionArea())
               
               self.MBUFFERCommand.run(msgMapTool, msg)
               self.step = 8
            elif value == QadMsg.translate("Command_SSGET", "Add") or value == "Add":
               # Passa al metodo Aggiungi: gli oggetti selezionati possono essere aggiunti al gruppo di selezione 
               self.AddOnSelection = True
               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "Remove") or value == "Remove":
               # Passa al metodo Rimuovi: gli oggetti possono essere rimossi dal gruppo di selezione
               self.AddOnSelection = False
               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "Previous") or value == "Previous":
               # Seleziona il gruppo di selezione più recente
               if self.plugIn.lastEntitySet is None:
                  self.showMsgOnAddRemove(0)
               else:
                  entitySet = QadEntitySet()
                  entitySet.set(self.plugIn.lastEntitySet)
                  # controllo sul layer                  
                  if self.onlyEditableLayers == True:
                     entitySet.removeNotEditable()
                  # controllo sul tipo
                  if self.checkPointLayer == False:
                     entitySet.removeGeomType(QGis.Point)
                  if self.checkLineLayer == False:
                     entitySet.removeGeomType(QGis.Line)
                  if self.checkPolygonLayer == False:
                     entitySet.removeGeomType(QGis.Polygon)
                  # controllo sulle quotature
                  if self.checkDimLayers == False:
                     QadDimStyles.removeAllDimLayersFromEntitySet(entitySet)
                     
                  entitySet.removeNotExisting()
                  self.elaborateSelSet(entitySet, False)
                  if self.SingleSelection == True and self.entitySet.count() > 0:
                     self.plugIn.setLastEntitySet(self.entitySet)
                     return True # fine

               if self.exitAfterSelection == True:
                  return True # fine

               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "Undo") or value == "Undo":
               # Annulla la selezione dell'oggetto aggiunto più recentemente al gruppo di selezione.
               # Inverto il tipo di selezione
               prevAddOnSelection = self.AddOnSelection
               self.AddOnSelection = not self.AddOnSelection
               self.elaborateSelSet(self.lastEntitySet, False)
               # Ripristino il tipo di selezione
               self.AddOnSelection = prevAddOnSelection
               if self.SingleSelection == True and self.entitySet.count() > 0:
                  self.plugIn.setLastEntitySet(self.entitySet)
                  return True # fine

               if self.exitAfterSelection == True:
                  return True # fine
               
               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "AUto") or value == "AUto":
               # Passa alla selezione automatica: vengono selezionati gli oggetti sui quali si posiziona il puntatore.
               # Facendo clic su un'area vuota all'interno o all'esterno di un oggetto, 
               # si crea il primo angolo di un rettangolo di selezione, come per il metodo Riquadro
               self.SingleSelection = False
               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "SIngle") or value == "SIngle":
               # Passa al metodo Singolo: viene selezionato il primo oggetto o gruppo di oggetti indicato,
               # senza che vengano richieste altre selezioni.
               self.SingleSelection = True
               if self.entitySet.count() > 0:
                  self.plugIn.setLastEntitySet(self.entitySet)
                  return True # fine               
               self.WaitForFirstPoint()
            elif value == QadMsg.translate("Command_SSGET", "Help") or value == "Help":
               self.help = True
               self.WaitForFirstPoint()
         elif type(value) == QgsPoint: # se é stato inserito il punto iniziale del rettangolo
            self.currSelectionMode = QadMsg.translate("Command_SSGET", "Box")
            self.points.append(value)           
            self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.ENTITYSET_SELECTION)
            self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_RECTANGLE)
            self.getPointMapTool().setStartPoint(value)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_SSGET", "Specify opposite corner: "))
            self.step = 3
         else: # se é stata selezionata un'entità
            self.elaborateEntity(value, shiftKey)

            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine               

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
          
         return False # continua

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL PRIMO PUNTO DEL RETTANGOLO DA OPZIONE 
      # FINESTRA, INTERSECA, RIQUADRO (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  self.showMsg(QadMsg.translate("Command_SSGET", "Window not correct."))
                  self.WaitForFirstPoint()
                  return False
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg
                        
         if type(value) == QgsPoint:
            self.points.append(value)           
            self.getPointMapTool().setSelectionMode(QadGetPointSelectionModeEnum.ENTITYSET_SELECTION)
            self.getPointMapTool().setDrawMode(QadGetPointDrawModeEnum.ELASTIC_RECTANGLE)
            
            # cambio il colore impostato da setDrawMode
            if self.currSelectionMode == QadMsg.translate("Command_SSGET", "Window") or value == "Window":
               self.getPointMapTool().rectangleCrossingSelectionColor = self.getPointMapTool().rectangleWindowSelectionColor
            elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "Crossing") or value == "Crossing":
                self.getPointMapTool().rectangleWindowSelectionColor = self.getPointMapTool().rectangleCrossingSelectionColor
            
            self.rectangleCrossingSelectionColor = getColorForCrossingSelectionArea()
            self.rectangleWindowSelectionColor = getColorForWindowSelectionArea()
            
            self.getPointMapTool().setStartPoint(value)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_SSGET", "Specify opposite corner: "))
            self.step = 3
         else:
            self.showMsg(QadMsg.translate("Command_SSGET", "Window not correct."))
            self.WaitForFirstPoint()

         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL SECONDO PUNTO DEL RETTANGOLO (da step = 1)
      elif self.step == 3: # dopo aver atteso un punto si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  self.showMsg(QadMsg.translate("Command_SSGET", "Window not correct."))
                  # si appresta ad attendere un punto
                  self.waitForPoint(QadMsg.translate("Command_SSGET", "Specify opposite corner: "))
                  return False
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            shiftKey = self.getPointMapTool().shiftKey
            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            shiftKey = False
            value = msg
                        
         if type(value) == QgsPoint:
            self.getPointMapTool().clear()
            self.points.append(value)
            
            if self.currSelectionMode == QadMsg.translate("Command_SSGET", "Box") or \
               self.currSelectionMode == "Box":
               if self.points[0].x() < value.x():
                  mode = "W"
               else:
                  mode = "C"
            elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "Window") or \
               self.currSelectionMode == "Window": 
               mode = "W"
            else: # "Interseca"
               mode = "C"
               
            selSet = qad_utils.getSelSet(mode, self.getPointMapTool(), self.points, \
                                         self.getLayersToCheck())
            self.elaborateSelSet(selSet, shiftKey)
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         else:
            self.showMsg(QadMsg.translate("Command_SSGET", "Window not correct."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_SSGET", "Specify opposite corner: "))

         return False # continua


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO PER MODALITA' INTERCETTA (da step = 1 o 4)
      elif self.step == 4: # dopo aver atteso un punto si riavvia il comando
         if self.PLINECommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")
            self.AddRemoveSelSetByFence(self.PLINECommand.vertices)
            del self.PLINECommand
            self.PLINECommand = None
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PER MODALITA' FCERCHIO e ICERCHIO (da step = 1 o 5)
      elif self.step == 5: # dopo aver atteso un punto si riavvia il comando
         if self.CIRCLECommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")
            if (self.CIRCLECommand.centerPt is not None) and \
               (self.CIRCLECommand.radius is not None):
               circle = QadCircle()
               circle.set(self.CIRCLECommand.centerPt, self.CIRCLECommand.radius)
               points = circle.asPolyline()
               if self.currSelectionMode == QadMsg.translate("Command_SSGET", "WCircle") or \
                  self.currSelectionMode == "WCircle":
                  self.AddRemoveSelSetByPolygon("WP", points)
               elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "CCircle") or \
                  self.currSelectionMode == "CCircle":
                  self.AddRemoveSelSetByPolygon("CP", points)               
            
            del self.CIRCLECommand
            self.CIRCLECommand = None
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI SELEZIONE DI OGGETTI PER MODALITA' FOGGETTI e IOGGETTI (da step = 1 o 6)
      elif self.step == 6: # dopo aver atteso un punto si riavvia il comando
         if self.SSGetClass.run(msgMapTool, msg) == True:
            self.showMsg("\n")
            destCRS = self.SSGetClass.getPointMapTool().canvas.mapSettings().destinationCrs()
            geoms = self.SSGetClass.entitySet.getGeometryCollection(destCRS) # trasformo la geometria
            
            if self.currSelectionMode == QadMsg.translate("Command_SSGET", "WObjects") or \
               self.currSelectionMode == "WObjects":
               self.AddRemoveSelSetByGeometry("WO", geoms)
            elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "CObjects") or \
               self.currSelectionMode == "CObjects":
               self.AddRemoveSelSetByGeometry("CO", geoms)
                                 
            del self.SSGetClass
            self.SSGetClass = None
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PER MODALITA' FPOLIGONO e IPOLIGONO (da step = 1 o 7)
      elif self.step == 7: # dopo aver atteso un punto si riavvia il comando
         if self.MPOLYGONCommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")              
            if self.currSelectionMode == QadMsg.translate("Command_SSGET", "WPolygon") or \
               self.currSelectionMode == "WPolygon":
               self.AddRemoveSelSetByPolygon("WP", self.MPOLYGONCommand.vertices)
            elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "CPolygon") or \
               self.currSelectionMode == "CPolygon":
               self.AddRemoveSelSetByPolygon("CP", self.MPOLYGONCommand.vertices)               
            
            del self.MPOLYGONCommand
            self.MPOLYGONCommand = None
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI SELEZIONE DI OGGETTI PER MODALITA' FBUFFER e IBUFFER (da step = 1 o 8)
      elif self.step == 8: # dopo aver atteso un punto si riavvia il comando
         if self.MBUFFERCommand.run(msgMapTool, msg) == True:
            self.showMsg("\n")

            bufferGeoms = []
            for layerEntitySet in self.MBUFFERCommand.entitySet.layerEntitySetList:
               geoms = layerEntitySet.getGeometryCollection()
               width = qad_utils.distMapToLayerCoordinates(self.MBUFFERCommand.width, \
                                                           self.MBUFFERCommand.getPointMapTool().canvas,\
                                                           layerEntitySet.layer)
               for geom in geoms:
                  bufferGeoms.append(geom.buffer(width, self.MBUFFERCommand.segments))
                        
            if self.currSelectionMode == QadMsg.translate("Command_SSGET", "WBuffer") or \
               self.currSelectionMode == "WBuffer":
               self.AddRemoveSelSetByGeometry("WO", bufferGeoms)
            elif self.currSelectionMode == QadMsg.translate("Command_SSGET", "CBuffer") or \
               self.currSelectionMode == "CBuffer":
               self.AddRemoveSelSetByGeometry("CO", bufferGeoms)
                                 
            del self.MBUFFERCommand
            self.MBUFFERCommand = None
         
            if self.SingleSelection == True and self.entitySet.count() > 0:
               self.plugIn.setLastEntitySet(self.entitySet)
               return True # fine

            if self.exitAfterSelection == True:
               return True # fine

            self.WaitForFirstPoint()
         return False class QadGRIPSTRETCHCommandClass(QadCommandClass):


   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPSTRETCHCommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.selectedEntityGripPoints = [] # lista in cui ogni elemento è una entità + una lista di punti da stirare
      self.basePt = QgsPoint()
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0

   
   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_gripStretch_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # addToSelectedEntityGripPoints
   #============================================================================
   def addToSelectedEntityGripPoints(self, entityGripPoints):
      # entità con lista dei grip point
      i = 0
      gripPoints = entityGripPoints.gripPoints
      gripPointsLen = len(gripPoints)
      ptList = []
      while i < gripPointsLen:
         gripPoint = gripPoints[i]
         # grip point selezionato
         if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED:
            if gripPoint.gripType == qad_grip.QadGripPointTypeEnum.CENTER:
               ptList.append(gripPoint.getPoint())
            elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.LINE_MID_POINT:
               # aggiungo il vertice precedente e successivo di quello intermedio
               if i > 0:
                  ptList.append(gripPoints[i - 1].getPoint())
               if i < gripPointsLen - 1:
                  ptList.append(gripPoints[i + 1].getPoint())
            elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.QUA_POINT:
               ptList.append(gripPoint.getPoint())
            elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.VERTEX or \
                 gripPoint.gripType == qad_grip.QadGripPointTypeEnum.END_VERTEX:
               ptList.append(gripPoint.getPoint())
            elif gripPoint.gripType == qad_grip.QadGripPointTypeEnum.ARC_MID_POINT:
               ptList.append(gripPoint.getPoint())
         i = i + 1
      
      if len(ptList) > 0:
         self.selectedEntityGripPoints.append([entityGripPoints.entity, ptList])

   
   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      # ritorna una lista in cui ogni elemento è una entità + una lista di punti da stirare
      del self.selectedEntityGripPoints[:] # svuoto la lista

      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         self.addToSelectedEntityGripPoints(entityGripPoints)
      self.getPointMapTool().selectedEntityGripPoints = self.selectedEntityGripPoints


   #============================================================================
   # getSelectedEntityGripPointNdx
   #============================================================================
   def getSelectedEntityGripPointNdx(self, entity):
      # lista delle entityGripPoint con dei grip point selezionati
      # cerca la posizione di un'entità nella lista in cui ogni elemento è una entità + una lista di punti da stirare
      i = 0
      tot = len(self.selectedEntityGripPoints)
      while i < tot:
         selectedEntityGripPoint = self.selectedEntityGripPoints[i]
         if selectedEntityGripPoint[0] == entity:
            return i
         i = i + 1
      return -1


   #============================================================================
   # stretch
   #============================================================================
   def stretch(self, entity, ptList, offSetX, offSetY, tolerance2ApproxCurve):
      # entity = entità da stirare
      # ptList = lista dei punti da stirare
      # offSetX, offSetY = spostamento da fare
      # tolerance2ApproxCurve = tolleranza per ricreare le curve
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.whatIs() == "ENTITY":
         stretchedGeom = entity.getGeometry()
         # controllo inserito perchè con le quote, questa viene cancellata e ricreata quindi alcuni oggetti potrebbero non esistere più
         if stretchedGeom is None: # se non c'è lo salto senza errore
            return True

         # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
         coordTransform = QgsCoordinateTransform(entity.layer.crs(), self.plugIn.canvas.mapSettings().destinationCrs())
         stretchedGeom.transform(coordTransform)           
         # stiro la feature
         stretchedGeom = qad_stretch_fun.gripStretchQgsGeometry(stretchedGeom, self.basePt, ptList, \
                                                                offSetX, offSetY, \
                                                                tolerance2ApproxCurve)
         
         if stretchedGeom is not None:
            # trasformo la geometria nel crs del layer
            coordTransform = QgsCoordinateTransform(self.plugIn.canvas.mapSettings().destinationCrs(), entity.layer.crs())
            stretchedGeom.transform(coordTransform)
                       
            f = entity.getFeature()
            f.setGeometry(stretchedGeom)
            if self.copyEntities == False:
               # plugIn, layer, feature, refresh, check_validity
               if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
                  return False
            else:
               # plugIn, layer, features, coordTransform, refresh, check_validity
               if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f, None, False, False) == False:
                  return False
               
      elif entity.whatIs() == "DIMENTITY":
         # stiro la quota
         if self.copyEntities == False:
            if entity.deleteToLayers(self.plugIn) == False:
               return False                      
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.stretch(ptList, offSetX, offSetY)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False
         # non so per quale motivo a volte non si aggiorna la mappa quindi forzo l'aggiornamento
         self.plugIn.canvas.refresh()
            
      return True


   #============================================================================
   # stretchFeatures
   #============================================================================
   def stretchFeatures(self, newPt):
      # mi ricavo un unico QadEntitySet con le entità selezionate
      entitySet = QadEntitySet()
      for selectedEntity in self.selectedEntityGripPoints:
         entitySet.addEntity(selectedEntity[0])
      self.plugIn.beginEditCommand("Feature stretched", entitySet.getLayerList())
      
      dimElaboratedList = [] # lista delle quotature già elaborate
      
      for selectedEntity in self.selectedEntityGripPoints:
         entity = selectedEntity[0]
         ptList = selectedEntity[1]
         layer = entity.layer
         
         tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
         offSetX = newPt.x() - self.basePt.x()
         offSetY = newPt.y() - self.basePt.y()

         # verifico se l'entità appartiene ad uno stile di quotatura
         dimEntity = QadDimStyles.getDimEntity(entity)  
         if dimEntity is None:
            if self.stretch(entity, ptList, offSetX, offSetY, tolerance2ApproxCurve) == False:
               self.plugIn.destroyEditCommand()
               return
         else:
            found = False
            for dimElaborated in dimElaboratedList:
               if dimElaborated == dimEntity:
                  found = True
            
            if found == False: # quota non ancora elaborata
               dimEntitySet = dimEntity.getEntitySet()
               # creo un'unica lista contenente i grip points di tutti i componenti della quota
               dimPtlist = []
               for layerEntitySet in dimEntitySet.layerEntitySetList:
                  for featureId in layerEntitySet.featureIds:
                     componentDim = QadEntity()
                     componentDim.set(layerEntitySet.layer, featureId)
                     i = self.getSelectedEntityGripPointNdx(componentDim)
                     if i >= 0:
                        dimPtlist.extend(self.selectedEntityGripPoints[i][1])

               dimElaboratedList.append(dimEntity)
               if self.stretch(dimEntity, dimPtlist, offSetX, offSetY, tolerance2ApproxCurve) == False:
                  self.plugIn.destroyEditCommand()
                  return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
                           
                           
   #============================================================================
   # waitForStretchPoint
   #============================================================================
   def waitForStretchPoint(self):
      self.step = 1
      self.plugIn.setLastPoint(self.basePt)
      # imposto il map tool
      self.getPointMapTool().basePt = self.basePt
      self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)
      
      keyWords = QadMsg.translate("Command_GRIP", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIP", "eXit")

      prompt = QadMsg.translate("Command_GRIPSTRETCH", "Specify stretch point or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)      


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_stretch_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)                                

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIPSTRETCH", "Specify base point: "))


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if len(self.selectedEntityGripPoints) == 0: # non ci sono oggetti da stirare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPSTRETCH", "\n** STRETCH **\n"))
         # si appresta ad attendere un punto di stiramento
         self.waitForStretchPoint()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI STIRAMENTO
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point

            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIP", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIP", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere un punto di stiramento
               self.waitForStretchPoint()
            elif value == QadMsg.translate("Command_GRIP", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere un punto di stiramento
               self.waitForStretchPoint()
            elif value == QadMsg.translate("Command_GRIP", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if ctrlKey:
               self.copyEntities = True
               
            self.stretchFeatures(value)

            if self.copyEntities == False:
               return True
            # si appresta ad attendere un punto di stiramento
            self.waitForStretchPoint()
          
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando
                                          
         return False 

              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default "spostamento"
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().basePt = self.basePt
            
         # si appresta ad attendere un punto di stiramento
         self.waitForStretchPoint()

         return False class QadGRIPMOVECommandClass(QadCommandClass):


   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPMOVECommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0

   
   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_move_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      self.entitySet.clear()

      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         self.entitySet.addEntity(entityGripPoints.entity)
      self.getPointMapTool().entitySet.set(self.entitySet)


   #============================================================================
   # move
   #============================================================================
   def move(self, entity, offSetX, offSetY):
      # entity = entità da spostare
      # offSetX, offSetY = spostamento da fare
      # tolerance2ApproxCurve = tolleranza per ricreare le curve
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.whatIs() == "ENTITY":
         # sposto l'entità
         movedGeom = qad_utils.moveQgsGeometry(entity.getGeometry(), offSetX, offSetY)
         
         if movedGeom is not None:
            f = entity.getFeature()
            f.setGeometry(movedGeom)
            if self.copyEntities == False:
               # plugIn, layer, feature, refresh, check_validity
               if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
                  return False
            else:
               # plugIn, layer, features, coordTransform, refresh, check_validity
               if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f, None, False, False) == False:
                  return False
               
      elif entity.whatIs() == "DIMENTITY":
         # stiro la quota
         if self.copyEntities == False:
            if entity.deleteToLayers(self.plugIn) == False:
               return False                      
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.move(offSetX, offSetY)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             
            
      return True


   #============================================================================
   # moveFeatures
   #============================================================================
   def moveFeatures(self, newPt):
      entity = QadEntity()
      self.plugIn.beginEditCommand("Feature moved", self.entitySet.getLayerList())
      
      dimElaboratedList = [] # lista delle quotature già elaborate

      for layerEntitySet in self.entitySet.layerEntitySetList:                        
         layer = layerEntitySet.layer
         
         transformedBasePt = self.mapToLayerCoordinates(layerEntitySet.layer, self.basePt)
         transformedNewPt = self.mapToLayerCoordinates(layerEntitySet.layer, newPt)
         offSetX = transformedNewPt.x() - transformedBasePt.x()
         offSetY = transformedNewPt.y() - transformedBasePt.y()
         
         for featureId in layerEntitySet.featureIds:
            entity.set(layerEntitySet.layer, featureId)

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)  
            if dimEntity is None:                        
               if self.move(entity, offSetX, offSetY) == False:
                  self.plugIn.destroyEditCommand()
                  return
            else:
               found = False
               for dimElaborated in dimElaboratedList:
                  if dimElaborated == dimEntity:
                     found = True
            
               if found == False: # quota non ancora elaborata
                  dimElaboratedList.append(dimEntity)
                  if self.move(dimEntity, offSetX, offSetY) == False:
                     self.plugIn.destroyEditCommand()
                     return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
                           
                           
   #============================================================================
   # waitForMovePoint
   #============================================================================
   def waitForMovePoint(self):
      self.step = 1
      self.plugIn.setLastPoint(self.basePt)
      # imposto il map tool
      self.getPointMapTool().basePt = self.basePt
      self.getPointMapTool().setMode(Qad_move_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_MOVE_PT)
      
      keyWords = QadMsg.translate("Command_GRIPMOVE", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIPMOVE", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIPMOVE", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIPMOVE", "eXit")

      prompt = QadMsg.translate("Command_GRIPMOVE", "Specify move point or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)      


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_move_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIPMOVE", "Specify base point: "))


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entitySet.isEmpty(): # non ci sono oggetti da spostare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPMOVE", "\n** MOVE **\n"))
         # si appresta ad attendere un punto di spostamento
         self.waitForMovePoint()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI SPOSTAMENTO
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point

            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIPMOVE", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIPMOVE", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere un punto di spostamento
               self.waitForMovePoint()
            elif value == QadMsg.translate("Command_GRIPMOVE", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere un punto di spostamento
               self.waitForMovePoint()
            elif value == QadMsg.translate("Command_GRIPMOVE", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if ctrlKey:
               self.copyEntities = True

            self.moveFeatures(value)

            if self.copyEntities == False:
               return True
            # si appresta ad attendere un punto di stiramento
            self.waitForMovePoint()
          
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando
                                          
         return False 

              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default "spostamento"
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().basePt = self.basePt
            
         # si appresta ad attendere un punto di spostamento
         self.waitForMovePoint()

         return False class QadGRIPROTATECommandClass(QadCommandClass):


   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPROTATECommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0
      self.Pt1ReferenceAng = None
      self.ReferenceAng = 0

   
   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_rotate_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      self.entitySet.clear()

      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         self.entitySet.addEntity(entityGripPoints.entity)
      self.getPointMapTool().entitySet.set(self.entitySet)


   #============================================================================
   # rotate
   #============================================================================
   def rotate(self, entity, basePt, angle, rotFldName):
      # entity = entità da ruotare
      # basePt = punto base
      # angle = angolo di rotazione in gradi
      # rotFldName = campo della tabella che memorizza la rotazione
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.whatIs() == "ENTITY":
         f = entity.getFeature()
         # ruoto l'entità
         f.setGeometry(qad_utils.rotateQgsGeometry(entity.getGeometry(), basePt, angle))
         if len(rotFldName) > 0:
            rotValue = f.attribute(rotFldName)
            # a volte vale None e a volte null (vai a capire...)
            rotValue = 0 if rotValue is None or isinstance(rotValue, QPyNullVariant) else qad_utils.toRadians(rotValue) # la rotazione é in gradi nel campo della feature
            rotValue = rotValue + angle
            f.setAttribute(rotFldName, qad_utils.toDegrees(qad_utils.normalizeAngle(rotValue)))               
         
         if self.copyEntities == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
               return False
         else:
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f, None, False, False) == False:
               return False
               
      elif entity.whatIs() == "DIMENTITY":
         # stiro la quota
         if self.copyEntities == False:
            if entity.deleteToLayers(self.plugIn) == False:
               return False           
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.rotate(basePt, angle)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             

      return True


   #============================================================================
   # rotateFeatures
   #============================================================================
   def rotateFeatures(self, angle):
      entity = QadEntity()
      self.plugIn.beginEditCommand("Feature rotated", self.entitySet.getLayerList())
      
      dimElaboratedList = [] # lista delle quotature già elaborate

      for layerEntitySet in self.entitySet.layerEntitySetList:                        
         layer = layerEntitySet.layer        
         transformedBasePt = self.mapToLayerCoordinates(layer, self.basePt)

         rotFldName = ""
         if qad_layer.isTextLayer(layer):
            # se la rotazione dipende da un solo campo
            rotFldNames = qad_label.get_labelRotationFieldNames(layer)
            if len(rotFldNames) == 1 and len(rotFldNames[0]) > 0:
               rotFldName = rotFldNames[0]         
         elif qad_layer.isSymbolLayer(layer):
            # se la rotazione dipende da un campo
            rotFldName = qad_layer.get_symbolRotationFieldName(layer)
         
         for featureId in layerEntitySet.featureIds:
            entity.set(layer, featureId)

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)  
            if dimEntity is None:
               if self.rotate(entity, transformedBasePt, angle, rotFldName) == False:
                  self.plugIn.destroyEditCommand()
                  return
            else:
               found = False
               for dimElaborated in dimElaboratedList:
                  if dimElaborated == dimEntity:
                     found = True
            
               if found == False: # quota non ancora elaborata
                  dimElaboratedList.append(dimEntity)
                  # basePt va espresso in map cooridnate
                  if self.rotate(dimEntity, self.basePt, angle, rotFldName) == False:
                     self.plugIn.destroyEditCommand()
                     return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
   
                           
   #============================================================================
   # waitForRotatePoint
   #============================================================================
   def waitForRotatePoint(self):
      self.step = 1
      self.plugIn.setLastPoint(self.basePt)
      # imposto il map tool
      self.getPointMapTool().basePt = self.basePt
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_NEW_ROTATION_PT)
      
      keyWords = QadMsg.translate("Command_GRIPROTATE", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIPROTATE", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIPROTATE", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIPROTATE", "Reference") + "/" + \
                 QadMsg.translate("Command_GRIPROTATE", "eXit")

      prompt = QadMsg.translate("Command_GRIPROTATE", "Specify rotation angle or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "Reference" + "/" + "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)      


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIPROTATE", "Specify base point: "))


   def waitForReferenceRot(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.ASK_FOR_FIRST_PT_REFERENCE_ANG)
      
      msg = QadMsg.translate("Command_GRIPROTATE", "Specify reference angle <{0}>: ")
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(msg.format(str(qad_utils.toDegrees(self.plugIn.lastReferenceRot))), \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastReferenceRot, \
                   "")               
      self.step = 3


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entitySet.isEmpty(): # non ci sono oggetti da ruotare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPROTATE", "\n** ROTATE **\n"))
         # si appresta ad attendere un punto di rotazione
         self.waitForRotatePoint()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DI UN PUNTO DI ROTAZIONE
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point

            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIPROTATE", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIPROTATE", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere un punto di rotazione
               self.waitForRotatePoint()
            elif value == QadMsg.translate("Command_GRIPROTATE", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere un punto di rotazione
               self.waitForRotatePoint()
            elif value == QadMsg.translate("Command_GRIPROTATE", "Reference") or value == "Reference":
               # si appresta ad attendere l'angolo di riferimento                      
               self.waitForReferenceRot()
            elif value == QadMsg.translate("Command_GRIPROTATE", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint or type(value) == float: # se é stato inserito l'angolo di rotazione
            if type(value) == QgsPoint: # se é stato inserito l'angolo di rotazione con un punto
               angle = qad_utils.getAngleBy2Pts(self.basePt, value)
            else:
               angle = qad_utils.toRadians(value)
            angle = angle - self.ReferenceAng
            self.plugIn.setLastRot(angle)

            if ctrlKey:
               self.copyEntities = True
            
            self.rotateFeatures(angle)

            if self.copyEntities == False:
               return True

            # si appresta ad attendere un punto di rotazione
            self.waitForRotatePoint()
          
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando
                                          
         return False 

              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default "spostamento"
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().basePt = self.basePt
            
         # si appresta ad attendere un punto di rotazione
         self.waitForRotatePoint()

         return False


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER ANGOLO ROTAZIONE DI RIFERIMENTO (da step = 1)
      elif self.step == 3: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == float: # se é stato inserito l'angolo di rotazione
            self.ReferenceAng = qad_utils.toRadians(value)
            self.getPointMapTool().ReferenceAng = self.ReferenceAng 
            # si appresta ad attendere un punto di rotazione
            self.waitForRotatePoint()

         elif type(value) == QgsPoint: # se é stato inserito l'angolo di rotazione con un punto                                 
            self.Pt1ReferenceAng = QgsPoint(value)
            self.getPointMapTool().Pt1ReferenceAng = self.Pt1ReferenceAng 
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_rotate_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT_REFERENCE_ANG)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_GRIPROTATE", "Specify second point: "))
            self.step = 4
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER NUOVO ANGOLO ROTAZIONE (da step = 3)
      elif self.step == 4: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint or type(value) == float: # se é stato inserito l'angolo di rotazione
            if type(value) == QgsPoint: # se é stato inserito l'angolo di rotazione con un punto                        
               self.ReferenceAng = qad_utils.getAngleBy2Pts(self.Pt1ReferenceAng, value)
            else:
               self.ReferenceAng = qad_utils.toRadians(value)
            self.getPointMapTool().ReferenceAng = self.ReferenceAng 
            
         # si appresta ad attendere un punto di rotazione
         self.waitForRotatePoint()
         
         return False class QadGRIPSCALECommandClass(QadCommandClass):


   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPSCALECommandClass(self.plugIn)


   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0
      self.Pt1ReferenceLen = None
      self.ReferenceLen = 1
      self.Pt1NewLen = None
      self.__referenceLenMode = False

   def __del__(self):
      QadCommandClass.__del__(self)
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_scale_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      self.entitySet.clear()

      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         self.entitySet.addEntity(entityGripPoints.entity)
      self.getPointMapTool().entitySet.set(self.entitySet)


   #============================================================================
   # scale
   #============================================================================
   def scale(self, entity, basePt, scale, sizeFldName):
      # entity = entità da scalare
      # basePt = punto base
      # scale = fattore di scala
      # sizeFldName = campo della tabella che memorizza la scala
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.whatIs() == "ENTITY":
         f = entity.getFeature()
         # ruoto l'entità
         f.setGeometry(qad_utils.scaleQgsGeometry(entity.getGeometry(), basePt, scale))
         if len(sizeFldName) > 0:
            sizeValue = f.attribute(sizeFldName)
            # a volte vale None e a volte null (vai a capire...)
            if sizeValue is None or isinstance(sizeValue, QPyNullVariant):
               sizeValue = 1
            sizeValue = sizeValue * scale
            f.setAttribute(sizeFldName, sizeValue)                           
         
         if self.copyEntities == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
               return False
         else:
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f, None, False, False) == False:
               return False
               
      elif entity.whatIs() == "DIMENTITY":
         # stiro la quota
         if self.copyEntities == False:
            if entity.deleteToLayers(self.plugIn) == False:
               return False           
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.scale(basePt, scale)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False


   def scaleFeatures(self, scale):
      entity = QadEntity()
      self.plugIn.beginEditCommand("Feature scaled", self.entitySet.getLayerList())
      
      dimElaboratedList = [] # lista delle quotature già elaborate

      for layerEntitySet in self.entitySet.layerEntitySetList:                        
         layer = layerEntitySet.layer        
                              
         transformedBasePt = self.mapToLayerCoordinates(layer, self.basePt)
         
         sizeFldName = ""
         if qad_layer.isTextLayer(layer):
            # se l'altezza testo dipende da un solo campo 
            sizeFldNames = qad_label.get_labelSizeFieldNames(layer)
            if len(sizeFldNames) == 1 and len(sizeFldNames[0]) > 0:
                sizeFldName = sizeFldNames[0]
         elif qad_layer.isSymbolLayer(layer):
            # se la scala dipende da un campo 
            sizeFldName = qad_layer.get_symbolScaleFieldName(layer)

         for featureId in layerEntitySet.featureIds:
            entity.set(layer, featureId)

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)  
            if dimEntity is None:
               if self.scale(entity, transformedBasePt, scale, sizeFldName) == False:
                  self.plugIn.destroyEditCommand()
                  return
            else:
               found = False
               for dimElaborated in dimElaboratedList:
                  if dimElaborated == dimEntity:
                     found = True
            
               if found == False: # quota non ancora elaborata
                  dimElaboratedList.append(dimEntity)
                  if self.scale(dimEntity, transformedBasePt, scale, sizeFldName) == False:
                     self.plugIn.destroyEditCommand()
                     return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   def waitForScale(self):

      self.getPointMapTool().basePt = self.basePt
      keyWords = QadMsg.translate("Command_GRIPSCALE", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIPSCALE", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIPSCALE", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIPSCALE", "Reference") + "/" + \
                 QadMsg.translate("Command_GRIPSCALE", "eXit")
                 
      default = self.plugIn.lastScale
      if self.__referenceLenMode:
         # imposto il map tool
         self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_NEW_LEN_PT)
         if self.plugIn.lastNewReferenceLen > 0:
            default = self.plugIn.lastNewReferenceLen
         prompt = QadMsg.translate("Command_GRIPSCALE", "Specify new length or [{0}]: ").format(keyWords)
      else:
         # imposto il map tool
         self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_SCALE_PT)
         prompt = QadMsg.translate("Command_GRIPSCALE", "Specify scale factor or [{0}]: ").format(keyWords)                        

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "Reference" + "/" + "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)      
      self.step = 1


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_BASE_PT)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIPSCALE", "Specify base point: "))


   def waitForReferenceLen(self):
      self.__referenceLenMode = True
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.ASK_FOR_FIRST_PT_REFERENCE_LEN)
      
      msg = QadMsg.translate("Command_GRIPSCALE", "Specify reference length <{0}>: ")
      # si appresta ad attendere un punto o enter     
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(msg.format(str(self.plugIn.lastReferenceLen)), \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT, \
                   self.plugIn.lastReferenceLen, \
                   "", QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)               
      self.step = 3
   

   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
            
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entitySet.isEmpty(): # non ci sono oggetti da ruotare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPSCALE", "\n** SCALE **\n"))
         # si appresta ad attendere la scala
         self.waitForScale()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL FATTORE DI SCALA
      elif self.step == 1:
         ctrlKey = False         
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False
            else:
               value = self.getPointMapTool().point

            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIPSCALE", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIPSCALE", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere la scala
               self.waitForScale()
            elif value == QadMsg.translate("Command_GRIPSCALE", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere la scala
               self.waitForScale()
            elif value == QadMsg.translate("Command_GRIPSCALE", "Reference") or value == "Reference":
               # si appresta ad attendere la lunghezza di riferimento                      
               self.waitForReferenceLen()
            elif value == QadMsg.translate("Command_GRIPSCALE", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint or type(value) == float: # se é stato inserita la scala
            if type(value) == QgsPoint: # se é stato inserita la scala con un punto
               if value == self.basePt:
                  self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
                  # si appresta ad attendere un punto
                  self.waitForScale()
                  return False
                                      
               scale = qad_utils.getDistance(self.basePt, value)
            else:
               scale = value
               
            if self.__referenceLenMode == True: # scale rappresenta la nuova distanza di riferimento               
               scale = scale / self.ReferenceLen
               
            self.plugIn.setLastScale(scale)
            
            if ctrlKey:
               self.copyEntities = True
            
            self.scaleFeatures(scale)

            if self.copyEntities == False:
               return True

            # si appresta ad attendere la scala
            self.waitForScale()
          
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando
                                          
         return False 


      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         self.basePt = QgsPoint(value)

         self.getPointMapTool().basePt = self.basePt
         # si appresta ad attendere la scala                      
         self.waitForScale()
         
         return False 
         
               
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PRIMO PUNTO PER LUNGHEZZA DI RIFERIMENTO (da step = 1)
      elif self.step == 3: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == float: # se é stato inserita la lunghezza
            self.ReferenceLen = value
            self.getPointMapTool().ReferenceLen = self.ReferenceLen 
            # si appresta ad attendere la nuova lunghezza                    
            self.waitForScale()

         elif type(value) == QgsPoint: # se é stato inserito la scala con un punto                                 
            self.Pt1ReferenceLen = QgsPoint(value)
            self.getPointMapTool().Pt1ReferenceLen = self.Pt1ReferenceLen 
            # imposto il map tool
            self.getPointMapTool().setMode(Qad_scale_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT_REFERENCE_LEN)
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_GRIPSCALE", "Specify second point: "))
            self.step = 4
            
         return False

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER LUNGHEZZA DI RIFERIMENTO (da step = 4)
      elif self.step == 4: # dopo aver atteso un punto o un numero reale si riavvia il comando
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if self.Pt1ReferenceLen == value:
            self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
            # si appresta ad attendere un punto
            self.waitForPoint(QadMsg.translate("Command_GRIPSCALE", "Specify second point: "))
            return False
            
         length = qad_utils.getDistance(self.Pt1ReferenceLen, value)
         self.ReferenceLen = length
         self.getPointMapTool().ReferenceLen = self.ReferenceLen
         # si appresta ad attendere la nuova lunghezza
         self.waitForScale()
            
         return False class QadGRIPMIRRORCommandClass(QadCommandClass):
   
   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadMIRRORCommandClass(self.plugIn)
   

   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entitySet = QadEntitySet()
      self.basePt = QgsPoint()
      self.secondMirrorPt = QgsPoint()
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0

   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_mirror_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      self.entitySet.clear()

      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         self.entitySet.addEntity(entityGripPoints.entity)
      self.getPointMapTool().entitySet.set(self.entitySet)


   #============================================================================
   # mirror
   #============================================================================
   def mirror(self, entity, pt1, pt2, rotFldName):
      # entity = entità da specchiare
      # pt1 e pt2 = linea di simmetria
      # rotFldName = campo della tabella che memorizza la rotazione
      # verifico se l'entità appartiene ad uno stile di quotatura
      if entity.whatIs() == "ENTITY":
         f = entity.getFeature()
         # specchio l'entità
         f.setGeometry(qad_utils.mirrorQgsGeometry(entity.getGeometry(), pt1, pt2))
         if len(rotFldName) > 0:
            rotValue = f.attribute(rotFldName)
            # a volte vale None e a volte null (vai a capire...)
            rotValue = 0 if rotValue is None or isinstance(rotValue, QPyNullVariant) else qad_utils.toRadians(rotValue) # la rotazione é in gradi nel campo della feature
            ptDummy = qad_utils.getPolarPointByPtAngle(pt1, rotValue, 1)
            mirrorAngle = qad_utils.getAngleBy2Pts(pt1, pt2)
            ptDummy = qad_utils.mirrorPoint(ptDummy, pt1, mirrorAngle)
            rotValue = qad_utils.getAngleBy2Pts(pt1, ptDummy)
            f.setAttribute(rotFldName, qad_utils.toDegrees(qad_utils.normalizeAngle(rotValue)))               
                  
         if self.copyEntities == False:
            # plugIn, layer, feature, refresh, check_validity
            if qad_layer.updateFeatureToLayer(self.plugIn, entity.layer, f, False, False) == False:
               return False
         else:             
            # plugIn, layer, features, coordTransform, refresh, check_validity
            if qad_layer.addFeatureToLayer(self.plugIn, entity.layer, f, None, False, False) == False:
               return False
      elif entity.whatIs() == "DIMENTITY":
         mirrorAngle = qad_utils.getAngleBy2Pts(pt1, pt2)
         # specchio la quota
         if self.copyEntities == False:
            if entity.deleteToLayers(self.plugIn) == False:
               return False
            
         newDimEntity = QadDimEntity(entity) # la copio
         newDimEntity.mirror(pt1, mirrorAngle)
         if newDimEntity.addToLayers(self.plugIn) == False:
            return False             

      return True


   #============================================================================
   # mirrorGeoms
   #============================================================================
   def mirrorGeoms(self):
      entity = QadEntity()
      self.plugIn.beginEditCommand("Feature mirrored", self.entitySet.getLayerList())

      dimElaboratedList = [] # lista delle quotature già elaborate

      for layerEntitySet in self.entitySet.layerEntitySetList:
         layer = layerEntitySet.layer        

         transformedBasePt = self.mapToLayerCoordinates(layer, self.basePt)
         transformedNewPt = self.mapToLayerCoordinates(layer, self.secondMirrorPt)
         
         rotFldName = ""
         if qad_layer.isTextLayer(layer):
            # se la rotazione dipende da un solo campo
            rotFldNames = qad_label.get_labelRotationFieldNames(layer)
            if len(rotFldNames) == 1 and len(rotFldNames[0]) > 0:
               rotFldName = rotFldNames[0]         
         elif qad_layer.isSymbolLayer(layer):
            rotFldName = qad_layer.get_symbolRotationFieldName(layer)

         for featureId in layerEntitySet.featureIds:
            entity.set(layer, featureId)

            # verifico se l'entità appartiene ad uno stile di quotatura
            dimEntity = QadDimStyles.getDimEntity(entity)  
            if dimEntity is None:
               if self.mirror(entity, transformedBasePt, transformedNewPt, rotFldName) == False:
                  self.plugIn.destroyEditCommand()
                  return
            else:
               found = False
               for dimElaborated in dimElaboratedList:
                  if dimElaborated == dimEntity:
                     found = True
            
               if found == False: # quota non ancora elaborata
                  dimElaboratedList.append(dimEntity)
                  if self.mirror(dimEntity, transformedBasePt, transformedNewPt, rotFldName) == False:
                     self.plugIn.destroyEditCommand()
                     return

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
   
   
   #============================================================================
   # waitForMirrorPoint
   #============================================================================
   def waitForMirrorPoint(self):
      self.step = 1
      self.plugIn.setLastPoint(self.basePt)
      # imposto il map tool
      self.getPointMapTool().firstMirrorPt = self.basePt
      self.getPointMapTool().setMode(Qad_mirror_maptool_ModeEnum.FIRST_PT_KNOWN_ASK_FOR_SECOND_PT)                                
         
      keyWords = QadMsg.translate("Command_GRIPMIRROR", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIPMIRROR", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIPMIRROR", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIPMIRROR", "eXit")

      prompt = QadMsg.translate("Command_GRIPMIRROR", "Specify second point or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" + "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto, un numero reale o enter o una parola chiave
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)      
   

   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_mirror_maptool_ModeEnum.NONE_KNOWN_ASK_FOR_FIRST_PT)
      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIPROTATE", "Specify base point: "))
   

   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
            
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entitySet.isEmpty(): # non ci sono oggetti da ruotare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPMIRROR", "\n** MIRROR **\n"))
         # si appresta ad attendere il secondo punto di specchio
         self.waitForMirrorPoint()

      #=========================================================================
      # RISPOSTA ALLA RICHIESTA SECONDO PUNTO PER SPECCHIO
      elif self.step == 1: # dopo aver atteso un punto si riavvia il comando
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  value = None
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            ctrlKey = self.getPointMapTool().ctrlKey
            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIPMIRROR", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIPMIRROR", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere il secondo punto di specchio
               self.waitForMirrorPoint()
            elif value == QadMsg.translate("Command_GRIPMIRROR", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere il secondo punto di specchio
               self.waitForMirrorPoint()
            elif value == QadMsg.translate("Command_GRIPMIRROR", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint: # se é stato inserito il secondo punto
            if qad_utils.ptNear(self.basePt, value):
               self.showMsg(QadMsg.translate("Command_GRIPMIRROR", "\nThe points must be different."))
               # si appresta ad attendere il secondo punto di specchio
               self.waitForMirrorPoint()
               return False
            
            self.secondMirrorPt.set(value.x(), value.y())

            if ctrlKey:
               self.copyEntities = True

            self.mirrorGeoms()

            if self.copyEntities == False:
               return True

            # si appresta ad attendere il secondo punto di specchio
            self.waitForMirrorPoint()

         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando

         return False

              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default "spostamento"
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            
         # si appresta ad attendere il secondo punto di specchio
         self.waitForMirrorPoint()

         return False class QadGRIPCHANGEARCRADIUSCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPCHANGEARCRADIUSCommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entity = None
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.basePt = QgsPoint()
      self.nOperationsToUndo = 0

   
   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_gripChangeArcRadius_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None

   
   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      # setta la prima entità con un grip selezionato
      self.entity = None
      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         for gripPoint in entityGripPoints.gripPoints:
            # grip point selezionato
            if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED:
               # verifico se l'entità appartiene ad uno stile di quotatura
               if entityGripPoints.entity.isDimensionComponent():
                  return False
               if entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.ARC:
                  return False
               
               self.entity = entityGripPoints.entity
               arc = entityGripPoints.entity.getQadGeom() # arco in map coordinate
               self.basePt.set(arc.center.x(), arc.center.y())
               return True
      return False
   

   #============================================================================
   # changeRadius
   #============================================================================
   def changeRadius(self, radius):
      # radius = nuovo raggio dell'arco
      if radius <= 0:
         return False
      arc = self.entity.getQadGeom()
      arc.radius = radius
      points = arc.asPolyline()
      if points is None:
         return False
      
      g = QgsGeometry.fromPolyline(points)
      f = self.entity.getFeature()      
      f.setGeometry(g)
      
      self.plugIn.beginEditCommand("Feature stretched", [self.entity.layer])
      
      if self.copyEntities == False:
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, self.entity.layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      else:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, self.entity.layer, f, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False

      self.plugIn.setLastRadius(radius)
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1

      return True


   #============================================================================
   # waitForRadius
   #============================================================================
   def waitForRadius(self):
      keyWords = QadMsg.translate("Command_GRIP", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIP", "eXit")
      prompt = QadMsg.translate("Command_GRIPCHANGEARCRADIUS", "Specify the radius or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" "eXit"
      keyWords += "_" + englishKeyWords
      # si appresta ad attendere un punto o enter o una parola chiave
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.FLOAT | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NOT_ZERO | QadInputModeEnum.NOT_NEGATIVE)
      self.step = 1
      # imposto il map tool
      self.getPointMapTool().setEntity(self.entity) # setta basePt nel centro dell'arco
      self.getPointMapTool().basePt = self.basePt
      self.getPointMapTool().setMode(Qad_gripChangeArcRadius_maptool_ModeEnum.BASE_PT_KNOWN_ASK_FOR_RADIUS_PT)


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_gripChangeArcRadius_maptool_ModeEnum.ASK_FOR_BASE_PT)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIP", "Specify base point: "))


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entity is None: # non ci sono oggetti da stirare
            return True
         self.showMsg(QadMsg.translate("Command_GRIPCHANGEARCRADIUS", "\n** RADIUS **\n"))
         # si appresta ad attendere raggio
         self.waitForRadius()
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL RAGGIO DI RACCORDO (da step = 1)
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.copyEntities == False:
                     self.skipToNextGripCommand = True
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIP", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIP", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere raggio
               self.waitForRadius()
            elif value == QadMsg.translate("Command_GRIP", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere raggio
               self.waitForRadius()
            elif value == QadMsg.translate("Command_GRIP", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint or type(value) == float: # se é stato inserito il raggio
            if type(value) == QgsPoint: # se é stato inserito il raggio con un punto
               if value == self.basePt:
                  self.showMsg(QadMsg.translate("QAD", "\nThe value must be positive and not zero."))
                  # si appresta ad attendere raggio
                  self.waitForRadius()
                  return False
                                      
               radius = qad_utils.getDistance(self.basePt, value)
            else:
               radius = value

            if ctrlKey:
               self.copyEntities = True
   
            self.changeRadius(radius)

            if self.copyEntities == False:
               return True
            # si appresta ad attendere raggio
            self.waitForRadius()
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando

         return False
              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().basePt = self.basePt
            
         # si appresta ad attendere raggio
         self.waitForRadius()

         return False class QadGRIPLENGTHENCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPLENGTHENCommandClass(self.plugIn)
   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entity = None
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.basePt = QgsPoint()
      self.nOperationsToUndo = 0
      
      self.linearObjectList = None
      self.atSubGeom = None
      self.move_startPt = None


   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):      
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_lengthen_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      # setta la prima entità con un grip selezionato
      self.entity = None
      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         for gripPoint in entityGripPoints.gripPoints:
            # grip point selezionato
            if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED:
               # verifico se l'entità appartiene ad uno stile di quotatura
               if entityGripPoints.entity.isDimensionComponent():
                  return False
               if entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.ARC and \
                  entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.LINESTRING:
                  return False
               
               # setta: self.entity, self.linearObjectList, self.atSubGeom e self.move_startPt
               self.entity = entityGripPoints.entity
               
               if self.linearObjectList is not None:
                  del self.linearObjectList
                  self.linearObjectList = None

               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(self.entity.layer, self.entity.getGeometry())
               
               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               res = False
               dummy = qad_utils.closestSegmentWithContext(gripPoint.getPoint(), geom)
               if dummy[2] is None:
                  return False
               # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
               subGeom, self.atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])               
               self.linearObjectList = qad_utils.QadLinearObjectList()

               self.linearObjectList.fromPolyline(subGeom.asPolyline())
               
               if qad_utils.getDistance(self.linearObjectList.getStartPt(), gripPoint.getPoint()) <= \
                  qad_utils.getDistance(self.linearObjectList.getEndPt(), gripPoint.getPoint()):
                  # si allunga dal punto iniziale
                  self.move_startPt = True
               else:
                  # si allunga dal punto finale
                  self.move_startPt = False

               # imposto il map tool
               if self.getPointMapTool().setInfo(self.entity, gripPoint.getPoint()) == False:
                  return False
               
               return True
      return False


   #============================================================================
   # lengthen
   #============================================================================
   def lengthen(self, point):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
                  
      # ritorna una tupla (<The squared cartesian distance>,
      #                    <minDistPoint>
      #                    <afterVertex>
      #                    <leftOf>)
      res = False
      newLinearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
         
      if self.move_startPt:
         linearObject = newLinearObjectList.getLinearObjectAt(0)
      else:
         linearObject = newLinearObjectList.getLinearObjectAt(-1)
         
      if linearObject.isSegment():
         newPt = qad_utils.getPerpendicularPointOnInfinityLine(linearObject.getStartPt(), linearObject.getEndPt(), point)
      else: # arco
         newPt = qad_utils.getPolarPointByPtAngle(linearObject.getArc().center, \
                                                  qad_utils.getAngleBy2Pts(linearObject.getArc().center, point), \
                                                  linearObject.getArc().radius)                  

      if newLinearObjectList.qty() > 1 and linearObject.isSegment():
         ang = linearObject.getTanDirectionOnStartPt()

      if self.move_startPt:
         linearObject.setStartPt(newPt)
      else:
         linearObject.setEndPt(newPt)
         
      if newLinearObjectList.qty() > 1 and linearObject.isSegment() and \
         qad_utils.TanDirectionNear(ang, linearObject.getTanDirectionOnStartPt()) == False:
         res = False
      else:
         res = True

      if res == False: # allungamento impossibile
         return False
               
      pts = newLinearObjectList.asPolyline() 
      updSubGeom = QgsGeometry.fromPolyline(pts)
               
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom)
      if updGeom is None:
         return False
      # trasformo la geometria nel crs del layer
      f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
         
      self.plugIn.beginEditCommand("Feature edited", layer)
      
      if self.copyEntities == False:
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      else:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layer, f, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      
      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1
      
      return True


   def waitForDynamicPt(self):
      keyWords = QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIP", "eXit")
      prompt = QadMsg.translate("Command_GRIPLENGTHEN", "Specify new endpoint or [{0}]: ").format(keyWords)

      englishKeyWords = "Copy" + "/" + "Undo" + "/" "eXit"
      keyWords += "_" + englishKeyWords

      # si appresta ad attendere un punto o enter o una parola chiave         
      # msg, inputType, default, keyWords, nessun controllo
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      self.step = 1
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_lengthen_maptool_ModeEnum.ASK_FOR_DYNAMIC_POINT)


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando

      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTO
      if self.step == 0: # inizio del comando
         self.waitForDynamicPt()
         return False

      #=========================================================================
      # RISPOSTA ALLA SELEZIONE OGGETTI DA MISURARE
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.copyEntities == False:
                     self.skipToNextGripCommand = True
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIP", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     

               self.waitForDynamicPt()
            elif value == QadMsg.translate("Command_GRIP", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  

               self.waitForDynamicPt()
            elif value == QadMsg.translate("Command_GRIP", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint: # se é stato selezionato un punto
            if ctrlKey:
               self.copyEntities = True
   
            self.lengthen(value)

            if self.copyEntities == False:
               return True

            self.waitForDynamicPt()
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando
                                          
         return False class QadGRIPINSERTREMOVEVERTEXCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPINSERTREMOVEVERTEXCommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entity = None
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.basePt = QgsPoint()
      self.nOperationsToUndo = 0

      self.after = True
      self.insert_mode = True
      self.vertexAt = 0
      self.firstPt = QgsPoint()
      self.linearObjectList = qad_utils.QadLinearObjectList()

   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_pedit_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   def setInsertVertexAfter_Mode(self):
      self.after = True
      self.insert_mode = True
      
   def setInsertVertexBefore_Mode(self):
      self.after = False
      self.insert_mode = True

   def setRemoveVertex_mode(self):
      self.insert_mode = False
      
      
   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      # setta la prima entità con un grip selezionato
      self.entity = None
      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         for gripPoint in entityGripPoints.gripPoints:
            # grip point selezionato
            if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED:
               # verifico se l'entità appartiene ad uno stile di quotatura
               if entityGripPoints.entity.isDimensionComponent():
                  return False
               if entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.LINESTRING:
                  return False
               
               # setta: self.entity, self.linearObjectList, self.atSubGeom
               self.entity = entityGripPoints.entity

               self.firstPt.set(gripPoint.getPoint().x(), gripPoint.getPoint().y())
               
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(self.entity.layer, self.entity.getGeometry())
               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               dummy = qad_utils.closestSegmentWithContext(self.firstPt, geom)
               if dummy[2] is not None:
                  # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
                  subGeom, self.atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
                  self.linearObjectList.fromPolyline(subGeom.asPolyline())
                  # setto il n. di vertice
                  self.vertexAt = gripPoint.nVertex
                  
                  self.getPointMapTool().setLinearObjectList(self.linearObjectList, self.entity.layer)
                  return True

      return False


   #============================================================================
   # insertVertexAt
   #============================================================================
   def insertVertexAt(self, pt):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False
      
      # faccio una copia locale
      linearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))

      if self.after: # dopo
         if self.vertexAt == linearObjectList.qty() and linearObjectList.isClosed():
            linearObjectList.insertPoint(0, pt)
         else:
            linearObjectList.insertPoint(self.vertexAt, pt)
      else: # prima
         if self.vertexAt == 0 and linearObjectList.isClosed():
            linearObjectList.insertPoint(self.linearObjectList.qty() - 1, pt)
         else:
            linearObjectList.insertPoint(self.vertexAt - 1, pt)

      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
               
      updSubGeom = QgsGeometry.fromPolyline(linearObjectList.asPolyline(tolerance2ApproxCurve))
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom)
      if updGeom is None:
         return
      # trasformo la geometria nel crs del layer
      f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
      
      self.plugIn.beginEditCommand("Feature edited", layer)
   
      if self.copyEntities == False:
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      else:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layer, f, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # removeVertexAt
   #============================================================================
   def removeVertexAt(self):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False

      # faccio una copia locale
      linearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)
            
      prevLinearObject, nextLinearObject = linearObjectList.getPrevNextLinearObjectsAtVertex(self.vertexAt)
      if prevLinearObject:
         firstPt = prevLinearObject.getStartPt()
         linearObjectList.remove(self.vertexAt - 1) # rimuovo la parte precedente
         
      if nextLinearObject:
         if prevLinearObject:
            # modifico la parte successiva
            secondPt = nextLinearObject.getEndPt()
            nextLinearObject.setSegment(firstPt, secondPt)
         else:
            linearObjectList.remove(self.vertexAt) # rimuovo la parte
      
      
      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))

      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())

      updSubGeom = QgsGeometry.fromPolyline(linearObjectList.asPolyline(tolerance2ApproxCurve))
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom)
      if updGeom is None:
         return
      # trasformo la geometria nel crs del layer
      f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
      
      self.plugIn.beginEditCommand("Feature edited", layer)

      # plugIn, layer, feature, refresh, check_validity
      if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
         self.plugIn.destroyEditCommand()
         return False

      self.plugIn.endEditCommand()


   #============================================================================
   # waitForBasePt
   #============================================================================
   def waitForBasePt(self):
      self.step = 2   
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_BASE_PT)

      # si appresta ad attendere un punto
      self.waitForPoint(QadMsg.translate("Command_GRIP", "Specify base point: "))


   #============================================================================
   # waitForNewVertex
   #============================================================================
   def waitForNewVertex(self):
      # imposto il map tool
      self.getPointMapTool().setVertexAt(self.vertexAt, self.after)
      if self.basePt is not None:
         self.getPointMapTool().firstPt = self.basePt
      self.getPointMapTool().setMode(Qad_pedit_maptool_ModeEnum.ASK_FOR_NEW_VERTEX)

      keyWords = QadMsg.translate("Command_GRIP", "Base point") + "/" + \
                 QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIP", "eXit")
      prompt = QadMsg.translate("Command_GRIPINSERTREMOVEVERTEX", "Specify the position of the new vertex or [{0}]: ").format(keyWords)

      englishKeyWords = "Base point" + "/" + "Copy" + "/" + "Undo" + "/" "eXit"
      keyWords += "_" + englishKeyWords

      # si appresta ad attendere un punto o enter o una parola chiave
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      self.step = 1


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entity is None: # non ci sono oggetti da stirare
            return True

         if self.insert_mode:
            self.showMsg(QadMsg.translate("Command_GRIPINSERTREMOVEVERTEX", "\n** ADD VERTEX **\n"))
            # si appresta ad attendere un nuovo punto
            self.waitForNewVertex()
         else:
            self.showMsg(QadMsg.translate("Command_GRIPINSERTREMOVEVERTEX", "\n** REMOVE VERTEX **\n"))
            self.removeVertexAt()
            return True
         
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUOVO VERTICE DA INSERIRE (da step = 1)
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.copyEntities == False:
                     self.skipToNextGripCommand = True
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIP", "Base point") or value == "Base point":
               # si appresta ad attendere il punto base
               self.waitForBasePt()
            elif value == QadMsg.translate("Command_GRIP", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere un nuovo punto
               self.waitForNewVertex()
            elif value == QadMsg.translate("Command_GRIP", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere un nuovo punto
               self.waitForNewVertex()
            elif value == QadMsg.translate("Command_GRIP", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint:
            if ctrlKey:
               self.copyEntities = True
   
            offsetX = value.x() - self.basePt.x()
            offsetY = value.y() - self.basePt.y()
            value.set(self.firstPt.x() + offsetX, self.firstPt.y() + offsetY)
            self.insertVertexAt(value)

            if self.copyEntities == False:
               return True
            # si appresta ad attendere un nuovo punto
            self.waitForNewVertex()
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando

         return False
              
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA PUNTO BASE (da step = 1)
      elif self.step == 2: # dopo aver atteso un punto
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  pass # opzione di default
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == QgsPoint: # se é stato inserito il punto base
            self.basePt.set(value.x(), value.y())
            # imposto il map tool
            self.getPointMapTool().basePt = self.basePt
            self.getPointMapTool().firstPt = self.basePt
            
         # si appresta ad attendere un nuovo punto
         self.waitForNewVertex()

         return False class QadGRIPARCLINECONVERTCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadGRIPARCLINECONVERTCommandClass(self.plugIn)

   
   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.entity = None
      self.skipToNextGripCommand = False
      self.copyEntities = False
      self.nOperationsToUndo = 0
      self.basePt = QgsPoint()

      self.lineToArc = True
      self.partAt = 0
      self.linearObjectList = qad_utils.QadLinearObjectList() # in map coordinate

   def __del__(self):
      QadCommandClass.__del__(self)


   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if (self.plugIn is not None):
         if self.PointMapTool is None:
            self.PointMapTool = Qad_gripLineToArcConvert_maptool(self.plugIn)
         return self.PointMapTool
      else:
         return None


   def setLineToArcConvert_Mode(self):
      self.lineToArc = True
      
   def setArcToLineConvert_Mode(self):
      self.lineToArc = False


   #============================================================================
   # setSelectedEntityGripPoints
   #============================================================================
   def setSelectedEntityGripPoints(self, entitySetGripPoints):
      # lista delle entityGripPoint con dei grip point selezionati
      # setta la prima entità con un grip selezionato
      self.entity = None
      for entityGripPoints in entitySetGripPoints.entityGripPoints:
         for gripPoint in entityGripPoints.gripPoints:
            # grip point selezionato
            if gripPoint.getStatus() == qad_grip.QadGripStatusEnum.SELECTED and \
               (gripPoint.gripType == qad_grip.QadGripPointTypeEnum.LINE_MID_POINT or \
                gripPoint.gripType == qad_grip.QadGripPointTypeEnum.ARC_MID_POINT):
               # verifico se l'entità appartiene ad uno stile di quotatura
               if entityGripPoints.entity.isDimensionComponent():
                  return False
               if entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.LINESTRING and \
                  entityGripPoints.entity.getEntityType() != QadEntityGeomTypeEnum.ARC:
                  return False
               
               # setta: self.entity, self.linearObjectList, self.atSubGeom
               self.entity = entityGripPoints.entity

               firstPt = QgsPoint(gripPoint.getPoint())
               # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
               geom = self.layerToMapCoordinates(self.entity.layer, self.entity.getGeometry())
               # ritorna una tupla (<The squared cartesian distance>,
               #                    <minDistPoint>
               #                    <afterVertex>
               #                    <leftOf>)
               dummy = qad_utils.closestSegmentWithContext(firstPt, geom)
               if dummy[2] is not None:
                  # ritorna la sotto-geometria al vertice <atVertex> e la sua posizione nella geometria (0-based)
                  subGeom, self.atSubGeom = qad_utils.getSubGeomAtVertex(geom, dummy[2])
                  self.linearObjectList.fromPolyline(subGeom.asPolyline())
                  # setto il n. della parte
                  self.partAt = gripPoint.nVertex
                  
                  self.getPointMapTool().setLinearObjectList(self.linearObjectList, self.entity.layer, self.partAt)
                  
                  return True

      return False


   #============================================================================
   # convertLineToArc
   #============================================================================
   def convertLineToArc(self, pt):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False
      
      # faccio una copia locale
      linearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))
      linearObject = linearObjectList.getLinearObjectAt(self.partAt)
      if linearObject.isArc(): # se è già arco
         return False
      
      startPt = linearObject.getStartPt()
      endPt = linearObject.getEndPt()
      arc = QadArc()
      if arc.fromStartSecondEndPts(startPt, pt, endPt) == False:
         return
      if qad_utils.ptNear(startPt, arc.getStartPt()):
         linearObject.setArc(arc, False) # arco non inverso
      else:
         linearObject.setArc(arc, True) # arco inverso
         
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())

      updSubGeom = QgsGeometry.fromPolyline(linearObjectList.asPolyline(tolerance2ApproxCurve))
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom)
      if updGeom is None:
         return
      # trasformo la geometria nel crs del layer
      f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
      
      self.plugIn.beginEditCommand("Feature edited", layer)
   
      if self.copyEntities == False:
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      else:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layer, f, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # convertArcToLine
   #============================================================================
   def convertArcToLine(self):
      layer = self.entity.layer
      f = self.entity.getFeature()
      if f is None: # non c'è più la feature
         return False
      
      # faccio una copia locale
      linearObjectList = qad_utils.QadLinearObjectList(self.linearObjectList)

      tolerance2ApproxCurve = QadVariables.get(QadMsg.translate("Environment variables", "TOLERANCE2APPROXCURVE"))

      linearObject = linearObjectList.getLinearObjectAt(self.partAt)
      if linearObject.isSegment(): # se è già segmento retto
         return False
      
      linearObject.setSegment(linearObject.getStartPt(), linearObject.getEndPt())
         
      # trasformo la geometria nel crs del canvas per lavorare con coordinate piane xy
      geom = self.layerToMapCoordinates(layer, self.entity.getGeometry())
               
      updSubGeom = QgsGeometry.fromPolyline(linearObjectList.asPolyline(tolerance2ApproxCurve))
      updGeom = qad_utils.setSubGeom(geom, updSubGeom, self.atSubGeom)
      if updGeom is None:
         return
      # trasformo la geometria nel crs del layer
      f.setGeometry(self.mapToLayerCoordinates(layer, updGeom))
      
      self.plugIn.beginEditCommand("Feature edited", layer)
   
      if self.copyEntities == False:
         # plugIn, layer, feature, refresh, check_validity
         if qad_layer.updateFeatureToLayer(self.plugIn, layer, f, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False
      else:
         # plugIn, layer, features, coordTransform, refresh, check_validity
         if qad_layer.addFeatureToLayer(self.plugIn, layer, f, None, False, False) == False:
            self.plugIn.destroyEditCommand()
            return False

      self.plugIn.endEditCommand()
      self.nOperationsToUndo = self.nOperationsToUndo + 1


   #============================================================================
   # waitForConvertToArc
   #============================================================================
   def waitForConvertToArc(self):
      # imposto il map tool
      self.getPointMapTool().setMode(Qad_gripLineToArcConvert_maptool_ModeEnum.START_END_PT_KNOWN_ASK_FOR_SECOND_PT)

      keyWords = QadMsg.translate("Command_GRIP", "Copy") + "/" + \
                 QadMsg.translate("Command_GRIP", "Undo") + "/" + \
                 QadMsg.translate("Command_GRIP", "eXit")
      prompt = QadMsg.translate("Command_GRIPARCLINECONVERT", "Specify the arc middle point or [{0}]: ").format(keyWords)

      englishKeyWords = "Copy" + "/" + "Undo" + "/" "eXit"
      keyWords += "_" + englishKeyWords

      # si appresta ad attendere un punto o enter o una parola chiave
      # msg, inputType, default, keyWords, valori positivi
      self.waitFor(prompt, \
                   QadInputTypeEnum.POINT2D | QadInputTypeEnum.KEYWORDS, \
                   None, \
                   keyWords, QadInputModeEnum.NONE)
      self.step = 1


   #============================================================================
   # run
   #============================================================================
   def run(self, msgMapTool = False, msg = None):
      if self.plugIn.canvas.mapSettings().destinationCrs().geographicFlag():
         self.showMsg(QadMsg.translate("QAD", "\nThe coordinate reference system of the project must be a projected coordinate system.\n"))
         return True # fine comando
     
      #=========================================================================
      # RICHIESTA SELEZIONE OGGETTI
      if self.step == 0: # inizio del comando
         if self.entity is None: # non ci sono oggetti da stirare
            return True

         if self.lineToArc:
            self.showMsg(QadMsg.translate("Command_GRIPINSERTREMOVEVERTEX", "\n** CONVERT TO ARC **\n"))
            # si appresta ad attendere un punto per definire l'arco
            self.waitForConvertToArc()
         else:
            self.showMsg(QadMsg.translate("Command_GRIPINSERTREMOVEVERTEX", "\n** CONVERT TO LINE **\n"))
            self.convertArcToLine()
            return True
         
         return False
      
      #=========================================================================
      # RISPOSTA ALLA RICHIESTA DEL NUOVO PUNTO PER DEFINIRE UN ARCO (da step = 1)
      elif self.step == 1:
         ctrlKey = False
         if msgMapTool == True: # il punto arriva da una selezione grafica
            # la condizione seguente si verifica se durante la selezione di un punto
            # é stato attivato un altro plugin che ha disattivato Qad
            # quindi stato riattivato il comando che torna qui senza che il maptool
            # abbia selezionato un punto            
            if self.getPointMapTool().point is None: # il maptool é stato attivato senza un punto
               if self.getPointMapTool().rightButton == True: # se usato il tasto destro del mouse
                  if self.copyEntities == False:
                     self.skipToNextGripCommand = True
                  return True # fine comando
               else:
                  self.setMapTool(self.getPointMapTool()) # riattivo il maptool
                  return False

            value = self.getPointMapTool().point
            ctrlKey = self.getPointMapTool().ctrlKey
         else: # il punto arriva come parametro della funzione
            value = msg

         if type(value) == unicode:
            if value == QadMsg.translate("Command_GRIP", "Copy") or value == "Copy":
               # Copia entità lasciando inalterate le originali
               self.copyEntities = True                     
               # si appresta ad attendere un punto per definire l'arco
               self.waitForConvertToArc()
            elif value == QadMsg.translate("Command_GRIP", "Undo") or value == "Undo":
               if self.nOperationsToUndo > 0: 
                  self.nOperationsToUndo = self.nOperationsToUndo - 1
                  self.plugIn.undoEditCommand()
               else:
                  self.showMsg(QadMsg.translate("QAD", "\nThe command has been canceled."))                  
               # si appresta ad attendere un punto per definire l'arco
               self.waitForConvertToArc()
            elif value == QadMsg.translate("Command_GRIP", "eXit") or value == "eXit":
               return True # fine comando
         elif type(value) == QgsPoint:
            if ctrlKey:
               self.copyEntities = True
   
            self.convertLineToArc(value)

            if self.copyEntities == False:
               return True
            # si appresta ad attendere un punto per definire l'arco
            self.waitForConvertToArc()
         else:
            if self.copyEntities == False:
               self.skipToNextGripCommand = True
            return True # fine comando

         return False class QadMsgClass():
   def __init__(self):
   def translate(self, context, sourceText, disambiguation = None, encoding = QCoreApplication.UnicodeUTF8, n = -1):
def qadShowPluginHelp(section = "", filename = "index", packageName = None):
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qad_variables import *
from qad_rubberband import *
from qad_getpoint import *
from qad_generic_cmd import QadCommandClass
from qad_entity import *
from qad_ssget_cmd import QadSSGetClass
from qad_grip import *
from qad_stretch_cmd import QadGRIPSTRETCHCommandClass
from qad_move_cmd import QadGRIPMOVECommandClass
from qad_rotate_cmd import QadGRIPROTATECommandClass
from qad_scale_cmd import QadGRIPSCALECommandClass
from qad_mirror_cmd import QadGRIPMIRRORCommandClass
from qad_arc_cmd import QadGRIPCHANGEARCRADIUSCommandClass
from qad_lengthen_cmd import QadGRIPLENGTHENCommandClass
from qad_pedit_cmd import QadGRIPINSERTREMOVEVERTEXCommandClass, QadGRIPARCLINECONVERTCommandClass
from qad_msg import QadMsg
import qad_utils
   def popup(self, pos, action = None):
      newPos = QPoint(pos.x() + self.offset, pos.y() + self.offset)
      QMenu.popup(self, newPos, action)
   
#    def leaveEvent(self, event):
#       if event.pos().x() < -1 * self.offset or event.pos().y() < -1 * self.offset:
#          self.hide()
     #self.hide()

   def mouseMoveEvent(self, event):
      x = event.pos().x()
      y = event.pos().y()
      if x < -1 * self.offset or y < -1 * self.offset or \
         x > self.width() or y > self.height():
         self.hide()
      else:
         QMenu.mouseMoveEvent(self, event)

#             newPos = self.parentWidget().mapFromGlobal(event.globalPos())
#             newMouseEvent = QMouseEvent(QEvent.MouseMove, newPos, Qt.NoButton, event.buttons(), event.modifiers())
#             self.parentWidget().mouseMoveEvent(newMouseEvent)


# Classe che gestisce il comando di selezione quando QAD è in stato di quiete
class QadVirtualSelCommandClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadVirtualSelCommandClass(self.plugIn)
   
   def getName(self):
      return "QadVirtualSelCommandClass"

   def __init__(self, plugIn):
      QadCommandClass.__init__(self, plugIn)
      self.SSGetClass = QadSSGetClass(plugIn)
      self.SSGetClass.entitySet.set(plugIn.tool.entitySet) # da usare solo con QadMapTool
      self.SSGetClass.exitAfterSelection = True
      self.SSGetClass.step = 1
   
   def __del__(self):
      QadCommandClass.__del__(self)
      del self.SSGetClass
      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      return self.SSGetClass.getPointMapTool(drawMode)

   def run(self, msgMapTool = False, msg = None):
      res = self.SSGetClass.run(msgMapTool, msg)
      if res == True:
         self.plugIn.tool.entitySet.set(self.SSGetClass.entitySet) # da usare solo con QadMapTool
         self.plugIn.tool.entitySet.selectOnLayer()
      return res


#===============================================================================
# QadVirtualGripCommandsEnum class.   
#===============================================================================
class QadVirtualGripCommandsEnum():
   NONE            = 0
   STRECTH         = 1
   MOVE            = 2
   ROTATE          = 3
   SCALE           = 4
   MIRROR          = 5
   LENGTHEN        = 6
   ADD_VERTEX      = 7
   REMOVE_VERTEX   = 8
   LINE_TO_ARC     = 9
   ARC_TO_LINE     = 10
   CHANGE_RADIUS   = 11
   ADD_VERTEX_BEFORE = 12


# Classe che gestisce i comando disponibili sui grip quando QAD è in stato di quiete
class QadVirtualGripCommandsClass(QadCommandClass):

   def instantiateNewCmd(self):
      """ istanzia un nuovo comando dello stesso tipo """
      return QadVirtualGripCommandsClass(self.plugIn)
   
   def getName(self):
      return "QadVirtualGripCommandsClass"

   def __init__(self, plugIn):      
      QadCommandClass.__init__(self, plugIn)
      self.commandNum = QadVirtualGripCommandsEnum.NONE
      self.currentCommand = None
      self.entitySetGripPoints = None
      self.basePt = QgsPoint()
   
   def __del__(self):
      QadCommandClass.__del__(self)
      del self.currentCommand

      
   def getPointMapTool(self, drawMode = QadGetPointDrawModeEnum.NONE):
      if self.currentCommand is not None:
         return self.currentCommand.getPointMapTool(drawMode)
      else:
         return None


   def getCurrentContextualMenu(self):
      if self.currentCommand is not None:
         return self.currentCommand.getCurrentContextualMenu()
      else:
         return None


   def getCommand(self):
      if self.commandNum == QadVirtualGripCommandsEnum.STRECTH:
         return QadGRIPSTRETCHCommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.MOVE:
         return QadGRIPMOVECommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.ROTATE:
         return QadGRIPROTATECommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.SCALE:
         return QadGRIPSCALECommandClass(self.plugIn)
      elif self.commandNum == QadVirtualGripCommandsEnum.MIRROR:

         return QadGRIPMIRRORCommandClass(self.plugIn)